Vue時間軸 vue-light-timeline的用法說明
輕量的vue時間軸組件
install
npm install vue-light-timeline
如果你使用的是yarn
yarn add vue-light-timeline
usage
import LightTimeline from 'vue-light-timeline';
Vue.use(LightTimeline);
<template> <light-timeline :items='items'></light-timeline> </template> export default { data () { return { items: [ { tag: '2019-02-12', content: '測試內(nèi)容' }, { tag: '2019-02-13', type: 'circle', content: '練習(xí)內(nèi)容' } ] } } }
或者你還可以為時間軸的每個部分傳遞插槽:
<template> <light-timeline :items='items'> <template slot='tag' slot-scope='{ item }'> {{item.date}} </template> <template slot='content' slot-scope='{ item }'> {{item.msg}} </template> </light-timeline> </template> <script> export default { data () { return { items: [ { date: '2019-02-12', msg: '測試內(nèi)容' }, { date '2019-02-13', msg: '練習(xí)內(nèi)容' } ] } } }
自己寫個好看點的樣式就行了
補充知識:Vue可移動水平時間軸
里程碑時間軸具體實現(xiàn)
效果圖
編輯里程碑效果圖
<template> <div class="state_grade"> <!-- <mile-stone :projectId="projectData.proId" :projectName="projectData.proName" :proNum="projectData.proNum"></mile-stone>--> <div class="timeLine" style="overflow: hidden;"> <div style="width: 10%; display: inline-block; margin-left: 5px;"> <el-button @click="mileStoUpdateVisible = true" type="primary">編輯里程碑</el-button> </div> <div style="width: 70%;display: inline-block" align="center"> <div style="width: 20%;display: inline-block; font-size: 14px;">里程碑狀態(tài):</div> <div style="width: 100px;display: inline-block; font-size: 14px; ">開始 <img class="node_picture" src="../../assets/images/timeLineA.png"></div> <div style="width: 100px;display: inline-block; font-size: 14px;">超期 <img class="node_picture" src="../../assets/images/timeLineB.png"> </div> <div style="width: 100px;display: inline-block; font-size: 14px;">關(guān)閉 <img class="node_picture" src="../../assets/images/timeLineC.png"> </div> </div> <div class="my_timeline_prev" @click="moveLeft"> <img src="../../assets/arrow_left_blue.png" class="my_timeline_node"/> <!-- <div class="my_timeline_item_line" style="margin-top: -18px;"></div>--> <!-- <div class="my_timeline_item_content" style="color: rgba(0,0,0,0);">上</div>--> </div> <div v-if="destroyIncomeStatistics" class="ul_box"> <ul class="my_timeline" ref="mytimeline" style="margin-left: 10px;"> <li class="my_timeline_item" v-for="(item,index) in timeLineList" :key="index"> <el-tooltip placement="top" effect="light"> <div slot="content" class="tooltip"> <el-row> <el-col :span="24">{{'階段名稱:'+item.stageName}}</el-col> </el-row> <el-row> <el-col :span="24">{{'階段目標(biāo):'+item.stageTarget}}</el-col> </el-row> <el-row> <el-col :span="24">{{'開始時間:'+item.startTime}}</el-col> </el-row> <el-row> <el-col :span="24">{{'結(jié)束時間:'+item.endTime}}</el-col> </el-row> <el-row> <el-col :span="24">{{'驗收標(biāo)準(zhǔn):'+item.acceptStar}}</el-col> </el-row> <el-row> <el-col :span="24"> <span v-if="item.milepostState==='1'">里程碑狀態(tài):打開</span> <span v-if="item.milepostState==='2'">里程碑狀態(tài):超期</span> <span v-if="item.milepostState==='3'">里程碑狀態(tài):關(guān)閉</span> </el-col> </el-row> </div> <!--圈圈節(jié)點--> <!-- <div class="my_timeline_node" style="backgroundColor: #999; width: 28px;height: 28px;" @click="changeActive(index)" :class="{active: index == timeIndex}"></div>--> <div class="my_timeline_node"> <div style="background-color: #FCFCFC"> <img class="my_timeline_picture" v-if="item.milepostState==='1'" src="../../assets/images/timeLineA.png"> <img class="my_timeline_picture" v-if="item.milepostState==='2'" src="../../assets/images/timeLineB.png"> <img class="my_timeline_picture" v-if="item.milepostState==='3'" src="../../assets/images/timeLineC.png"> </div> </div> </el-tooltip> <!--線--> <div :class="[timeLineList.length==index+1?my_timeline_item_line_last:my_timeline_item_line_not_last]"></div> <!--標(biāo)注--> <div class="my_timeline_item_content"> <div>{{item.endTime}}</div> <el-tooltip placement="top" effect="light"> <div slot="content">{{item.endTime}}<br/>{{item.stageName}}</div> <div class="detail_info">{{item.stageName}}</div> </el-tooltip> </div> </li> </ul> </div> <div class="my_timeline_next" @click="moveRight"> <img src="../../assets/arrow_right_blue.png" class="my_timeline_node"/> <div class="my_timeline_item_content" style="color: rgba(0,0,0,0);">下</div> </div> </div> <el-dialog :title="titleMessage" center :visible="mileStoUpdateVisible" width="50%" @open="onMileStoUpdateVisibleOpen()" @close="closeMileStone()"> <stone-detail :projectId="this.projectId" :proNum="this.projectData.proNum" @closeMileStone="closeMileStone()" ref="stone-detail" @refreshMileStoneData="searchMileStone()"></stone-detail> </el-dialog> </div> </div> </template> <script> import API from '../../api/api_project'; import StoneDetail from "../../components/project-info/stonedetail" import MemberDetail from "../../components/project-info/memberdetail.vue" export default { name: 'project-detail', components:{ MemberDetail, StoneDetail, }, data() { return { destroyIncomeStatistics:true, loading: false, titleMessage: '', mileStoUpdateVisible: false, my_timeline_item_line_last: "my_timeline_item_line_last", my_timeline_item_line_not_last: "my_timeline_item_line_not_last", menuTree:[], timeLineList: [], page:{ total:0, pageNum: 0, pageSize: 10, }, model: { select: "", searchConent: "", projectId: "", proName:"", }, projectData:{ proId: '', proNum: '', proName: '', hwDept: '', hwPo: '', busineMode: '1', buildProDate: '', startDate: '', expEndDate: '', hwPoDate: '', hwPoEndDate:'', realEndDate: '', proManageId:'', proQa:'', hwPm:'', proEstNum: '0', proState:'1' }, proPeoId:'', projectId:'', proPeoUpdateVisible:false, projectMember: [], } }, mounted(){ this.projectId=this.$route.params.projectId this.searchMileStone() this.sortDataArray(this.timeLineList) //到數(shù)據(jù)庫獲取projectId對應(yīng)的信息列表存入projectData API.getProjectInfo(this.projectId).then((data)=>{ this.projectData=data.data; this.projectData.busineMode = this.projectData.busineMode.toString(); this.projectData.proState = this.projectData.proState.toString(); }) this.search(); }, methods: { searchMileStone() { console.log('項目id:'+this.projectId) let params={ proId:this.projectId, }; API.getMileStoneList(params).then(data => { let result = data.data if (result && result.list) { if(this.timeLineList.length>0){ this.timeLineList.splice(0,this.timeLineList.length); } for(var i=0;i<result.list.length;i++){ this.timeLineList.splice(i, 1, result.list[i]) } this.sortDataArray(this.timeLineList) } },({msg})=>{ this.$message.error(msg); }); console.log('刷新里程碑列表') console.log(this.timeLineList) }, closeMileStone() { this.mileStoUpdateVisible = false; // this.projectId = ''; }, onMileStoUpdateVisibleOpen() { this.titleMessage = this.projectData.proNum + '項目里程碑'; this.$nextTick(() => { let form = this.$refs["stone-detail"]; form.initPage(); }); }, changeActive(index) { this.timeIndex = index; }, moveLeft() { let marginLeft = parseInt(this.$refs.mytimeline.style.marginLeft); let listNum = 0; if (Math.abs(marginLeft) > 10) { this.$refs.mytimeline.style.marginLeft = marginLeft + 120 + 'px'; } }, moveRight() { let marginLeft = parseInt(this.$refs.mytimeline.style.marginLeft); if (marginLeft <= 10 && (marginLeft >= -(this.timeLineList.length * 120))) { this.$refs.mytimeline.style.marginLeft = marginLeft - 120 + 'px'; } }, //對數(shù)組根據(jù)日期進行排序 sortDataArray(dataArray) { return dataArray.sort(function (a, b) { return Date.parse(a.endTime.replace(/-/g, "/")) - Date.parse(b.endTime.replace(/-/g, "/")); }) }, sortByKey(array,key){ return array.sort(function(a,b){ var y = a[key]; var x = b[key]; return((x<y)?-1:((x>y)?1:0)); }) }, handleCurrentChange(val) { this.page.pageNum = val ; this.search(); }, handleSizeChange(val) { this.page.pageSize = val; this.search(); }, handleSearch(){ this.page.pageNum= 0; this.search(); }, } </script> .content { height: 100px; } .my_timeline_next { float: left; display: inline-block; background-color: #FCFCFC; cursor: pointer; } .my_timeline_prev { width: 50px; float: left; margin-top: 110px; } .my_timeline_next { width: 34px; margin-top: 80px; } .el-col-24 { margin-left: 10px; padding-bottom: 5px; } .el-col-12 { margin-left: 10px; } .tooltip { } .ul_box { width: 80%; height: 120px; display: inline-block; float: left; margin-top: 50px; overflow: hidden; } .my_timeline_item { display: inline-block; width: 150px; } .my_timeline_node { background-color: #FCFCFC; box-sizing: border-box; border-radius: 50%; cursor: pointer; width: 40px; height: 40px; } .node_picture { //margin-top: 20px; height: 25px; width: 25px; margin-left: 5px; margin-bottom: -7px; } .my_timeline_picture { margin-top: 13px; height: 25px; width: 25px; } .my_timeline_node.active { background-color: #fff !important; border: 6px solid #f68720; } .my_timeline_item_line_last { width: 100%; height: 10px; margin: -14px 0 0 28px; border-left: none; } .my_timeline_item_line_not_last { width: 100%; height: 10px; margin: -14px 0 0 25px; border-top: 2px solid #E4E7ED; border-left: none; } .my_timeline_item_content { margin: 10px 0 0 -10px; width: 90%; /*根據(jù)自己項目進行定義寬度*/ font-size: 14px; } .detail_info { width: 80%; height: 250px; padding-bottom: 50px; overflow: hidden; /*設(shè)置超出的部分進行影藏*/ text-overflow: ellipsis; /*設(shè)置超出部分使用省略號*/ white-space: nowrap; /*設(shè)置為單行*/ font-size: 14px; } .state_grade.process_wrap{ border-color: #e4ebf0; margin-top: 150px; border-radius: 2px; padding-bottom: 10px; } .fall-back { float:right; margin-right: 20px; margin-bottom:50px; } .state_grade{ border: 1px solid #e6e6e6; background: #FCFCFC; padding: 10px; //position: relative; /*height: 90px;*/ height: 250px; margin-bottom: 15px; /*margin-top: 15px;*/ } .title_top{ height: 33px; } .obj_tit_wrap{ border-bottom: 1px solid #e6e6e6; padding-bottom: 3px; font-size: 14px; } .obj_tit_mile{ width: 150px; height: 35px; } .tit_deco{ color: #9a9a9a; font-size: 14px; } .add_contain{ display:inline-block; padding-bottom: 10px; padding-top: 20px; } .project_content_warp{ background: #fdfdfd; margin-bottom: 15px; } .project_job_add{ padding-left: 30px; background: #FCFCFC; border-bottom: 1px solid #E5E5E5; line-height: 10px; margin-bottom: 15px; font-size: 14px; } .project_info_span{ display:inline-block; padding-left: 10px; } .el-col-8{ height: 50px; } </style>
編輯里程碑
stonedetail.vue
<template> <div> <el-row> <el-col :span="23"> <div style="margin-top: 10px"> <el-tag effect="dark" style="font-size: 16px;width: 110px;text-align: center">里程碑</el-tag> </div> </el-col> <el-col :span="1"> <img src="../../assets/images/add.png" style="width: 30px;height: 30px;margin-top: 10px" @click="addItems()"/> </el-col> </el-row> <hr/> <el-row style="text-align: center"> <el-col :span="3"> <el-tag style="width: 100%;font-size: 14px">序 號</el-tag> </el-col> <el-col :span="8"> <el-tag style="width: 100%;font-size: 14px">階段名稱</el-tag> </el-col> <el-col :span="7"> <el-tag style="width: 100%;font-size: 14px">起始時間</el-tag> </el-col> <el-col :span="5"> <el-tag style="width: 100%;font-size: 14px">結(jié)束時間</el-tag> </el-col> </el-row> <el-form label-width="100px" align="left" ref="form" style="text-align: left;" :model="model"> <div v-for="(item, index) in model.timeLineList" :key="index"> <el-row> <el-col :span="3"> <input style="text-align: center" class="el-input__inner" type="text" v-model="index" disabled="true"> </el-col> <el-col :span="8"> <input placeholder="請輸入階段名稱" style="text-align: center" class="el-input__inner" type="text" v-model="item.stageName"> </el-col> <el-col :span="6"> <el-date-picker style="width: 100%" type="date" :editable="false" v-model="item.startTime" placeholder="請選擇起始時間" format="yyyy-MM-dd" value-format="yyyy-MM-dd" > </el-date-picker> </el-col> <el-col :span="6"> <el-date-picker style="width: 100%" type="date" :editable="false" v-model="item.endTime" placeholder="請選擇結(jié)束時間" format="yyyy-MM-dd" value-format="yyyy-MM-dd" > </el-date-picker> </el-col> </el-row> <el-row> <el-col :span="3"> <input placeholder="階段目標(biāo)" style="text-align: center;" class="el-input__inner" type="text" disabled="true"> </el-col> <el-col :span="20"> <el-input v-model="item.stageTarget" placeholder="請輸入階段目標(biāo)"></el-input> <!-- <textarea placeholder="請輸入階段目標(biāo)" v-model="item.stageTarget" style="height: 30px;" class="el-input__inner" type="text"></textarea>--> </el-col> </el-row> <el-row> <el-col :span="3"> <input placeholder="驗收標(biāo)準(zhǔn)" style="text-align: center;" class="el-input__inner" type="text" disabled="true"> </el-col> <el-col :span="20"> <el-input v-model="item.acceptStar" placeholder="請輸入驗收標(biāo)準(zhǔn)"></el-input> </el-col> </el-row> <el-row> <el-col :span="3"> <input placeholder="里程碑狀態(tài)" style="text-align: center;" class="el-input__inner" type="text" disabled="true"> </el-col> <el-col :span="20"> <template> <el-select v-model="item.milepostState" placeholder="請選擇"> <el-option v-for="item in milepostStateList" :key="item.ref_id" :label="item.ref_value" :value="item.ref_id"> </el-option> </el-select> </template> </el-col> <el-col :span="1"> <img src="../../assets/images/delete.png" style="width: 30px;height: 30px" @click="deleteItems(index)"/> </el-col> </el-row> </div> </el-form> <div style="text-align: center;margin-top: 30px"> <el-button type="primary" @click="submit()">確認(rèn)修改</el-button> </div> </div> </template> <script> import API from '../../api/api_project'; export default { name: "stoneDetail", props: ['projectId', 'proNum'], watch: { 'proId': { // projectId,所以每次都能監(jiān)聽到變化 immediate: true, handler: function (val) { if (!val) return; this.onProjectIdChange(val); } } }, data() { return { proId:'', milepostStateList: [{ ref_id: "1", ref_value: '打開', ref_key: '1' }, { ref_id: "2", ref_value: '超期', ref_key: '2' }, { ref_id: "3", ref_value: '關(guān)閉', ref_key: '3' }], deleteList: [], model: { timeLineList: [], }, } }, methods: { /** * 提交修改的信息 */ submit: function () { this.$refs.form.validate((valid) => { if (!valid) { this.$message.error('請?zhí)顚懻_信息'); return; } console.log('編輯里程碑結(jié)果:') console.log(this.model.timeLineList) let proMileposts = this.model.timeLineList API.updatetMileStone(proMileposts).then(data => { if (data.code == 200) { this.$message.success("修改成功"); this.refreshMileStoneData(); this.close(); } else { this.$message.error(data.msg); // this.close(); } }) }); }, close() { this.$emit("closeMileStone"); this.proId='' this.model.timeLineList.splice(0,this.model.timeLineList.length) }, refreshMileStoneData() { this.$emit("refreshMileStoneData"); }, addItems() { this.model.timeLineList.push({ milepostId:'', proId: this.proId, stageName: '', startTime: this.addDate(), endTime: this.addDate(), stageTarget: '', acceptStar: '', deliverableName: '', milepostState: '1', }); }, addDate() { var date = new Date(); var seperator1 = "-"; var year = date.getFullYear(); var month = date.getMonth() + 1; var strDate = date.getDate(); if (month >= 1 && month <= 9) { month = "0" + month; } if (strDate >= 0 && strDate <= 9) { strDate = "0" + strDate; } var currentdate = year + seperator1 + month + seperator1 + strDate; return currentdate; }, deleteItems(index) { this.$confirm('確認(rèn)刪除該記錄嗎?', '提示', { confirmButtonClass: 'el-button--warning' }).then(() => { if(this.model.timeLineList[index].milepostId) { API.deleteMileStone(this.model.timeLineList[index].milepostId).then(data=>{ if(data.code===200) { this.$message.success("刪除成功"); this.model.timeLineList.splice(index, 1); this.refreshMileStoneData(); }else { this.$message.error(data.msg); } }) } else{ this.model.timeLineList.splice(index, 1); } }).catch(() => {}); }, onProjectIdChange(id) { this.model.timeLineList.splice(0,this.model.timeLineList.length) // if (id) { let params={ proId:id, }; API.getMileStoneList(params).then(data => { let result = data.data if (result && result.list) { for(var i=0;i<result.list.length;i++){ this.model.timeLineList.splice(i, 1, result.list[i]) } } }, ({msg}) => { this.$message.error(msg); }); // } console.log('dailog打開里程碑列表') console.log(this.model.timeLineList) }, initPage() { this.proId=this.projectId; if (this.proId) { this.onProjectIdChange(this.proId); } } }, } </script> <style scoped> </style>
以上這篇Vue時間軸 vue-light-timeline的用法說明就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
如何隱藏element-ui中tree懶加載葉子節(jié)點checkbox(分頁懶加載效果)
這篇文章主要介紹了如何隱藏element-ui中tree懶加載葉子節(jié)點checkbox(分頁懶加載效果),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07關(guān)于this.$refs獲取不到dom的可能原因及解決方法
這篇文章主要介紹了關(guān)于this.$refs獲取不到dom的可能原因及解決方法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11vue3?中的toRef函數(shù)和toRefs函數(shù)的基本使用
這篇文章主要介紹了vue3?toRef函數(shù)和toRefs函數(shù),文中介紹了ref和toRef的區(qū)別,ref本質(zhì)是拷貝,修改響應(yīng)式數(shù)據(jù)不會影響原始數(shù)據(jù),toRef的本質(zhì)是引用關(guān)系,修改響應(yīng)式數(shù)據(jù)會影響原始數(shù)據(jù),需要的朋友可以參考下2022-11-11vue + element-ui實現(xiàn)簡潔的導(dǎo)入導(dǎo)出功能
Element-UI是餓了么前端團隊推出的一款基于Vue.js 2.0 的桌面端UI框架,手機端有對應(yīng)框架是 Mint UI,下面這篇文章主要給大家介紹了關(guān)于利用vue + element-ui如何實現(xiàn)簡潔的導(dǎo)入導(dǎo)出功能的相關(guān)資料,需要的朋友可以參考下。2017-12-12