|  | @@ -0,0 +1,340 @@
 | 
	
		
			
				|  |  | +<template>
 | 
	
		
			
				|  |  | +    <div class="time-line-wrap" v-show="isShow">
 | 
	
		
			
				|  |  | +        <div class="play" @click="handleChange">
 | 
	
		
			
				|  |  | +            <img
 | 
	
		
			
				|  |  | +                class="icon"
 | 
	
		
			
				|  |  | +                :src="require(`@/assets/images/home/${isCounting ? 'transparent-pause-icon.png' : 'transparent-play-icon.png'}`)"
 | 
	
		
			
				|  |  | +                alt=""
 | 
	
		
			
				|  |  | +            />
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +        <div class="line">
 | 
	
		
			
				|  |  | +            <div class="active-line" :style="{ width: widthTotal()}"></div>
 | 
	
		
			
				|  |  | +                <div :class="['dot-item', {'cur-category':active===index},{'not-special':active===index&&!item.special&&listType!=='mentalState'}]" v-for="(item, index) in timeArr" :key="index">
 | 
	
		
			
				|  |  | +                <span v-show="listType==='mentalState'" :class="['name']">{{ item.nodeName}}</span>
 | 
	
		
			
				|  |  | +                <div :class="['dot', {'big-dot': item.bigDot}]" :style="{marginLeft:marginLeftValue(index)}"></div>
 | 
	
		
			
				|  |  | +                <div v-show="item.farmworkName&&active===index" :class="{'ns':active===index}">{{item.farmworkName}}</div>
 | 
	
		
			
				|  |  | +                <span v-show="listType==='mentalState'&&item.nodeName">{{ item.date }}</span>
 | 
	
		
			
				|  |  | +                <template v-if="listType!=='mentalState'&&active===index&&!isBtnActive">
 | 
	
		
			
				|  |  | +                    <span class="position">{{ item.jieqi }}</span>
 | 
	
		
			
				|  |  | +                    <span :class="['name name-1',{'color':item.bigDot}]">{{ item.nodeName}}</span>
 | 
	
		
			
				|  |  | +                </template>
 | 
	
		
			
				|  |  | +            </div>
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +    </div>
 | 
	
		
			
				|  |  | +</template>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +<script setup>
 | 
	
		
			
				|  |  | +import { ref, onDeactivated, onMounted} from "vue";
 | 
	
		
			
				|  |  | +import { useStore } from "vuex";
 | 
	
		
			
				|  |  | +// import eventBus from "@/api/eventBus";
 | 
	
		
			
				|  |  | +const store = useStore();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const isShow = ref(true)
 | 
	
		
			
				|  |  | +const total = ref(0)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const widthTotal = () =>{
 | 
	
		
			
				|  |  | +    let num
 | 
	
		
			
				|  |  | +    num = isCompute.value?((active.value/(timeArr.value.length - 1)) * 100) + total.value : widthNum.value
 | 
	
		
			
				|  |  | +    // if(listType.value==='mentalState'){
 | 
	
		
			
				|  |  | +    if(num>=100 && listType.value==='mentalState'){
 | 
	
		
			
				|  |  | +        // const arr = [5,24,37,50,68,82,95]
 | 
	
		
			
				|  |  | +        num = 93
 | 
	
		
			
				|  |  | +        // num = arr[active.value]
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if(num>=100 && listType.value==='cataclysm'){
 | 
	
		
			
				|  |  | +        num = 101
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return num + '%'
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const marginLeftValue = (index) =>{
 | 
	
		
			
				|  |  | +    let num = 7.5
 | 
	
		
			
				|  |  | +    if(listType.value === 'mentalState'){
 | 
	
		
			
				|  |  | +        num = 12
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return num + 'px'
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const active = ref(0);
 | 
	
		
			
				|  |  | +const isCounting = ref(false);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const timeArr = ref([])
 | 
	
		
			
				|  |  | +const organId = ref(null)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +onMounted(() => {
 | 
	
		
			
				|  |  | +    getTimeList()
 | 
	
		
			
				|  |  | +})
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const isUpdate = () =>{
 | 
	
		
			
				|  |  | +   if(listType.value==='cataclysm'){
 | 
	
		
			
				|  |  | +        if(timeArr.value[active.value -1]?.phenologyName!==timeArr.value[active.value].phenologyName){
 | 
	
		
			
				|  |  | +            isBtnActive.value = false
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const widthNum = ref(0)
 | 
	
		
			
				|  |  | +const curIndex = ref(0)
 | 
	
		
			
				|  |  | +const isCompute = ref(false)
 | 
	
		
			
				|  |  | +const listType = ref('mentalState')//mentalState:灵境时间轴,cataclysm:灾变时间轴
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// nodeType 节点类型 0:大发育期,1:小发育期,2:节气
 | 
	
		
			
				|  |  | +// nodeStatus 节点状态(0-过去;1-现在;2-未来)
 | 
	
		
			
				|  |  | +const getTimeList = () =>{
 | 
	
		
			
				|  |  | +    widthNum.value = 6
 | 
	
		
			
				|  |  | +    total.value = 0
 | 
	
		
			
				|  |  | +    isCompute.value = false
 | 
	
		
			
				|  |  | +    restActive()
 | 
	
		
			
				|  |  | +    timeArr.value = [
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            "farmworkName": "",
 | 
	
		
			
				|  |  | +            "nodeDate": "2025-01-07",
 | 
	
		
			
				|  |  | +            "nodeName": "花芽萌动期",
 | 
	
		
			
				|  |  | +            "nodeStatus": 0
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            "farmworkName": "",
 | 
	
		
			
				|  |  | +            "nodeDate": "2025-01-19",
 | 
	
		
			
				|  |  | +            "nodeName": "花蕾抽出期",
 | 
	
		
			
				|  |  | +            "nodeStatus": 2
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            "farmworkName": "",
 | 
	
		
			
				|  |  | +            "nodeDate": "2025-02-02",
 | 
	
		
			
				|  |  | +            "nodeName": "花穗伸长期",
 | 
	
		
			
				|  |  | +            "nodeStatus": 2
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    ]
 | 
	
		
			
				|  |  | +    // VE_API.farm.getTimeLine({farmId:organId.value}).then(({code,data}) =>{
 | 
	
		
			
				|  |  | +    //     if(code===0){
 | 
	
		
			
				|  |  | +    //         curIndex.value = 0
 | 
	
		
			
				|  |  | +    //         active.value = curIndex.value
 | 
	
		
			
				|  |  | +    //         timeArr.value = data.map((item,index) =>{
 | 
	
		
			
				|  |  | +    //             return {
 | 
	
		
			
				|  |  | +    //                 ...item,
 | 
	
		
			
				|  |  | +    //                 bigDot:index===0?true:false,
 | 
	
		
			
				|  |  | +    //                 curCategory:item.nodeStatus===1,
 | 
	
		
			
				|  |  | +    //                 smallDot:index==1||index==2||index==4||index==5,
 | 
	
		
			
				|  |  | +    //                 date:item.nodeDate.slice(5,7) + '.' + item.nodeDate.slice(8,10)
 | 
	
		
			
				|  |  | +    //             }
 | 
	
		
			
				|  |  | +    //         })
 | 
	
		
			
				|  |  | +    //         eventBus.emit("timeLine:changeTime",{...data[0],isFirst:true})
 | 
	
		
			
				|  |  | +    //     }
 | 
	
		
			
				|  |  | +    // })
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const incrementInterval = 7000; // 默认间隔5秒
 | 
	
		
			
				|  |  | +const specialIncrementInterval = 7000; // 特殊间隔7秒
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const timer = ref(null);
 | 
	
		
			
				|  |  | +const incrementCount = (type) => {
 | 
	
		
			
				|  |  | +    isCompute.value = true
 | 
	
		
			
				|  |  | +    if (active.value === timeArr.value.length - 1) {
 | 
	
		
			
				|  |  | +        isCompute.value = false
 | 
	
		
			
				|  |  | +        active.value = 0;
 | 
	
		
			
				|  |  | +        isUpdate()
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +        if(type!=='original'){
 | 
	
		
			
				|  |  | +            active.value += 1;
 | 
	
		
			
				|  |  | +            isUpdate()
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        timeArr.value[active.value].show = true
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    let time = incrementInterval;
 | 
	
		
			
				|  |  | +    if (active.value === 0 || active.value === timeArr.value.length - 1) {
 | 
	
		
			
				|  |  | +        time = specialIncrementInterval;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    timer.value = setTimeout(() => {
 | 
	
		
			
				|  |  | +        if (isCounting.value) incrementCount();
 | 
	
		
			
				|  |  | +    }, time);
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const timerId = ref(null);
 | 
	
		
			
				|  |  | +const isBtnActive = ref(true)
 | 
	
		
			
				|  |  | +const handleChange = () => {
 | 
	
		
			
				|  |  | +    clearTime()
 | 
	
		
			
				|  |  | +    if (active.value === 0 || active.value === timeArr.value.length - 1) {
 | 
	
		
			
				|  |  | +        timerId.value = setTimeout(() => {
 | 
	
		
			
				|  |  | +            if (isCounting.value) incrementCount();
 | 
	
		
			
				|  |  | +        }, specialIncrementInterval);
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +        incrementCount('original');
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    isCounting.value = !isCounting.value;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +onDeactivated(() => {
 | 
	
		
			
				|  |  | +    clearTime();
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +//清除定时器
 | 
	
		
			
				|  |  | +const clearTime = () => {
 | 
	
		
			
				|  |  | +    if (timerId.value) {
 | 
	
		
			
				|  |  | +        clearTimeout(timerId.value);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if (timer.value) {
 | 
	
		
			
				|  |  | +        clearTimeout(timer.value);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const restActive = () => {
 | 
	
		
			
				|  |  | +    clearTime();
 | 
	
		
			
				|  |  | +    active.value = curIndex.value;
 | 
	
		
			
				|  |  | +    isCounting.value = false;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +</script>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +<style lang="scss" scoped>
 | 
	
		
			
				|  |  | +.time-line-wrap {
 | 
	
		
			
				|  |  | +    width: 100%;
 | 
	
		
			
				|  |  | +    height: 100%;
 | 
	
		
			
				|  |  | +    border-radius: 10px 10px 20px 20px;
 | 
	
		
			
				|  |  | +    background: rgba(35, 35, 35, 0.6);
 | 
	
		
			
				|  |  | +    display: flex;
 | 
	
		
			
				|  |  | +    align-items: center;
 | 
	
		
			
				|  |  | +    box-sizing: border-box;
 | 
	
		
			
				|  |  | +    padding: 10px 8px;
 | 
	
		
			
				|  |  | +    border: 1px solid rgba(255,255,255,0.4);
 | 
	
		
			
				|  |  | +    .play {
 | 
	
		
			
				|  |  | +        display: flex;
 | 
	
		
			
				|  |  | +        align-items: center;
 | 
	
		
			
				|  |  | +        margin-right: 20px;
 | 
	
		
			
				|  |  | +        .icon {
 | 
	
		
			
				|  |  | +            width: 28px;
 | 
	
		
			
				|  |  | +            height: 28px;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    .line {
 | 
	
		
			
				|  |  | +        background: linear-gradient(30deg, #fff 0% , #2C2C2C 100%);
 | 
	
		
			
				|  |  | +        border-radius: 2px;
 | 
	
		
			
				|  |  | +        width: 80%;
 | 
	
		
			
				|  |  | +        height: 2px;
 | 
	
		
			
				|  |  | +        display: flex;
 | 
	
		
			
				|  |  | +        justify-content: space-between;
 | 
	
		
			
				|  |  | +        position: relative;
 | 
	
		
			
				|  |  | +        z-index: 2;
 | 
	
		
			
				|  |  | +        .active-line {
 | 
	
		
			
				|  |  | +            background: linear-gradient(30deg, #eccd9b 0% ,#F3C11D 100%,);
 | 
	
		
			
				|  |  | +            position: absolute;
 | 
	
		
			
				|  |  | +            top: 0;
 | 
	
		
			
				|  |  | +            left: 0;
 | 
	
		
			
				|  |  | +            height: 2px;
 | 
	
		
			
				|  |  | +            z-index: 1;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        .dot-item {
 | 
	
		
			
				|  |  | +            color: rgba(255,255,255,0.3);
 | 
	
		
			
				|  |  | +            font-size: 10px;
 | 
	
		
			
				|  |  | +            position: relative;
 | 
	
		
			
				|  |  | +            z-index: 2;
 | 
	
		
			
				|  |  | +            .dot {
 | 
	
		
			
				|  |  | +                width: 4px;
 | 
	
		
			
				|  |  | +                height: 4px;
 | 
	
		
			
				|  |  | +                background: #E6E6E6;
 | 
	
		
			
				|  |  | +                border-radius: 50%;
 | 
	
		
			
				|  |  | +                margin: -1px 0 6px 14px;
 | 
	
		
			
				|  |  | +                position: relative;
 | 
	
		
			
				|  |  | +                &::after{
 | 
	
		
			
				|  |  | +                    content: '';
 | 
	
		
			
				|  |  | +                    position: absolute;
 | 
	
		
			
				|  |  | +                    top: -2px;
 | 
	
		
			
				|  |  | +                    left: -2px;
 | 
	
		
			
				|  |  | +                    width: 4px;
 | 
	
		
			
				|  |  | +                    height: 4px;
 | 
	
		
			
				|  |  | +                    border-radius: 50%;
 | 
	
		
			
				|  |  | +                    border: 2px solid rgba(255,255,255,0.2);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            .ns{
 | 
	
		
			
				|  |  | +                position: absolute;
 | 
	
		
			
				|  |  | +                top: -45px;
 | 
	
		
			
				|  |  | +                left: -10px;
 | 
	
		
			
				|  |  | +                width: 56px;
 | 
	
		
			
				|  |  | +                height: 20px;
 | 
	
		
			
				|  |  | +                color: #fff;
 | 
	
		
			
				|  |  | +                text-align: center;
 | 
	
		
			
				|  |  | +                line-height: 20px;
 | 
	
		
			
				|  |  | +                border-radius: 5px;
 | 
	
		
			
				|  |  | +                background: linear-gradient(180deg,#F3C11D 0%,#715803 100%);
 | 
	
		
			
				|  |  | +                &::before{
 | 
	
		
			
				|  |  | +                    content: '';
 | 
	
		
			
				|  |  | +                    position: absolute;
 | 
	
		
			
				|  |  | +                    top: 20px;
 | 
	
		
			
				|  |  | +                    left: calc(50% - 8px);
 | 
	
		
			
				|  |  | +                    border-left: 6px solid transparent;
 | 
	
		
			
				|  |  | +                    border-right: 6px solid transparent;
 | 
	
		
			
				|  |  | +                    border-top: 6px solid #715803;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            span {
 | 
	
		
			
				|  |  | +                margin-left: 3px;
 | 
	
		
			
				|  |  | +                letter-spacing: 0.5px;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            .position{
 | 
	
		
			
				|  |  | +                position: absolute;
 | 
	
		
			
				|  |  | +                width: 22px;
 | 
	
		
			
				|  |  | +                left: -4px;
 | 
	
		
			
				|  |  | +                top: 6px;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            .color{
 | 
	
		
			
				|  |  | +                color: #D7C690;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            .big-dot {
 | 
	
		
			
				|  |  | +                width: 6px;
 | 
	
		
			
				|  |  | +                height: 6px;
 | 
	
		
			
				|  |  | +                margin: -2px 0 5px 14px;
 | 
	
		
			
				|  |  | +                position: relative;
 | 
	
		
			
				|  |  | +                &::after{
 | 
	
		
			
				|  |  | +                    content: '';
 | 
	
		
			
				|  |  | +                    position: absolute;
 | 
	
		
			
				|  |  | +                    top: -2px;
 | 
	
		
			
				|  |  | +                    left: -2px;
 | 
	
		
			
				|  |  | +                    width: 6px;
 | 
	
		
			
				|  |  | +                    height: 6px;
 | 
	
		
			
				|  |  | +                    border-radius: 50%;
 | 
	
		
			
				|  |  | +                    border: 2px solid rgba(255,255,255,0.2);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            .name{
 | 
	
		
			
				|  |  | +                position: absolute;
 | 
	
		
			
				|  |  | +                top: -19px;
 | 
	
		
			
				|  |  | +                left: -20px;
 | 
	
		
			
				|  |  | +                width: 62px;
 | 
	
		
			
				|  |  | +                text-align: center;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            .name-1{
 | 
	
		
			
				|  |  | +                left: -27px;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            &.cur-category{
 | 
	
		
			
				|  |  | +                color: #F3C11D;
 | 
	
		
			
				|  |  | +                .color{
 | 
	
		
			
				|  |  | +                    color: #F3C11D;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                .dot{
 | 
	
		
			
				|  |  | +                    background: #f3c11d;
 | 
	
		
			
				|  |  | +                    &::after{
 | 
	
		
			
				|  |  | +                        border: 2px solid rgba(243,193,29,0.2);
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            &.not-special{
 | 
	
		
			
				|  |  | +                color: #D7C690;
 | 
	
		
			
				|  |  | +                .color{
 | 
	
		
			
				|  |  | +                    color: #D7C690;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                .dot{
 | 
	
		
			
				|  |  | +                    background: #D7C690;
 | 
	
		
			
				|  |  | +                    &::after{
 | 
	
		
			
				|  |  | +                        border: 2px solid rgba(215, 198, 144,0.2);
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +</style>
 |