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 相关文章推荐
jQuery实现的类flash菜单效果代码
May 17 Javascript
jQuery hover 延时器实现代码
Mar 12 Javascript
jQuery效果 slideToggle() 方法(在隐藏和显示之间切换)
Jun 28 Javascript
JavaScript中数据结构与算法(三):链表
Jun 19 Javascript
javascript特殊文本输入框网页特效
Sep 13 Javascript
js转html实体的方法
Sep 27 Javascript
JavaScript中document.referrer的用法详解
Jul 04 Javascript
jQuery实现每隔一段时间自动更换样式的方法分析
May 03 jQuery
bootstrap table插件动态加载表头
Jul 19 Javascript
详解Vue的watch中的immediate与watch是什么意思
Dec 30 Javascript
JQuery通过键盘控制键盘按下与松开触发事件
Aug 07 jQuery
原生JavaScript实现轮播图
Jan 10 Javascript
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
MYSQL数据库初学者使用指南
2006/11/16 PHP
phpcms中的评论样式修改方法
2016/10/21 PHP
css把超出的部分显示为省略号的方法兼容火狐
2008/07/23 Javascript
javascript 限制输入和粘贴(IE,firefox测试通过)
2008/11/14 Javascript
juqery 学习之三 选择器 层级 基本
2010/11/25 Javascript
兼容各大浏览器的JavaScript阻止事件冒泡代码
2015/07/09 Javascript
常用的Javascript数据验证插件
2015/08/04 Javascript
深入浅析JavaScript中的arguments对象(强力推荐)
2016/06/03 Javascript
Bootstrap作品展示站点实战项目2
2016/10/14 Javascript
简单实现Vue的observer和watcher
2016/12/21 Javascript
Angular 通过注入 $location 获取与修改当前页面URL的实例
2017/05/31 Javascript
JavaScript基础之this详解
2017/06/04 Javascript
使用Angular CLI生成 Angular 5项目教程详解
2018/03/18 Javascript
基于jQuery ztree实现表格风格的树状结构
2018/08/31 jQuery
解决Angular4项目部署到服务器上刷新404的问题
2018/08/31 Javascript
解决angularjs WdatePicker ng-model的问题
2018/09/13 Javascript
vue axios请求频繁时取消上一次请求的方法
2018/11/10 Javascript
详解小程序之简单登录注册表单验证
2019/05/13 Javascript
js获取 gif 的帧数的代码实例
2019/09/10 Javascript
vscode 使用Prettier插件格式化配置使用代码详解
2020/08/10 Javascript
js实现特别简单的钟表效果
2020/09/14 Javascript
简单学习Python多进程Multiprocessing
2017/08/29 Python
基于Python3.6+splinter实现自动抢火车票
2018/09/25 Python
Python XlsxWriter模块Chart类用法实例分析
2019/03/11 Python
Python实现栈和队列的简单操作方法示例
2019/11/29 Python
Python简单实现区域生长方式
2020/01/16 Python
python新式类和经典类的区别实例分析
2020/03/23 Python
10 套华丽的CSS3 按钮小结
2012/10/03 HTML / CSS
利用CSS3实现文本框的清除按钮相关的一些效果
2015/06/23 HTML / CSS
银行求职推荐信范文
2013/11/30 职场文书
最新大学职业规划书范文
2013/12/30 职场文书
综合实践教学反思
2014/01/31 职场文书
岗位廉洁从政承诺书
2014/03/27 职场文书
2014年社区妇联工作总结
2014/12/02 职场文书
雷峰塔导游词
2015/02/09 职场文书
服务器nginx权限被拒绝解决案例
2022/09/23 Servers