You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
316 lines
7.6 KiB
316 lines
7.6 KiB
<template> |
|
<view class="u-steps-item" ref="u-steps-item" :class="[`u-steps-item--${parentData.direction}`]"> |
|
<view class="u-steps-item__line" v-if="index + 1 < childLength" |
|
:class="[`u-steps-item__line--${parentData.direction}`]" :style="[lineStyle]"></view> |
|
<view class="u-steps-item__wrapper" |
|
:class="[`u-steps-item__wrapper--${parentData.direction}`, parentData.dot && `u-steps-item__wrapper--${parentData.direction}--dot`]"> |
|
<slot name="icon"> |
|
<view class="u-steps-item__wrapper__dot" v-if="parentData.dot" :style="{ |
|
backgroundColor: statusColor |
|
}"> |
|
|
|
</view> |
|
<view class="u-steps-item__wrapper__icon" v-else-if="parentData.activeIcon || parentData.inactiveIcon"> |
|
<u-icon :name="index <= parentData.current ? parentData.activeIcon : parentData.inactiveIcon" |
|
:size="iconSize" |
|
:color="index <= parentData.current ? parentData.activeColor : parentData.inactiveColor"> |
|
</u-icon> |
|
</view> |
|
<view v-else :style="{ |
|
backgroundColor: statusClass === 'process' ? parentData.activeColor : 'transparent', |
|
borderColor: statusColor |
|
}" class="u-steps-item__wrapper__circle"> |
|
<text v-if="statusClass === 'process' || statusClass === 'wait'" |
|
class="u-steps-item__wrapper__circle__text" :style="{ |
|
color: index == parentData.current ? '#ffffff' : parentData.inactiveColor |
|
}">{{ index + 1}}</text> |
|
<u-icon v-else :color="statusClass === 'error' ? 'error' : parentData.activeColor" size="12" |
|
:name="statusClass === 'error' ? 'close' : 'checkmark'"></u-icon> |
|
</view> |
|
</slot> |
|
</view> |
|
<view class="u-steps-item__content" :class="[`u-steps-item__content--${parentData.direction}`]" |
|
:style="[contentStyle]"> |
|
<u--text :text="title" :type="parentData.current == index ? 'main' : 'content'" lineHeight="20px" |
|
:size="parentData.current == index ? 14 : 13"></u--text> |
|
<slot name="desc"> |
|
<u--text :text="desc" type="tips" size="12"></u--text> |
|
</slot> |
|
</view> |
|
<!-- <view |
|
class="u-steps-item__line" |
|
v-if="showLine && parentData.direction === 'column'" |
|
:class="[`u-steps-item__line--${parentData.direction}`]" |
|
:style="[lineStyle]" |
|
></view> --> |
|
</view> |
|
</template> |
|
|
|
<script> |
|
import props from './props.js'; |
|
// #ifdef APP-NVUE |
|
const dom = uni.requireNativePlugin('dom') |
|
// #endif |
|
/** |
|
* StepsItem 步骤条的子组件 |
|
* @description 本组件需要和u-steps配合使用 |
|
* @tutorial https://uviewui.com/components/steps.html |
|
* @property {String} title 标题文字 |
|
* @property {String} current 描述文本 |
|
* @property {String | Number} iconSize 图标大小 (默认 17 ) |
|
* @property {Boolean} error 当前步骤是否处于失败状态 (默认 false ) |
|
* @example <u-steps current="0"><u-steps-item title="已出库" desc="10:35" ></u-steps-item></u-steps> |
|
*/ |
|
export default { |
|
name: 'u-steps-item', |
|
mixins: [uni.$u.mpMixin, uni.$u.mixin, props], |
|
data() { |
|
return { |
|
index: 0, |
|
childLength: 0, |
|
showLine: false, |
|
size: { |
|
height: 0, |
|
width: 0 |
|
}, |
|
parentData: { |
|
direction: 'row', |
|
current: 0, |
|
activeColor: '', |
|
inactiveColor: '', |
|
activeIcon: '', |
|
inactiveIcon: '', |
|
dot: false |
|
} |
|
} |
|
}, |
|
watch: { |
|
'parentData'(newValue, oldValue) { |
|
} |
|
}, |
|
created() { |
|
this.init() |
|
}, |
|
computed: { |
|
lineStyle() { |
|
const style = {} |
|
if (this.parentData.direction === 'row') { |
|
style.width = this.size.width + 'px' |
|
style.left = this.size.width / 2 + 'px' |
|
} else { |
|
style.height = this.size.height + 'px' |
|
// style.top = this.size.height / 2 + 'px' |
|
} |
|
style.backgroundColor = this.parent.children?.[this.index + 1]?.error ? uni.$u.color.error : this.index < |
|
this |
|
.parentData |
|
.current ? this.parentData.activeColor : this.parentData.inactiveColor |
|
return style |
|
}, |
|
statusClass() { |
|
const { |
|
index, |
|
error |
|
} = this |
|
const { |
|
current |
|
} = this.parentData |
|
if (current == index) { |
|
return error === true ? 'error' : 'process' |
|
} else if (error) { |
|
return 'error' |
|
} else if (current > index) { |
|
return 'finish' |
|
} else { |
|
return 'wait' |
|
} |
|
}, |
|
statusColor() { |
|
let color = '' |
|
switch (this.statusClass) { |
|
case 'finish': |
|
color = this.parentData.activeColor |
|
break |
|
case 'error': |
|
color = uni.$u.color.error |
|
break |
|
case 'process': |
|
color = this.parentData.dot ? this.parentData.activeColor : 'transparent' |
|
break |
|
default: |
|
color = this.parentData.inactiveColor |
|
break |
|
} |
|
return color |
|
}, |
|
contentStyle() { |
|
const style = {} |
|
if (this.parentData.direction === 'column') { |
|
style.marginLeft = this.parentData.dot ? '2px' : '6px' |
|
style.marginTop = this.parentData.dot ? '0px' : '6px' |
|
} else { |
|
style.marginTop = this.parentData.dot ? '2px' : '6px' |
|
style.marginLeft = this.parentData.dot ? '2px' : '6px' |
|
} |
|
|
|
return style |
|
} |
|
}, |
|
mounted() { |
|
this.parent && this.parent.updateFromChild() |
|
uni.$u.sleep().then(() => { |
|
this.getStepsItemRect() |
|
}) |
|
}, |
|
methods: { |
|
init() { |
|
// 初始化数据 |
|
this.updateParentData() |
|
if (!this.parent) { |
|
return uni.$u.error('u-steps-item必须要搭配u-steps组件使用') |
|
} |
|
this.index = this.parent.children.indexOf(this) |
|
this.childLength = this.parent.children.length |
|
}, |
|
updateParentData() { |
|
// 此方法在mixin中 |
|
this.getParentData('u-steps') |
|
}, |
|
// 父组件数据发生变化 |
|
updateFromParent() { |
|
this.init() |
|
}, |
|
// 获取组件的尺寸,用于设置横线的位置 |
|
getStepsItemRect() { |
|
// #ifndef APP-NVUE |
|
this.$uGetRect('.u-steps-item').then(size => { |
|
this.size = size |
|
}) |
|
// #endif |
|
|
|
// #ifdef APP-NVUE |
|
dom.getComponentRect(this.$refs['u-steps-item'], res => { |
|
const { |
|
size |
|
} = res |
|
this.size = size |
|
}) |
|
// #endif |
|
} |
|
} |
|
} |
|
</script> |
|
|
|
<style lang="scss" scoped> |
|
@import "../../libs/css/components.scss"; |
|
|
|
.u-steps-item { |
|
flex: 1; |
|
@include flex; |
|
|
|
&--row { |
|
flex-direction: column; |
|
align-items: center; |
|
position: relative; |
|
} |
|
|
|
&--column { |
|
position: relative; |
|
flex-direction: row; |
|
justify-content: flex-start; |
|
padding-bottom: 5px; |
|
} |
|
|
|
&__wrapper { |
|
@include flex; |
|
justify-content: center; |
|
align-items: center; |
|
position: relative; |
|
background-color: #fff; |
|
|
|
&--column { |
|
width: 20px; |
|
height: 32px; |
|
|
|
&--dot { |
|
height: 20px; |
|
width: 20px; |
|
} |
|
} |
|
|
|
&--row { |
|
width: 32px; |
|
height: 20px; |
|
|
|
&--dot { |
|
width: 20px; |
|
height: 20px; |
|
} |
|
} |
|
|
|
&__circle { |
|
width: 20px; |
|
height: 20px; |
|
/* #ifndef APP-NVUE */ |
|
box-sizing: border-box; |
|
flex-shrink: 0; |
|
/* #endif */ |
|
border-radius: 100px; |
|
border-width: 1px; |
|
border-color: $u-tips-color; |
|
border-style: solid; |
|
@include flex(row); |
|
align-items: center; |
|
justify-content: center; |
|
transition: background-color 0.3s; |
|
|
|
&__text { |
|
color: $u-tips-color; |
|
font-size: 11px; |
|
@include flex(row); |
|
align-items: center; |
|
justify-content: center; |
|
text-align: center; |
|
line-height: 11px; |
|
} |
|
} |
|
|
|
&__dot { |
|
width: 10px; |
|
height: 10px; |
|
border-radius: 100px; |
|
background-color: $u-content-color; |
|
} |
|
} |
|
|
|
&__content { |
|
@include flex; |
|
flex: 1; |
|
|
|
&--row { |
|
flex-direction: column; |
|
align-items: center; |
|
} |
|
|
|
&--column { |
|
flex-direction: column; |
|
margin-left: 6px; |
|
} |
|
} |
|
|
|
&__line { |
|
position: absolute; |
|
background: $u-tips-color; |
|
|
|
&--row { |
|
top: 10px; |
|
height: 1px; |
|
} |
|
|
|
&--column { |
|
width: 1px; |
|
left: 10px; |
|
} |
|
} |
|
} |
|
</style>
|
|
|