tsx自定义Timeline 时间线
效果
示例
<time-line
v-for="(item, index) in data.lifecycle"
:key="index"
:type="getType(item.type)"
:subTitle="item.subTitle"
:subTitleSyle="{ color: getColor(item.type) }"
:title="item.title"
:timestamp="getTimestamp(item.timestamp)"
>
{{ item.content }}
</time-line>
index.tsx
import { defineComponent, computed } from 'vue'
const style = require('./index.module.less')
export default defineComponent({
name: 'timeline',
props: {
type: {
type: String,
default: ''
},
title: {
type: String,
default: ''
},
subTitle: {
type: String,
default: ''
},
timestamp: {
type: String,
default: ''
},
subTitleClassName: {
type: String,
default: ''
},
titleClassName: {
type: String,
default: ''
},
timestampClassName: {
type: String,
default: ''
},
titleSyle:{
type:[String,Object],
default: ''
},
subTitleSyle:{
type:[String,Object],
default: ''
},
timestampSyle:{
type:[String,Object],
default: ''
}
},
setup(props, { emit, slots }) {
return () => {
return (
<div class={style['time-line']}>
<div class={style['line-box']}>
<div class={[style.note, style['bg-color'], style[props.type]].join(' ')} />
<div class={[style.line, style['bg-color'], style[props.type]].join(' ')} />
</div>
<div style="flex: 1">
{slots.dot ? (
slots.dot()
) : (
<div class={style['content-box']}>
<div class={style.top}>
<div style="display:flex;flex:1;">
{props.title ? slots.title ? slots.title() : <div class={[style.title,props.titleClassName].join(' ')} style={props.titleSyle}>{props.title}</div> : null}
{props.subTitle ? (
slots.subTitle ? (
slots.subTitle()
) : (
<div style={props.subTitleSyle} class={[style['sub-title'],props.subTitleClassName].join(' ')}>{props.subTitle}</div>
)
) : null}
</div>
{slots.timestamp ? slots.timestamp() : <div style={props.timestampClassName} class={[style.timestamp,props.timestampClassName].join(' ')}>{props.timestamp}</div>}
</div>
<div class={style.content}>{slots.default ? slots.default() : null}</div>
</div>
)}
</div>
</div>
)
}
}
})
index.module.less
.time-line {
display: flex;
.line-box {
display: flex;
width: 10px;
position: relative;
flex-direction: column;
align-items: center;
justify-content: center;
.bg-color {
background: #D9D9D9;
&.error {
background: #F15643;
}
&.success {
background: #02BE91;
}
&.warring {
background: #FFAB00;
}
}
.line {
width: 1px;
height: 100%;
}
.note {
width: 10px;
position: absolute;
top: 5px;
height: 10px;
border-radius: 5px;
}
}
.content-box {
margin-left: 8px;
.top {
display: flex;
align-items: center;
.title {
font-size: 15px;
font-weight: bold;
margin-right: 8px;
color: rgba(22, 24, 23, 0.9);
line-height: 18px;
}
.sub-title {
font-size: 14px;
font-weight: 400;
color: #02BE91;
line-height: 16px;
}
.timestamp {
font-size: 14px;
font-weight: 400;
color: rgba(22, 24, 23, 0.4);
line-height: 16px;
}
}
.content {
margin-top: 8px;
font-size: 14px;
font-weight: 400;
color: rgba(22, 24, 23, 0.65);
line-height: 16px;
min-height: 50px;
padding-bottom: 16px;
}
}
}