Vue实现可移动水平时间轴


Posted in Javascript onJune 29, 2020

本文实例为大家分享了Vue实现可移动水平时间轴的具体代码,供大家参考,具体内容如下

里程碑时间轴具体实现

效果图

Vue实现可移动水平时间轴

编辑里程碑效果图

Vue实现可移动水平时间轴

<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;">里程碑状态:</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;">关闭 <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">{{'阶段目标:'+item.stageTarget}}</el-col>
  </el-row>
  <el-row>
  <el-col :span="24">{{'开始时间:'+item.startTime}}</el-col>
  </el-row>
  <el-row>
  <el-col :span="24">{{'结束时间:'+item.endTime}}</el-col>
  </el-row>
  <el-row>
  <el-col :span="24">{{'验收标准:'+item.acceptStar}}</el-col>
  </el-row>
  <el-row>
  <el-col :span="24">
  <span v-if="item.milepostState==='1'">里程碑状态:打开</span>
  <span v-if="item.milepostState==='2'">里程碑状态:超期</span>
  <span v-if="item.milepostState==='3'">里程碑状态:关闭</span>
  </el-col>
  </el-row>
  </div>
  <!--圈圈节点-->
  <!-- <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>
 <!--标注-->
 <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)
 //到数据库获取projectId对应的信息列表存入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';
 }
 },
//对数组根据日期进行排序
 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%; /*根据自己项目进行定义宽度*/
 font-size: 14px;
 }

 .detail_info {
 width: 80%;
 height: 250px;
 padding-bottom: 50px;
 overflow: hidden; /*设置超出的部分进行影藏*/
 text-overflow: ellipsis; /*设置超出部分使用省略号*/
 white-space: nowrap; /*设置为单行*/
 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">结束时间</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="请选择结束时间"
 format="yyyy-MM-dd"
 value-format="yyyy-MM-dd"
 >
 </el-date-picker>
 </el-col>
 </el-row>

 <el-row>
 <el-col :span="3">
 <input placeholder="阶段目标" 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="请输入阶段目标"></el-input>
 <!-- <textarea placeholder="请输入阶段目标" 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="验收标准" 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="请输入验收标准"></el-input>
 </el-col>
 </el-row>

 <el-row>
 <el-col :span="3">
 <input placeholder="里程碑状态" 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()">确认修改</el-button>
 </div>
 </div>


</template>

<script>
 import API from '../../api/api_project';

 export default {
 name: "stoneDetail",
 props: ['projectId', 'proNum'],
 watch: {
 'proId': {
 // projectId,所以每次都能监听到变化
 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: '关闭',
  ref_key: '3'
 }],
 deleteList: [],
 model: {
  timeLineList: [],
 },

 }
 },
 methods: {
 /**
 * 提交修改的信息
 */
 submit: function () {
 this.$refs.form.validate((valid) => {
  if (!valid) {
  this.$message.error('请填写正确信息');
  return;
  }


  console.log('编辑里程碑结果:')
  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('确认删除该记录吗?', '提示', {
  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.js组件的教程,请大家点击专题vue.js组件学习教程进行学习。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
HTML中事件触发列表与解说
Jul 09 Javascript
Javascript面向对象编程
Mar 18 Javascript
jquery+ajax验证不通过也提交表单问题处理
Dec 12 Javascript
JavaScript中继承用法实例分析
May 16 Javascript
JS控制TreeView的结点选择
Nov 11 Javascript
JS实现批量上传文件并显示进度功能
Jun 27 Javascript
最全的JavaScript开发工具列表 总有一款适合你
Jun 29 Javascript
javascript按钮禁用和启用的效果实例代码
Oct 29 Javascript
Vue底层实现原理总结
Feb 17 Javascript
详解.vue文件解析的实现
Jun 11 Javascript
小程序视频列表中视频的播放与停止的示例代码
Jul 20 Javascript
jQuery实现左右两个列表框的内容相互移动功能示例
Jan 27 jQuery
uniapp与webview之间的相互传值的实现
Jun 29 #Javascript
基于Element封装一个表格组件tableList的使用方法
Jun 29 #Javascript
iview实现图片上传功能
Jun 29 #Javascript
vue+animation实现翻页动画
Jun 29 #Javascript
vue+element实现图片上传及裁剪功能
Jun 29 #Javascript
vue实现匀速轮播效果
Jun 29 #Javascript
vant实现购物车功能
Jun 29 #Javascript
You might like
PHP中的CMS的涵义
2007/03/11 PHP
PHP 文本文章分页代码 按标记或长度(不涉及数据库)
2012/06/07 PHP
PHP学习笔记之session
2018/05/06 PHP
javascript+xml技术实现分页浏览
2008/07/27 Javascript
javascript获得服务器端控件的ID的实现代码
2011/12/28 Javascript
javascript break指定标签打破多层循环示例
2014/01/20 Javascript
Jquery实现自定义tooltip示例代码
2014/02/12 Javascript
jquery实现文本框数量加减功能的例子分享
2014/05/10 Javascript
js 将图片连接转换成base64格式的简单实例
2016/08/10 Javascript
BootStrapTable服务器分页实例解析
2016/12/20 Javascript
bootstrap table单元格新增行并编辑
2017/05/19 Javascript
微信小程序 地图map实例详解
2017/06/07 Javascript
jQuery实现返回顶部按钮和scroll滚动功能[带动画效果]
2017/07/05 jQuery
JS HTML图片显示Canvas 压缩功能
2017/07/21 Javascript
cordova入门基础教程及使用中遇到的一些问题总结
2017/11/14 Javascript
axios中cookie跨域及相关配置示例详解
2017/12/20 Javascript
vue实现动态按钮功能
2019/05/13 Javascript
微信小程序实现蒙版弹出窗功能
2019/09/17 Javascript
Vue.js自定义指令学习使用详解
2019/10/19 Javascript
浅谈Python实现2种文件复制的方法
2018/01/19 Python
python实现Flappy Bird源码
2018/12/24 Python
Python使用sklearn库实现的各种分类算法简单应用小结
2019/07/04 Python
python 批量添加的button 使用同一点击事件的方法
2019/07/17 Python
django 使用 PIL 压缩图片的例子
2019/08/16 Python
详解使用PyInstaller将Pygame库编写的小游戏程序打包为exe文件
2019/08/23 Python
pip安装tensorflow的坑的解决
2020/04/19 Python
Spartoo英国:欧洲最大的网上鞋店
2016/09/13 全球购物
美国中小型企业领先的办公家具供应商:Office Designs
2016/11/26 全球购物
建筑工程专业学生的自我评价
2013/12/25 职场文书
爱护草坪标语
2014/06/24 职场文书
接触艺术对孩子学习思维有益
2019/08/06 职场文书
七年级话题作文之执着
2019/11/19 职场文书
导游词之绍兴柯岩古镇
2020/01/09 职场文书
基于python定位棋子位置及识别棋子颜色
2021/07/26 Python
如何利用 CSS Overview 面板重构优化你的网站
2021/10/24 HTML / CSS
vue 实现弹窗关闭后刷新效果
2022/04/08 Vue.js