vue3.0项目管理时间轴(计划任务)自定义组件

基于项目管理开发需求而封装,可以灵活的输入时间线,并在时间线上,进行不同的计划安排,简单直观,组件引用了antd3.0组件库的popover组件,逻辑清晰简单,可自行更改!

效果图:

代码块:

<template>
    <div class="wapper" id="queryForm">
        <div class="workLine">
            <div v-for="(items,index) in task" :key="index"
                 :style="'width:'+items.Domwidth+'px; margin-left:'+items.width+'px'"
                 class="timetips">
                <a-popover title="计划详情">
                    <template #content>
                        <p>{{items.content}}</p>
                    </template>
                    <a-button style="background-color: white;border: none;text-decoration:underline" type="link">
                        计划({{index+1}})
                    </a-button>
                </a-popover>
                <i class="ri-map-pin-3-fill"/>
            </div>
        </div>
        <div class="lineFATH" style="display: flex;width: 100%;position: relative">
            <div v-for="(item,index) in list" :key="item.id"
                 :style="'left:'+item.width+'px' "
                 class="timeCard">
                <div class="timeCardMid">
                    <p class="timeCardMidLine"/>
                </div>
                <div :class="index===0?'ONE':''||index===(list.length-1)?'TWO':''" class="timeCardBot">
                    {{item.data}}
                </div>
            </div>
        </div>

    </div>
</template>

<script>
    import {toRefs, ref, reactive, nextTick, onMounted, getCurrentInstance} from 'vue'

    export default {
        props: {
            list: {
                type: Array,
                default: [
                    {
                        id: "1",
                        data: " 2022-01-12"
                    },
                    {
                        id: "2",
                        data: "2022-08-12"
                    },
                    {
                        id: "3",
                        data: "2022-03-12"
                    },
                    {
                        id: "4",
                        data: "2022-10-12"
                    },
                    {
                        id: "5",
                        data: "2022-12-12"
                    },
                ],
            },
            task: {
                type: Array,
                default: [
                    {
                        id: "1",
                        startTime: "2022-02-32",
                        endTime: "2022-05-12",
                        content: "这是我的第一个任务"
                    },
                    {
                        id: "2",
                        startTime: "2022-05-32",
                        endTime: "2022-08-12",
                        content: "这是我的第二个任务"
                    },
                    {
                        id: "3",
                        startTime: "2022-08-32",
                        endTime: "2022-11-12",
                        content: "这是我的第三个任务"
                    },
                    {
                        id: "4",
                        startTime: "2022-11-32",
                        endTime: "2022-12-12",
                        content: "这是我的第n个任务"
                    },
                ]
            }

        },
        setup(props) {
            const internalInstance = getCurrentInstance();
            const Array = reactive({
                /*时间轴*/
                list: props.list,
                /* 任务划分区域*/
                task: props.task,
                DomWidth: 0,
                timeWidth: "",
                evenly: '',

            });
            /*处理底部时间轴*/
            const addDays = () => {
                Array.list.forEach((item) => {
                    item.dueTime = Date.parse(item.data);
                });
                /*使用sort对Json数组的数据进行时间从小到大的排序*/
                Array.list.sort(function (a, b) {
                    return a.dueTime - b.dueTime;
                });
                console.log(Array.list)
                /*获取整个时间段的数据的总天数,并除以父级元素宽度,获取每一天元素可以分得的宽度*/
                Array.timeWidth = compareDate(Array.list[0].data, Array.list[Array.list.length - 1].data);
                Array.evenly = (Array.DomWidth / Array.timeWidth).toFixed(0);
                /*将得到的底部时间段,进行计算,分配在主轴线上所占位置*/
                for (let i = 0; i < Array.list.length; i++) {
                    Array.list[i].width = Array.evenly * compareDate(Array.list[0].data, Array.list[i].data)

                }
                /*起止位置分别定位为0以及100%*/
                Array.list[0].width = 0;
                Array.list[Array.list.length - 1].width = Array.DomWidth - 1
                tasks()
            };
            /*处理任务时间轴*/
            const tasks = () => {
                for (let i = 0; i < Array.task.length; i++) {
                    Array.task[i].Domwidth = Array.evenly * compareDate(Array.task[i].startTime, Array.task[i].endTime);

                    if (i === 0) {
                        Array.task[i].width = 0
                    } else {
                        Array.task[i].width = Array.evenly * compareDate(Array.task[i - 1].endTime, Array.task[i].startTime)
                    }
                }
                internalInstance.ctx.$forceUpdate()
            };
            /*计算两个时间之间的天数*/
            const compareDate = (start, end) => {
                if (start === null || start.length === 0 || end === null || end.length === 0) {
                    return 0;
                }
                let arr = start.split("-");
                let starttime = new Date(arr[0], parseInt(arr[1] - 1), arr[2]);
                let starttimes = starttime.getTime();

                let arrs = end.split("-");
                let endtime = new Date(arrs[0], parseInt(arrs[1] - 1), arrs[2]);
                let endtimes = endtime.getTime();

                let intervalTime = endtimes - starttimes;//两个日期相差的毫秒数 一天86400000毫秒
                let Inter_Days = ((intervalTime).toFixed(2) / 86400000) + 1;//加1,是让同一天的两个日期返回一天

                return Inter_Days;
            };

            /*挂载时输出父元素的宽度*/
            onMounted(() => {
                /*或取父级元素的宽高*/
                Array.DomWidth = document.getElementById('queryForm').clientWidth;
                addDays()
            });
            return {
                ...toRefs(Array),
                internalInstance,
                compareDate
            }
        }


    }
</script>

<style scoped>
    .wapper {
        margin: 20px 20px;
        background-color: #39c1e0;
        border: 1px solid #39c1e0;

    }

    p {
        margin: 0;
        padding: 0;
    }

    .timeCard {
        position: absolute;
        top: 0px;
        height: 35px;
        text-align: center;

    }

    .timeCardMid {
        height: 35px;
    }

    .timeCardMidLine {
        height: 35px;
        width: 1px;
        background-color: #39c1e0;
    }

    .timeCardBot {
        height: 35px;
        border-radius: 5px;
        text-align: center;
        line-height: 35px;
        padding: 0 5px;
        position: relative;
        border: 1px solid #d9d9d9;
        top: -0;
        left: -50%;
        width: 100px;

    }

    .workLine {
        display: flex;
    }

    .ri-map-pin-3-fill {
        position: absolute;
        left: 50%;
        top: -66%;
        font-size: 16px;
        color: #3d3d3d;

    }

    .ONE {
        left: -20px !important;
    }

    .TWO {
        left: -80%;
    }

    .timetips {
        background-color: white;
        position: relative;
        border-radius: 5px;
        height: inherit;
        font-size: 12px;
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        justify-content: center;

    }
</style>

希望能够帮助到大家!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值