311 lines
9.4 KiB
Vue
311 lines
9.4 KiB
Vue
<template>
|
||
<view class="tm-timeline">
|
||
|
||
<block v-if="model=='center'">
|
||
<block v-for="(item,index) in listData" :key="index">
|
||
<view v-if="(index+1)%2" class="tm-timeline-item " >
|
||
<view :style="{
|
||
width: bwi(item)+'px',
|
||
height: bwi(item)+'px'
|
||
}" :class="[item['icon']?'pa-4':'',item.color?item.color:color_tmeme,`shadow-${item.color?item.color:color_tmeme}-4`,black_tmeme?'bk':'']" class=" flex-center rounded tm-timeline-jidian border-white-a-2">
|
||
<tm-icons style="line-height: 0;" dense v-if="item.icon" color="white" :size="item.iconSize||24" :name="item.icon"></tm-icons>
|
||
</view>
|
||
<view class=" tm-timeline-item-content relative">
|
||
<view :class="[`text-${(item.color?item.color:color_tmeme)}`]" v-if="item.time" class="tm-timeline-item-right pr-36 text-weight-b text-size-n text-align-right">
|
||
{{item.time}}
|
||
</view>
|
||
<!-- <tm-divider :vertical="true" :width="4" :height="100"></tm-divider> -->
|
||
<view :class="[`border-${item.borderColor?item.borderColor:borderColor}-l-1`,black_tmeme?'bk':'']" class="tm-timeline-item-right pl-36 ">
|
||
<view v-if="item.title" class="mb-12 text-align-left">
|
||
<text class="text-weight-b text-size-n" :class="[`text-${(item.color?item.color:color_tmeme)}`]">{{item.title}}</text>
|
||
</view>
|
||
<view class="text-align-left pb-24">
|
||
<text class="text-size-s text-grey-darken-1">
|
||
{{item.content}}
|
||
</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
</view>
|
||
<view v-if="(index+1)%2==0" class="tm-timeline-item ">
|
||
<view :style="{
|
||
width: bwi(item)+'px',
|
||
height: bwi(item)+'px'
|
||
}" :class="[item['icon']?'pa-4':'',item.color?item.color:color_tmeme,`shadow-${item.color?item.color:color_tmeme}-4`,black_tmeme?'bk':'']" class="flex-center rounded tm-timeline-jidian border-white-a-2">
|
||
<tm-icons style="line-height: 0;" dense v-if="item.icon" color="white" :size="item.iconSize||24" :name="item.icon"></tm-icons>
|
||
</view>
|
||
<view class=" tm-timeline-item-content relative">
|
||
<view :class="[index!==listData.length-1?(`border-${item.borderColor?item.borderColor:borderColor}-r-1`):'',black_tmeme?'bk':'']" class="tm-timeline-item-left pr-36 ">
|
||
<view v-if="item.title" class="mb-12 text-align-right">
|
||
<text class="text-weight-b text-size-n" :class="[`text-${(item.color?item.color:color_tmeme)}`]">{{item.title}}</text>
|
||
</view>
|
||
<view class="text-align-right pb-24">
|
||
<text class="text-size-s text-grey-darken-1">
|
||
{{item.content}}
|
||
</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="item.time" :class="[`text-${(item.color?item.color:color_tmeme)}`]" class="tm-timeline-item-right pl-36 text-weight-b text-size-n ">
|
||
{{item.time}}
|
||
</view>
|
||
</view>
|
||
|
||
</view>
|
||
|
||
</block>
|
||
</block>
|
||
<block v-if="model=='left'">
|
||
<block v-for="(item,index) in listData" :key="index">
|
||
<view class="tm-timeline-item tm-timeline-item--leftDir">
|
||
<view style="width: 160upx;">
|
||
<view :style="{
|
||
width: bwi(item)+'px',
|
||
height: bwi(item)+'px'
|
||
}" :class="[item['icon']?'pa-4':'',item.color?item.color:color_tmeme,`shadow-${item.color?item.color:color_tmeme}-4`,black_tmeme?'bk':'']" class="flex-center rounded tm-timeline-jidian border-white-a-2">
|
||
<tm-icons style="line-height: 0;" dense v-if="item.icon" color="white" :size="item.iconSize||24" :name="item.icon"></tm-icons>
|
||
</view>
|
||
<view :style="{
|
||
marginTop:'-'+botop(item)+'px'
|
||
}" :class="[index!==listData.length-1?'tm-timeline-item-boder':'',`${item.borderColor?item.borderColor:borderColor}`,black_tmeme?'bk':'']"></view>
|
||
</view>
|
||
<view class=" tm-timeline-item-content relative">
|
||
|
||
<view class="tm-timeline-item-left ">
|
||
<slot name="content" :data="item">
|
||
<view v-if="item.time" :class="['text-'+(item.color?item.color:color_tmeme)]" class="mb-0 tm-timeline-item-right text-size-s ">
|
||
{{item.time}}
|
||
</view>
|
||
<view v-if="item.title" class="mb-12 text-align-left">
|
||
<text :class="['text-'+(item.color?item.color:color_tmeme)]" class="text-weight-b text-size-n ">{{item.title}}</text>
|
||
</view>
|
||
<view class="text-align-left pb-24 mb-32">
|
||
<text class="text-size-s text-grey-darken-1">
|
||
{{item.content}}
|
||
</text>
|
||
</view>
|
||
</slot>
|
||
</view>
|
||
|
||
|
||
</view>
|
||
|
||
</view>
|
||
|
||
</block>
|
||
</block>
|
||
<block v-if="model=='right'">
|
||
<block v-for="(item,index) in listData" :key="index">
|
||
<view class="tm-timeline-item tm-timeline-item--leftDir endright">
|
||
|
||
<view class=" tm-timeline-item-content relative">
|
||
|
||
<view class="tm-timeline-item-left ">
|
||
<view v-if="item.time" :class="[`text-${(item.color?item.color:color_tmeme)}`]" class="mb-0 tm-timeline-item-right text-size-s text-align-right">
|
||
{{item.time}}
|
||
</view>
|
||
<view v-if="item.title" class="mb-12 text-align-right">
|
||
<text :class="[`text-${(item.color?item.color:color_tmeme)}`]" class="text-weight-b text-size-n ">{{item.title}}</text>
|
||
</view>
|
||
<view class="text-align-right pb-24 mb-32">
|
||
<text class="text-size-s text-grey-darken-1">
|
||
{{item.content}}
|
||
</text>
|
||
</view>
|
||
</view>
|
||
|
||
|
||
</view>
|
||
<view style="width: 140upx;">
|
||
<view :style="{
|
||
width: bwi(item)+'px',
|
||
height: bwi(item)+'px'
|
||
}" :class="[item['icon']?'pa-4':'',item.color?item.color:color_tmeme,`shadow-${item.color?item.color:color_tmeme}-4`,black_tmeme?'bk':'']" class="flex-center rounded tm-timeline-jidian border-white-a-2">
|
||
<tm-icons style="line-height: 0;" dense v-if="item.icon" color="white" :size="item.iconSize||24" :name="item.icon"></tm-icons>
|
||
</view>
|
||
<view :style="{
|
||
marginTop:'-'+botop(item)+'px'
|
||
}" :class="[index!==listData.length-1?'tm-timeline-item-boder':'',`${item.borderColor?item.borderColor:borderColor}`,black_tmeme?'bk':'']"></view>
|
||
</view>
|
||
</view>
|
||
|
||
</block>
|
||
</block>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
/**
|
||
* timeline 时间轴
|
||
* @property {Boolean} reverse = [] 默认:false ,是否反转数据。
|
||
* @property {String} border-color = [] 默认:grey-lighten-2 ,默认线的颜色。
|
||
* @property {String} color = [] 默认:primary ,认主题和节点颜色如果。
|
||
* @property {Number} size = [] 默认:32 ,默认的节点大小,单位upx
|
||
* @property {String} model = [left|center|right] 默认:center ,时间轴的方向。
|
||
* @property {Array} list = [] 默认:[] ,数据。{
|
||
title:'',
|
||
content:'我是内容我是内容我是内容',
|
||
time:"2020年7月",
|
||
color:"blue",
|
||
icon:'icon-position-fill',
|
||
iconSize:36,
|
||
borderColor:'blue'
|
||
},
|
||
*/
|
||
import tmIcons from "@/tm-vuetify/components/tm-icons/tm-icons.vue"
|
||
export default {
|
||
components:{tmIcons},
|
||
name: 'tm-timeline',
|
||
props:{
|
||
list:{
|
||
type:Array,
|
||
default:()=>{
|
||
return [];
|
||
}
|
||
},
|
||
// 是否反转内容
|
||
reverse:{
|
||
type:Boolean,
|
||
default:false
|
||
},
|
||
// 默认线的颜色,
|
||
borderColor:{
|
||
type:String,
|
||
default:'grey-lighten-2'
|
||
},
|
||
// 默认主题和节点颜色如果
|
||
color:{
|
||
type:String,
|
||
default:'primary'
|
||
},
|
||
size:{
|
||
type:Number,
|
||
default:36
|
||
},
|
||
black:{
|
||
type:Boolean|String,
|
||
default:null
|
||
},
|
||
model:{
|
||
type:String,
|
||
default:'center' // left|center|right
|
||
},
|
||
// 跟随主题色的改变而改变。
|
||
fllowTheme:{
|
||
type:Boolean|String,
|
||
default:true
|
||
}
|
||
},
|
||
|
||
data() {
|
||
return {
|
||
listData:[],
|
||
};
|
||
},
|
||
watch:{
|
||
list:{
|
||
deep:true,
|
||
handler(){
|
||
this.jsList = this.list;
|
||
}
|
||
}
|
||
},
|
||
computed:{
|
||
black_tmeme: function() {
|
||
if (this.black !== null) return this.black;
|
||
return this.$tm.vx.state().tmVuetify.black;
|
||
},
|
||
color_tmeme:function(){
|
||
if(this.$tm.vx.state().tmVuetify.color!==null&&this.$tm.vx.state().tmVuetify.color && this.fllowTheme){
|
||
return this.$tm.vx.state().tmVuetify.color;
|
||
}
|
||
return this.color;
|
||
},
|
||
jsList:{
|
||
get:function(){
|
||
return this.listData;
|
||
},
|
||
set:function(val){
|
||
if(this.reverse){
|
||
this.listData = this.list.reverse();
|
||
}else{
|
||
this.listData = this.list;
|
||
}
|
||
}
|
||
}
|
||
},
|
||
mounted() {
|
||
this.jsList = this.list;
|
||
},
|
||
methods: {
|
||
botop(d){
|
||
return uni.upx2px(d.size+8||32)
|
||
},
|
||
bwi(item){
|
||
if(!item||!item['size']){
|
||
return uni.upx2px(this.size||24)
|
||
}else if(item['size']){
|
||
return uni.upx2px(item['size']||24)
|
||
}
|
||
return uni.upx2px(24)
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="less" scoped>
|
||
.tm-timeline {
|
||
.tm-timeline-item {
|
||
.tm-timeline-item-left,
|
||
.tm-timeline-item-right {
|
||
width: 200upx;
|
||
flex-shrink: 0;
|
||
// transform: translateY(-34upx);
|
||
|
||
}
|
||
|
||
.tm-timeline-item-content{
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: flex-start;
|
||
align-content: flex-start;
|
||
}
|
||
.tm-timeline-jidian {
|
||
|
||
margin: auto;
|
||
}
|
||
&.tm-timeline-item--leftDir{
|
||
display: flex;
|
||
flex-flow: row;
|
||
&.endright{
|
||
justify-content: flex-end;
|
||
}
|
||
.tm-timeline-item-left,
|
||
.tm-timeline-item-right {
|
||
width:auto;
|
||
max-width: 400upx;
|
||
|
||
}
|
||
.tm-timeline-item-boder{
|
||
height: 100%;
|
||
width: 1px;margin: auto;
|
||
}
|
||
.tm-timeline-jidian {
|
||
position: relative;
|
||
margin: auto;
|
||
z-index: 2;
|
||
}
|
||
.tm-timeline-item-content{
|
||
display: flex;
|
||
justify-content: flex-start;
|
||
align-items: flex-start;
|
||
align-content: flex-start;
|
||
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
</style>
|