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 相关文章推荐
28个JS验证函数收集
Mar 02 Javascript
中文路径导致unitpngfix.js不正常的解决方法
Jun 26 Javascript
Tab切换组件(选项卡功能)实例代码
Nov 21 Javascript
JavaScript中的typeof操作符用法实例
Apr 05 Javascript
原生javascript实现获取指定元素下所有后代元素的方法
Oct 28 Javascript
node.js中的fs.unlink方法使用说明
Dec 15 Javascript
jQuery解析与处理服务器端返回xml格式数据的方法详解
Jul 04 Javascript
JS 动态判断PC和手机浏览器实现代码
Sep 21 Javascript
JavaScript中值类型和引用类型的区别
Feb 23 Javascript
百度地图JavascriptApi Marker平滑移动及车头指向行径方向
Mar 13 Javascript
微信小程序 获取二维码实例详解
Jun 23 Javascript
元素全屏的设置与监听实例
Nov 28 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
PHP函数实现从一个文本字符串中提取关键字的方法
2015/07/01 PHP
如何利用http协议发布博客园博文评论
2015/08/03 PHP
示例详解Laravel重置密码代码重构
2016/08/10 PHP
PHP入门教程之字符串处理技巧总结(转换,过滤,解析,查找,截取,替换等)
2016/09/11 PHP
php获取数据库中数据的实现方法
2017/06/01 PHP
基于PHP实现短信验证码发送次数限制
2020/07/11 PHP
番茄的表单验证类代码修改版
2008/07/18 Javascript
编写跨浏览器的javascript代码必备[js多浏览器兼容写法]
2008/10/29 Javascript
jquery选择器之属性过滤选择器详解
2014/01/27 Javascript
js或jquery实现页面打印可局部打印
2014/03/27 Javascript
使用变量动态设置js的属性名
2014/10/19 Javascript
关于javascript模块加载技术的一些思考
2014/11/28 Javascript
javascript实现页面刷新时自动清空表单并选中的方法
2015/07/18 Javascript
jQuery插件EasyUI校验规则 validatebox验证框
2015/11/29 Javascript
第三篇Bootstrap网格基础
2016/06/21 Javascript
关于在Servelet中如何获取当前时间的操作方法
2016/06/28 Javascript
详解Node.js:events事件模块
2016/11/24 Javascript
在使用JSON格式处理数据时应该注意的问题小结
2017/05/20 Javascript
CSS3结合jQuery实现动画效果及回调函数的实例
2017/12/27 jQuery
BootstrapValidator实现表单验证功能
2019/11/08 Javascript
理解Proxy及使用Proxy实现vue数据双向绑定操作
2020/07/18 Javascript
js利用iframe实现选项卡效果
2020/08/09 Javascript
vue-cli3 引入 font-awesome的操作
2020/08/11 Javascript
python实战教程之自动扫雷
2018/07/13 Python
tensorflow更改变量的值实例
2018/07/30 Python
Python hashlib加密模块常用方法解析
2019/12/18 Python
Python列表元素删除和remove()方法详解
2021/01/04 Python
英国著名的化妆品折扣网站:Allbeauty.com
2016/07/21 全球购物
英国马莎百货官网:Marks & Spencer
2016/07/29 全球购物
宝拉珍选美国官网:Paula’s Choice美国
2018/01/07 全球购物
生日宴会主持词
2014/03/20 职场文书
中学生家长评语大全
2014/04/16 职场文书
县长群众路线对照检查材料思想汇报
2014/10/02 职场文书
捐款感谢信
2015/01/20 职场文书
2016思想纪律作风整顿心得体会
2016/01/23 职场文书
MySQL 条件查询的常用操作
2022/04/28 MySQL