前言
案列中的jquery来源:https://www.jq22.com/jquery-info18500,本次改造对里面的js文件进行了改造(原先的立即执行函数引入到vue组件中会出现渲染两次的情况)
效果图:
一、安装jquery
1.cnpm安装
代码如下(示例):
cnpm install jquery --save
2.在main.js中引入jquery
代码如下(示例):
// 引入jquery
import $ from 'jquery'
window.$ = $
3.在vue.config.js中对jquery进行配置
代码如下(示例):
chainWebpack: (config) => {
config.resolve.alias
// jquery配置
.set('jquery', resolve('./node_modules/jquery/src/jquery'))
.set('scrolls', resolve('src/utils/jq/jqueryAt.js')) //这个jqueryAt.js文件就是在https://www.jq22.com/jquery-info18500 案列中下载下来的js文件,但是在本案列中对其改造了,文章末尾会贴上代码
}
二、在 vue 组件中正式渲染时间段
1.完整的 vue 代码如下,千万别忘了引入对应的css文件
<template>
<div>
<div class="kaoqing" id="demo1"></div>
</div>
</template>
<script>
import * as $ from "jquery";
export default {
name: "HelloWorld",
props: {
msg: String,
},
data() {
return {
data3: [
{
startime: "2018-03-07 01:30:00",
endtime: "2018-03-07 23:00:00",
},
{
startime: "2018-03-08 01:30:00",
endtime: "2018-03-08 05:30:00",
},
{
startime: "2018-03-05 16:30:00",
endtime: "2018-03-05 20:30:00",
},
{
startime: "2018-03-05 01:30:00",
endtime: "2018-03-05 02:00:00",
},
],
};
},
mounted() {
//渲染函数
if ($("#demo1")) {
import("../assets/jq/drag4").then((f) => {
f.default($);
$("#demo1").initJuicy({
width: 800,
mondayDate: "2018-03-05",
timedata: this.data3,
status: true, //false表示不能编辑,true可以编辑
});
});
}
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
@import "../styles/style.css"; //直接使用案列中下载的就行,本文章末尾会贴出完成代码,直接复制过去也可以
</style>
有个需要注意的小问题:因为 offset() 要在组件内容可见的情况下才会执行,所以如果你的 vue 文件是一个弹窗的话可能会报 图1 的错误,只需要把写在 mounted里的渲染函数写到弹窗显示的函数里执行即可
// 图1 /
// 图2 /
三、在 vue 组件中使用到的 js 以及 css 文件完整代码,直接 cv 即可
1.经过改造的 jqueryAt.js
/**
* Created by juicy on 2018-3-10.上一稳定版本为drag2,添加左边左滑
* 按格子移动,数据格式为日期
*/
export default function ($) {
'use strict'
$.fn.initJuicy = function (data) {
return new MyinitJuicy(data, this)
}
var perwidth = 0
var MyinitJuicy = function (data, that) {
var me = this
me.init(data, that)
me.offsetleft = $(that).offset().left + 80
}
MyinitJuicy.prototype.getdata = function () {
var backdata = []
var monday = $('.kaoqing').data('monday')
$.each($('.weekday'), function (i, obj) {
var thisday = getNextDate(monday, i)
$.each($(obj).find('.item'), function (j, obj1) {
var x = parseFloat($(obj1).css('left')) / perwidth
var y = parseFloat($(obj1).css('width')) / perwidth + x
var startime =
Math.round(x) % 2 == 0
? thisday + ' ' + ('0' + Math.round(x) / 2).slice(-2) + ':00:00'
: thisday + ' ' + ('0' + parseInt(Math.round(x) / 2)).slice(-2) + ':30:00'
var endtime =
Math.round(y) % 2 == 0
? thisday + ' ' + ('0' + Math.round(y) / 2).slice(-2) + ':00:00'
: thisday + ' ' + ('0' + parseInt(Math.round(y) / 2)).slice(-2) + ':30:00'
backdata.push({
startime: startime,
endtime: endtime,
})
})
})
return backdata
}
// 初始化
MyinitJuicy.prototype.init = function (data, that) {
var me = this
me.current = 0 //新增编号
me.cando = true //当前位置是否允许新增
me.nowmove = -1 //当前向左向右拖动的序号
me.newcreate = true
me.opts = $.extend(
true,
{},
{
//用于设弹窗默认值
width: 900,
mondayDate: '',
timedata: [], //[{startime:,endtime:},]
status: true,
data1: [
{
type: '周一',
timeSlot: [],
},
{
type: '周二',
timeSlot: [],
},
{
type: '周三',
timeSlot: [],
},
{
type: '周四',
timeSlot: [],
},
{
type: '周五',
timeSlot: [],
},
{
type: '周六',
timeSlot: [],
},
{
type: '周日',
timeSlot: [],
},
],
},
data
)
me.mousedown = false
//初始化
var str = ''
var boxwidth = me.opts.width
var navwidth = me.opts.width - 90
me.perwidth = perwidth = navwidth / 48
$(that).css('width', boxwidth + 'px')
$(that).attr('data-monday', me.opts.mondayDate)
var data3 = me.opts.timedata
var timedata = me.opts.data1
// for (var i = 0; i < 7; i++) {
// //渲染出 YYYY-MM-DD 中的月和日,此处用不到
// timedata[i]['type'] += getNextDay(me.opts.mondayDate, i)
// console.log('时间插槽', timedata[i]['type'])
// }
$.each(data3, function (i, obj) {
//时间段有颜色部分数据渲染
var day = new Date(obj.startime.replace(/-/g, '/')).getDay() - 1
if (day == -1) day = 6
timedata[day]['timeSlot'].push([getMytime(obj.startime), getMytime(obj.endtime)])
})
for (var i = 0; i < 7; i++) {
str += '<div class="weekday">' + '<div class=xq>' + timedata[i].type + '</div>' + '<div>' + '<div class="day">'
for (var j = 0; j < 24; j++) {
str += '<div class="hour"><div class="halfhour"></div></div>'
}
str += '<div class="hour"></div></div><div class="bar">'
if (timedata.length == 0) {
str += '</div></div></div>'
} else {
for (var t = 0; t < timedata[i].timeSlot.length; t++) {
var left = (navwidth * timedata[i].timeSlot[t][0]) / 24
var width = (navwidth * (timedata[i].timeSlot[t][1] - timedata[i].timeSlot[t][0])) / 24
str +=
'<div class="item item' +
me.current +
'" style="left:' +
left +
'px;width:' +
width +
'px" data-num="' +
me.current +
'">' +
'<div class="bleft"></div><div class="bright"></div></div>'
me.current++
}
str += '</div></div></div>'
}
}
var $str = $(str)
$(that).append($str)
//点在蓝条条上就禁止它新建了
if (me.opts.status) {
$('.bright,.bleft').css('cursor', 'e-resize')
$str.find('.item').on('mousedown', function (e) {
me.cando = false
return false
})
$str.find('.bar').on('mousedown', function (e) {
if (me.cando) {
me.mousedown = true
me.newcreate = true
fnstart(e, me, this)
}
return false //防止事件冒泡
})
$('body').on('mouseup', function (e) {
me.cando = true
if (me.mousedown) {
me.mousedown = false
fnend(me)
me.nowmove = -1
}
return false //防止事件冒泡
})
$str.find('.bright').on('mousedown', function (e) {
me.mousedown = true
me.newcreate = false
me._startX = e.pageX
me.direction = 'right'
me.width = parseFloat($(this).parent().css('width')) //会实时变化
me.left = parseFloat($(this).parent().css('left')) //会实时变化
me.startwidth = parseFloat($(this).parent().css('width')) //是个常数
me.startleft = parseFloat($(this).parent().css('left')) //是个常数
me.nowmove = parseFloat($(this).parent().data('num'))
return false
})
$str.find('.bleft').on('mousedown', function (e) {
me.mousedown = true
me.newcreate = false
me._startX = e.pageX
me.direction = 'left'
me.width = parseFloat($(this).parent().css('width')) //会实时变化
me.left = parseFloat($(this).parent().css('left')) //会实时变化
me.startwidth = parseFloat($(this).parent().css('width')) //是个常数
me.startleft = parseFloat($(this).parent().css('left')) //是个常数
me.nowmove = parseFloat($(this).parent().data('num'))
return false
})
//注意:move事件一定要绑在body上,当鼠标移动过快可能移除那个div区域
$('body').on('mousemove', function (e) {
if (me.mousedown && me.newcreate) {
fnmove(e, me)
} else if (me.mousedown && !me.newcreate) {
if (me.direction && me.direction == 'left') {
fnmoveleft(e, me)
} else if (me.direction && me.direction == 'right') {
fnmoveright(e, me)
}
} else {
e.preventDefault()
}
})
} else {
$('.bright,.bleft').css('cursor', 'default')
}
}
function fnmoveleft(e, me) {
console.log('左边不是新建' + me.startwidth)
me._curX = e.pageX
me._curY = e.pageY
me._moveX = me._startX - me._curX
var item = '.item' + me.nowmove
var left = me.startleft - me._moveX
var width = me.startwidth + me._moveX
//左边的向左拉,不超过左边边界
if (me._moveX > 0 && me._moveX < me.startleft) {
$(item).css({
width: width + 'px',
left: left + 'px',
})
me.width = width
me.left = left
} else if (me._moveX > 0 && me._moveX >= me.startleft) {
//左边的向左拉,超过左边边界
$(item).css({
width: me.startleft + me.startwidth + 'px',
left: 0,
})
me.width = me.startleft + me.startwidth
me.left = 0
} else if (me._moveX < 0 && -me._moveX <= me.startwidth) {
//左边的向右拉,不能超过当前右边的0.5小时
$(item).css({
width: width + 'px',
left: left + 'px',
})
me.width = width
me.left = left
} else if (me._moveX < 0 && -me._moveX > me.startwidth) {
//左边的向右拉,超过最右边
$(item).css({
width: 0,
left: me.startwidth + me.startleft + 'px',
})
me.width = 0
me.left = me.startwidth + me.startleft
}
}
function fnmoveright(e, me) {
console.log('右边不是新建' + me.startwidth)
me._curX = e.pageX
me._curY = e.pageY
me._moveX = me._curX - me._startX
var item = '.item' + me.nowmove
var left = me.startleft
var width = me.startwidth + me._moveX
//右边的向右拉,不超过右边边界
if (me._moveX > 0 && me._moveX < me.perwidth * 48 - me.startleft - me.startwidth) {
$(item).css({
width: width + 'px',
left: left + 'px',
})
me.width = width
} else if (me._moveX > 0 && me._moveX >= me.perwidth * 48 - me.startleft - me.startwidth) {
//右边的向右拉,超过右边边界
$(item).css({
width: me.perwidth * 48 - left + 'px',
left: left + 'px',
})
me.width = me.perwidth * 48 - left
} else if (me._moveX < 0 && -me._moveX <= me.startwidth) {
//右边的向左拉,不能超过当前左边的0.5小时
$(item).css({
width: width + 'px',
left: left + 'px',
})
me.width = width
} else if (me._moveX < 0 && -me._moveX > me.startwidth) {
//右边的向左拉,超过最左边
$(item).css({
width: 0,
left: left + 'px',
})
me.width = 0
}
}
function fnstart(e, me, that) {
me._startX = e.pageX
var left = me._startX - me.offsetleft
me.left = nearest(left)
me.startleft = nearest(left)
me.nowmove = me.current
var str =
'<div class="item item' +
me.current +
'" style="left:' +
me.left +
'px;width:1px" data-num="' +
me.current +
'">' +
'<div class="bleft"></div><div class="bright"></div></div>'
me.current++
var item = '.item' + (me.current - 1)
$(that).append($(str))
if (me.opts.status) {
$('.bright,.bleft').css('cursor', 'e-resize')
$(item).on('mousedown', function (e) {
me.cando = false
return false
})
$(item)
.find('.bright')
.on('mousedown', function (e) {
me.mousedown = true
me.newcreate = false
me._startX = e.pageX
me.direction = 'right'
me.width = parseFloat($(this).parent().css('width')) //会实时变化
me.left = parseFloat($(this).parent().css('left')) //会实时变化
me.startwidth = parseFloat($(this).parent().css('width')) //是个常数
me.startleft = parseFloat($(this).parent().css('left')) //是个常数
me.nowmove = parseFloat($(this).parent().data('num'))
return false
})
$(item)
.find('.bleft')
.on('mousedown', function (e) {
me.mousedown = true
me.newcreate = false
me._startX = e.pageX
me.direction = 'left'
me.width = parseFloat($(this).parent().css('width')) //会实时变化
me.left = parseFloat($(this).parent().css('left')) //会实时变化
me.startwidth = parseFloat($(this).parent().css('width')) //是个常数
me.startleft = parseFloat($(this).parent().css('left')) //是个常数
me.nowmove = parseFloat($(this).parent().data('num'))
return false
})
} else {
$('.bleft,.bright').css('cursor', 'default')
}
}
function fnmove(e, me) {
console.log('新建' + me.nowmove + me.left)
me._curX = e.pageX
me._curY = e.pageY
me._moveX = me._curX - me._startX
var item = '.item' + (me.current - 1)
if (me._moveX > 0 && me._moveX < me.perwidth * 48 - me.startleft) {
me.width = me._moveX
$(item).css('width', me._moveX + 'px')
// $(item).css("width", me._moveX + 'px')
} else if (me._moveX > 0 && me._moveX >= me.perwidth * 48 - me.startleft) {
me.width = me.perwidth * 48 - me.startleft
$(item).css('width', me.perwidth * 48 - me.startleft + 'px')
} else {
me.width = 0
$(item).css('width', 0)
}
}
function fnend(me, i) {
var width = me.width
var left = me.left
var item = '.item' + me.nowmove
if (width == 0) {
$(item).remove()
} else {
$(item).css('width', nearest(width) + 'px')
$(item).css('left', nearest(left) + 'px')
var result = xiaoxiannvbianshen(item)
var items = $(item).parent().find('.item')
if (result.length < items.length) {
$.each(items, function (i, obj) {
if (i < result.length) {
$(obj).css({
left: result[i][0] + 'px',
width: result[i][1] + 'px',
})
} else {
$(obj).remove()
}
})
}
}
//松手后才能修改值
}
function nearest(left) {
var yu = left % perwidth
if (yu < perwidth / 2) {
return left - yu
} else {
return left + (perwidth - yu)
}
}
function getMytime(date) {
if (date.split(' ')[1] == '24:00:00') {
return 24
} else {
var time = new Date(date.replace(/-/g, '/'))
if (time.getMinutes() > 10) {
return time.getHours() + 0.5
} else {
return time.getHours()
}
}
}
function getNextDay(d, i) {
var monday = new Date(d.replace(/-/g, '/'))
monday = monday.getTime() + 1000 * 60 * 60 * 24 * i
monday = new Date(monday)
return monday.getMonth() + 1 + '/' + monday.getDate()
}
function getNextDate(d, i) {
var monday = new Date(d.replace(/-/g, '/'))
monday = monday.getTime() + 1000 * 60 * 60 * 24 * i
monday = new Date(monday)
return (
monday.getFullYear() + '-' + ('0' + (monday.getMonth() + 1)).slice(-2) + '-' + ('0' + monday.getDate()).slice(-2)
)
}
function xiaoxiannvbianshen(item) {
var array = []
var arrayresult = []
var $item = $(item).parent().find('.item')
$.each($item, function (i, obj) {
var left = parseFloat($(obj).css('left'))
var width = parseFloat($(obj).css('width'))
array.push([left, left + width])
})
var sortarray = bubbleSort(array)
//var sortarray = array.sort();
var temp = sortarray[0]
console.log('排序后:')
console.log(sortarray)
for (var i = 0; i < sortarray.length; i++) {
if (!sortarray[i + 1]) {
arrayresult.push(temp)
break
}
if (temp[1] < sortarray[i + 1][0]) {
arrayresult.push(temp)
temp = sortarray[i + 1]
} else {
if (temp[1] <= sortarray[i + 1][1]) {
temp = [temp[0], sortarray[i + 1][1]]
} else {
temp = [temp[0], temp[1]]
}
}
}
console.log('小仙女变身后:')
console.log(arrayresult)
var huanyuan = []
for (var j = 0; j < arrayresult.length; j++) {
huanyuan.push([arrayresult[j][0], arrayresult[j][1] - arrayresult[j][0]])
}
return huanyuan
}
function bubbleSort(array) {
for (var unfix = array.length - 1; unfix > 0; unfix--) {
for (var i = 0; i < unfix; i++) {
if (array[i][0] > array[i + 1][0]) {
var temp = array[i]
array.splice(i, 1, array[i + 1])
array.splice(i + 1, 1, temp)
}
}
}
return array
}
}
2.style.css 的完整文件
.kaoqing {
/*width: 800px;*/
}
*{
box-sizing: border-box;
}
body {
background-color: #e3e3e3;
}
.bar {
background-color: #fff;
border: 1px solid #555;
position: relative;
margin: 0 auto 20px 0;
height: 20px;
width: calc(100% + 1px);
width: -webkit-calc(100% + 1px);
}
/*刻度*/
.day {
position: relative;
margin: 20px auto 0 0;
height: 10px;
box-sizing: border-box;
}
.day .hour {
position: absolute;
border-left: 1px solid #555;
height: 10px;
width: calc(1 / 24 * 100%);
}
.day .halfhour {
position: absolute;
border-left: 1px solid #555;
height: 7px;
width: 50%;
top: 4px;
}
.day .hour:after {
position: absolute;
top: -15px;
font: 11px/1 sans-serif;
}
.day .hour:nth-of-type(1) {
left: 0%;
}
.day .hour:nth-of-type(1):after {
content: "0";
}
.day .hour:nth-of-type(2) {
left: calc(1 / 24 * 1 * 100%);
}
.day .hour:nth-of-type(2):after {
/*content: "1";*/
}
.day .hour:nth-of-type(3) {
left: calc(1 / 24 * 2 * 100%);
}
.day .hour:nth-of-type(3):after {
content: "2";
}
.day .hour:nth-of-type(4) {
left: calc(1 / 24 * 3 * 100%);
}
.day .hour:nth-of-type(4):after {
/*content: "3";*/
}
.day .hour:nth-of-type(5) {
left: calc(1 / 24 * 4 * 100%);
}
.day .hour:nth-of-type(5):after {
content: "4";
}
.day .hour:nth-of-type(6) {
left: calc(1 / 24 * 5 * 100%);
}
.day .hour:nth-of-type(6):after {
/*content: "5";*/
}
.day .hour:nth-of-type(7) {
left: calc(1 / 24 * 6 * 100%);
}
.day .hour:nth-of-type(7):after {
content: "6";
}
.day .hour:nth-of-type(8) {
left: calc(1 / 24 * 7 * 100%);
}
.day .hour:nth-of-type(8):after {
/*content: "7";*/
}
.day .hour:nth-of-type(9) {
left: calc(1 / 24 * 8 * 100%);
}
.day .hour:nth-of-type(9):after {
content: "8";
}
.day .hour:nth-of-type(10) {
left: calc(1 / 24 * 9 * 100%);
}
.day .hour:nth-of-type(10):after {
/*content: "9";*/
}
.day .hour:nth-of-type(11) {
left: calc(1 / 24 * 10 * 100%);
}
.day .hour:nth-of-type(11):after {
content: "10";
}
.day .hour:nth-of-type(12) {
left: calc(1 / 24 * 11 * 100%);
}
.day .hour:nth-of-type(12):after {
/*content: "11";*/
}
.day .hour:nth-of-type(13) {
left: calc(1 / 24 * 12 * 100%);
}
.day .hour:nth-of-type(13):after {
content: "12";
}
.day .hour:nth-of-type(14) {
left: calc(1 / 24 * 13 * 100%);
}
.day .hour:nth-of-type(14):after {
/*content: "13";*/
}
.day .hour:nth-of-type(15) {
left: calc(1 / 24 * 14 * 100%);
}
.day .hour:nth-of-type(15):after {
content: "14";
}
.day .hour:nth-of-type(16) {
left: calc(1 / 24 * 15 * 100%);
}
.day .hour:nth-of-type(16):after {
/*content: "15";*/
}
.day .hour:nth-of-type(17) {
left: calc(1 / 24 * 16 * 100%);
}
.day .hour:nth-of-type(17):after {
content: "16";
}
.day .hour:nth-of-type(18) {
left: calc(1 / 24 * 17 * 100%);
}
.day .hour:nth-of-type(18):after {
/*content: "17";*/
}
.day .hour:nth-of-type(19) {
left: calc(1 / 24 * 18 * 100%);
}
.day .hour:nth-of-type(19):after {
content: "18";
}
.day .hour:nth-of-type(20) {
left: calc(1 / 24 * 19 * 100%);
}
.day .hour:nth-of-type(20):after {
/*content: "19";*/
}
.day .hour:nth-of-type(21) {
left: calc(1 / 24 * 20 * 100%);
}
.day .hour:nth-of-type(21):after {
content: "20";
}
.day .hour:nth-of-type(22) {
left: calc(1 / 24 * 21 * 100%);
}
.day .hour:nth-of-type(22):after {
/*content: "21";*/
}
.day .hour:nth-of-type(23) {
left: calc(1 / 24 * 22 * 100%);
}
.day .hour:nth-of-type(23):after {
content: "22";
}
.day .hour:nth-of-type(24) {
left: calc(1 / 24 * 23 * 100%);
}
.day .hour:nth-of-type(24):after {
/*content: "23";*/
}
.day .hour:nth-of-type(25) {
left: calc(1 / 24 * 24 * 100%);
width: 1px;
}
.day .hour:nth-of-type(25):after {
content: "24";
}
.day .hour:after {
text-indent: -0.5em;
}
.day .halfhour {
left: 50%;
}
.weekday {
position: relative;
overflow: hidden;
padding-right: 10px;
}
.weekday>div:nth-child(1) {
width: 80px;
position: relative;
top: 25px;
text-align: center;
user-select: none;
float: left;
}
.weekday>div:nth-child(2) {
margin-left: 80px;
}
.bar div {
display: inline-block;
}
.item {
position: absolute;
top: 0;
/*width: 10px;*/
/*width:calc(1 / 24 * 4 * 100%);*/
height: 100%;
background-color: #8dc8ff;
/*overflow: hidden;*/
}
.bright {
width: 10px;
height: 100%;
/*cursor: e-resize;*/
background: transparent;
position: absolute;
right:-5px ;
top: 0;
z-index: 1;
}
.bleft {
width: 10px;
height: 100%;
/*cursor: e-resize;*/
background: transparent;
position: absolute;
left:-5px ;
top: 0;
z-index: 1;
}