springboot+thymeleaf+mybatis實現(xiàn)甘特圖的詳細(xì)過程
首先我們要明白:這個甘特圖需要哪些動態(tài)數(shù)據(jù)。
(1)需要:ID,tName,number,計劃開始時間,開始時間,計劃結(jié)束時間,結(jié)束時間,項目負(fù)責(zé)人,參與人,知情人ID,計劃時長(可以計算得出的,不必在數(shù)據(jù)庫中);前置任務(wù);項目進(jìn)度,該任務(wù)屬于哪個任務(wù)

(2)然后利用easycode插件生成實體類,映射類,服務(wù)類,ontCroller等
(3)利用bootstrap框架做出甘特圖的樣式,寫好JS。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleleaf.org">
<head>
<title>ganttu.html</title>
<meta name="keywords" content="keyword1,keyword2,keyword3" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="reason" content="甘特圖的實際進(jìn)度與計劃進(jìn)度可能不符,為了展示實際進(jìn)度與計劃進(jìn)度的差異和方便統(tǒng)計,自己寫了個甘特圖框架" />
<meta name="mast" content="使用代碼之前請留言,禁止轉(zhuǎn)載..." />
<meta name="description" content="liuyuhang 的甘特圖,當(dāng)前版本1.0,2019-02-19" />
<meta name="description" content="時間日期格式:yyyy-mm-dd" />
<meta name="description" content="①計劃進(jìn)度與實際進(jìn)度雙重進(jìn)度體系" />
<meta name="description" content="②有前置任務(wù)連接線" />
<meta name="description" content="③可修改圖顏色" />
<meta name="description" content="④可隱藏與展示列" />
<meta name="description" content="⑤可隱藏域展示子項目" />
<meta name="description" content="⑥可跳轉(zhuǎn)時間到當(dāng)前時間" />
<meta name="description" content="⑦可從當(dāng)前項目開始時間查看" />
<meta name="description" content="⑦可隱藏某時間之前的內(nèi)容" />
<meta name="warning" content="⑧未做圖拖拽,并不打算做..." />
<meta name="author" content="liuyuhang 13501043063" />
<!-- 只引用了這些,其余的并沒有引用 -->
<link rel="external nofollow" rel="stylesheet" />
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style type="text/css">
#ganttu-head {
height: 70px;
background-color: #dddddd;
padding: 10px 20px;
}
#ganttu-body {
min-height: 780px;
background-color: #eeeeee;
padding: 10px 20px;
font-size: 20px;
}
#ganttu-index-projectName {
display: inline;
padding: 5px 15px;
background-image: linear-gradient(to left, #222222 0%, #222222 75%, #000000 100%);
color: white;
border-radius: 18px;
}
#ganttu-index-projectDesc {
display: inline;
padding: 5px 15px;
background-image: linear-gradient(to left, #777777 0%, #777777 75%, #333333 100%);
color: white;
border-radius: 18px;
}
td {
white-space: nowrap
}
</style>
</head>
<body>
<div id='ganttu-head' class='col-lg-12 col-md-12 col-sm-12 col-xs-12' style="height:100px" >
<div style='display: inline;font-size: 30px;font-weight: normal;padding: 5px 15px;'>甘特圖面板</div>
<div id='ganttu-index-projectName'>此項目 名稱...</div>
<div id='ganttu-index-projectDesc'>此項目描述...</div>
</div>
<div id='ganttu-body' class='col-lg-12 col-md-12 col-sm-12 col-xs-12' style=';overflow-x:scroll;font-size:14px;'>
<!-- 甘特圖放到了這個div中 -->
<div id="lyh-ganttu" class='col-lg-12 col-md-12 col-sm-12 col-xs-12' style='position:relative;padding:0px;height:700px;'></div>
</div>
</body>
<script type="text/javascript" th:inline="javascript">
$(function() {
lyhGanttuInit('lyh-ganttu'); //甘特圖初始化
})
var lyhGanttuData=[[${lyhGanttuData}]];
/**
* 甘特圖設(shè)置,變量名固定
*/
var lyhGanttuConfig = {
start : '1900/01/01', //初始化開始時間配置 - 別在意
end : '1900/01/10', //初始化結(jié)束時間配置 - 別在意
planBorder : '#1a8cff', //計劃進(jìn)度的border顏色
planBackground : '#80bfff', //計劃進(jìn)度的back顏色
border : '#ffaa00', //實際進(jìn)度的border染顏色
background : '#ffcc66', //實際進(jìn)度的back顏色
lineColor : 'green', //前置任務(wù)線顏色
//表格中的thead的題頭設(shè)置,可按照格式任意添加或減少
labels : {
'projectName' : {
'name' : ' 任務(wù)名 ',
'show' : true,
}, //任務(wù)名
'projectCode' : {
'name' : '編號',
'show' : true,
}, //編號
'planStartAt' : {
'name' : '計劃開始',
'show' : true,
}, //計劃開始時間
'planEndAt' : {
'name' : '計劃結(jié)束',
'show' : false,
}, //計劃結(jié)束時間
'startAt' : {
'name' : '實際開始',
'show' : false,
}, //實際開始時間
'endAt' : {
'name' : '實際結(jié)束',
'show' : false,
}, //實際結(jié)束時間
'persent' : {
'name' : '完成比例',
'show' : true,
}, //完工百分比
'dur' : {
'name' : '時長',
'show' : true,
}, //持續(xù)時間
'resps' : {
'name' : '負(fù)責(zé)人',
'show' : true,
}, //負(fù)責(zé)人
'actors' : {
'name' : '參與人',
'show' : true,
}, //參與人
'insiders' : {
'name' : '知情人',
'show' : false,
}, //知情人
'before' : {
'name' : '前置任務(wù)',
'show' : false,
}, //前置任務(wù)
'operate' : {
'name' : "<button title='新建計劃' class='btn btn-primary btn-xs'><span class='glyphicon glyphicon-plus' style='margin-right:0px'></span></button>",
'show' : true,
}, //修改按鈕
}
}
/**
* 添加修改功能
*/
function lyhGanttuDataModifyByOperate() {
var data = lyhGanttuData.data;
for (var i = 0; i < data.length; i++) {
data[i]['operate'] = "<button title='修改此計劃' class='btn btn-primary btn-xs'><span class='glyphicon glyphicon-edit' style='margin-right:0px'></span></button>";
}
}
//================
//以下為甘特圖本身的繪圖代碼,調(diào)用lyhGanttuInit,參數(shù)為要加載甘特圖的id
//請使用谷歌瀏覽器,縮放倍數(shù)為100%
/**
* 甘特圖初始化函數(shù)
*/
function lyhGanttuInit(target) {
//重置日期設(shè)置緩存
lyhGanttuConfig.start = '1900/01/01';
lyhGanttuConfig.end = '1900/01/10';
lyhGanttuConfigModifyByDate(); //過濾所有時間,獲取時間長度
lyhGanttuDataModifyByOperate(); //添加點修改或新增數(shù)據(jù)按鈕
var table = lyhGanttuTable(target);
$('#' + target).html(table);
drawLink(target); //線條初始化
//提示工具初始化
$('#' + target).find('[title]').attr('data-toggle', 'tooltip').attr('data-placement', 'right');
$("[data-toggle='tooltip']").tooltip();
//標(biāo)記today
var today = lyhGanttuDate(new Date()); //今天的日期字符串
var todayIn = $('#' + target + ' .table thead tr #date').find('[data-original-title=\'' + today + '\']');
if (todayIn.length > 0) {
todayIn.addClass('todayDiv').css('background-color', 'orange').append($('<div>').css({
'height' : parseInt($('#' + target + ' .table').css('height').split('px')[0]) - 45 + 'px',
'position' : 'absolute',
'z-index' : 202,
'margin-top' : '-40px',
'margin-left' : '-10px',
'border-left' : '2px dashed red',
}).append($('<button>').addClass('btn btn-danger btn-xs todayBtn').css('margin-left', '3px').html(' today ')))
}
}
/**
* 繪制甘特圖基礎(chǔ)函數(shù)
*/
function lyhGanttuTable(target) {
var htr = $('<tr>').addClass('text-center');
var labels = lyhGanttuConfig.labels; //head的標(biāo)簽json
var start = lyhGanttuConfig.start; //總開始時間
var end = lyhGanttuConfig.end; //總結(jié)束時間
var pBorder = lyhGanttuConfig.planBorder;
var pBackground = lyhGanttuConfig.planBackground;
var border = lyhGanttuConfig.border;
var background = lyhGanttuConfig.background;
var indexBtn = $('<button>').addClass('btn btn-success btn-xs').append("<span class='glyphicon glyphicon-chevron-down' style='margin-right:0px'></span><span class='glyphicon glyphicon-chevron-right' style='display:none;margin-right:0px'></span>");
indexBtn.click(function() { //展開或隱藏所以有任務(wù)卡點擊函數(shù)
var me = $(this);
var indexBtnDown = me.find('.glyphicon-chevron-down'); //轉(zhuǎn)開狀態(tài)
var indexBtnRight = me.find('.glyphicon-chevron-right'); //隱藏狀態(tài)
var meTrs = $('#' + target + ' .table tr');
var meTdsHide = meTrs.find('div[hideId]');
if (indexBtnRight.is(':hidden')) { //若當(dāng)前為展開狀態(tài),則隱藏,同時調(diào)整按鈕
meTdsHide.parent().parent().hide(300);
indexBtnRight.show();
indexBtnDown.hide();
} else { //當(dāng)前為隱藏狀態(tài),則展開
meTdsHide.parent().parent().show(300);
indexBtnRight.hide();
indexBtnDown.show();
}
setTimeout(function() { //重新繪圖
drawLink('lyh-ganttu');
}, 400)
})
var index = $('<td>').append(indexBtn);
htr.append(index); //添加index
//循環(huán)添加label
for (var label in labels) {
var htd = $('<td>').append($('<div>').attr('id', label).html(labels[label].name));
if (labels[label].show != true) {
htd.css('display', 'none');
}
htr.append(htd);
}
//添加甘特圖的日期頭
var dataHtd = $('<td>').attr('id', 'date').css('width', '50%').css('padding', '0px');
var hDivs = lyhGanttuHeadDivs(target);
for (var i = 0; i < hDivs.length; i++) {
dataHtd.append(hDivs[i]);
}
htr.append(dataHtd);
//添加甘特圖的數(shù)據(jù)內(nèi)容
var tbody = $('<tbody>')
var data = lyhGanttuData.data;
for (var i = 0; i < data.length; i++) {
//寫入展開按鈕
var btr = $('<tr>').addClass('text-center').css('max-height', '40px');
if (data[i].pid == 0) {
var plusBtn = $('<button>').append("<span class='glyphicon glyphicon-flag' style='margin-right:0px'></span>").addClass('btn btn-success btn-xs').attr('title', '展開/隱藏-計劃').attr('id', data[i]['id']);
plusBtn.click(function() { //任務(wù)展開與隱藏按鈕點擊函數(shù)
var me = $(this);
var meId = me.attr('id');
var meTrs = $('#' + target + ' .table tr');
var meTdsHide = meTrs.find('div[hideId=' + meId + ']');
if (meTdsHide.is(':hidden')) { //已經(jīng)隱藏
meTdsHide.parent().parent().show(300);
} else {
meTdsHide.parent().parent().hide(300);
}
setTimeout(function() { //重新繪圖
drawLink('lyh-ganttu');
}, 400)
})
var plus = $('<td>').css('padding', '5px').append(plusBtn)
} else {
var plus = $('<td>').css('padding', '5px').append($('<div>').attr('id', data[i]['id']).attr('hideId', data[i]['pid']).attr('title', '工作包').append("<span class='glyphicon glyphicon-tasks' style='margin-right:0px'></span>"));
}
btr.append(plus)
//寫入數(shù)據(jù)
for (var label in labels) {
for (var key in data[i]) {
if (label == key) {
if (label.indexOf('At') > -1) { //若是時間數(shù)據(jù),則截取一下
var tda = $('<td>').css('padding', '5px').append($('<div>').addClass(key).html(data[i][key].substr(5, 5)).attr('title', data[i][key]))
} else if (label == 'resps' || label == 'actors' || label == 'insiders') { //負(fù)責(zé)人,參與人,知情人加載
var tda = $('<td>').css('padding', '5px').append($('<div>').addClass(key).html(data[i][key][0]).attr('title', data[i][key]));
} else if (label == 'before') { //前置任務(wù)
var befores = data[i][key];
var beforesNames = [];
if (befores.length > 0) {
for (var j = 0; j < data.length; j++) {
for (var k = 0; k < befores.length; k++) {
if (data[j].id == befores[k]) {
beforesNames.push(data[j].projectName);
}
}
}
} else {
beforesNames.push('無');
}
var tda = $('<td>').css('padding', '5px').append($('<div>').addClass(key).html(beforesNames[0]).attr('title', beforesNames));
} else { //其他信息加載
var tda = $('<td>').css('padding', '5px').append($('<div>').addClass(key).html(data[i][key]));
}
if (labels[label].show != true) { //該列是否展示
tda.hide();
}
if (label == 'planStartAt') {
tda.css('cursor', 'pointer')
tda.click(function() { //對planStartAt添加點擊函數(shù)
var me = $(this);
var psaTitle = me.find('div').attr('data-original-title');
var dateDivs = $('#' + target + ' .table thead #date');
var dateBtn = dateDivs.find('div[data-original-title=\'' + psaTitle + '\']').prev();
dateBtn.click();
})
}
btr.append(tda);
break;
}
}
}
//寫入圖信息
var ps = data[i]['planStartAt']; //計劃開始時間
var pe = data[i]['planEndAt']; //計劃結(jié)束時間
var dpss = lyhGanttuDateDiff(start, ps) - 1; //計劃開始時間和總開始時間的時間差
var dpse = lyhGanttuDateDiff(ps, pe) + 1; //計劃開始時間和計劃結(jié)束時間的時間差
var dse = lyhGanttuDateDiff(start, end); //總開始和總結(jié)束時間差
var as = data[i]['startAt']; //實際開始時間
var ae = data[i]['endAt']; //實際結(jié)束時間
var dass = lyhGanttuDateDiff(start, as) - 1; //實際開始時間和總開始時間的時間差
var dase = lyhGanttuDateDiff(as, ae) + 1; //實際開始時間和實際結(jié)束時間的時間差
var tdu = $('<td>').css('padding', '0px').css('max-height', '38px');
var d = $('<div>').css({ //計劃的div
'display' : 'inline-block',
'width' : '55px',
'height' : '26px',
'margin-bottom' : '-5px',
'margin-top' : '3px',
'padding' : '-1px',
'z-index' : 200,
}).addClass('Gout').append($('<div>').css({ //背景色的div,用于標(biāo)注周末
'width' : '55px',
'height' : '30px',
'position' : 'absolute',
'margin-top' : '-2px',
'opacity' : 0.07,
}).addClass('weekend')).append($('<div>').css({ //實際的div
'width' : '55px',
'height' : '14px',
'position' : 'absolute',
'margin-top' : '7px',
'z-index' : 200,
}).addClass('Gin'));
var weekDay = new Date(start).getDay(); //獲取初始日期是星期幾 - - 0-6為星期日 -- 星期六
//甘特圖繪圖填色
for (var k = 0; k < dse; k++) { //在總開始和總結(jié)束之間做日期循環(huán)
var dc = d.clone();
if ((k + weekDay) % 7 == 5 || (k + weekDay) % 7 == 6) { //周末標(biāo)識填充
dc.find('.weekend').css({
'background-color' : 'blue',
'border-left' : '1px inset #ddd',
})
}
if (k > dpss - 1 && k < dpss + dpse) { //計劃內(nèi)容填充
dc.css({
'background-color' : pBackground,
'border-top' : '1px inset ' + pBorder,
'border-bottom' : '1px inset ' + pBorder,
}).attr('title', '計劃進(jìn)度與實際進(jìn)度');
if (k == dpss) { //左邊界
dc.css('border-left', '1px inset ' + pBorder);
dc.find('.Gin').html('<div style="position:absolute;top:-3px;padding-left:10px">' + data[i]['persent'] + '</div>'); //完工百分比
dc.attr('sId', data[i]['id']); //標(biāo)記為開始,查詢sid,獲取當(dāng)前的計劃的id
}
if (k == dpss + dpse - 1) { //右邊界
dc.css('border-right', '1px inset ' + pBorder);
dc.attr('eId', data[i]['id']); //標(biāo)記為結(jié)束,查詢eid,獲取當(dāng)前的計劃的id
}
}
if (k > dass - 1 && k < dass + dase) { //實際內(nèi)容填充
dc.find('.Gin').css({
'background-color' : background,
'border-top' : '1px inset ' + border,
'border-bottom' : '1px inset ' + border,
}).attr('title', '實際進(jìn)度與實際進(jìn)度');
if (k == dass) { //左邊界
dc.find('.Gin').css('border-left', '1px inset ' + border);
}
if (k == dass + dase - 1) { //右邊界
dc.find('.Gin').css('border-right', '1px inset ' + border);
}
if (dc.css('border-top-width') != '1px') { //是否是只有實際進(jìn)度,進(jìn)行margin-top位置調(diào)整
dc.find('.Gin').css('margin-top', '8px');
}
}
tdu.append(dc)
}
btr.append(tdu)
tbody.append(btr);
}
//寫入table頂部工具欄,包括隱藏展示列功能
var optr = $('<tr>');
var hideResetBtn = $('<button>').addClass('btn btn-primary btn-sm').attr('title', '展示所有隱藏項').html('<span class="glyphicon glyphicon-transfer"></span>')
hideResetBtn.click(function() { //全部展示或隱藏的按鈕點擊函數(shù)
if (lyhGanttuConfig.labels.planEndAt.show == false) {
for (var key in lyhGanttuConfig.labels) {
if (key != 'projectName' && key != 'planStartAt' && key != 'operate') {
lyhGanttuConfig.labels[key].show = true;
}
}
} else {
for (var key in lyhGanttuConfig.labels) {
if (key != 'projectName' && key != 'planStartAt' && key != 'operate') {
lyhGanttuConfig.labels[key].show = false;
}
}
}
lyhGanttuInit(target); //重新繪圖
})
var optdFirst = $('<td>').css('padding', '5px').append(hideResetBtn);
optr.append(optdFirst); //寫入重置隱藏項按鈕
for (var key in labels) {
if (key != 'projectName' && key != 'planStartAt' && key != 'operate') {
var checkSpan = $('<span>').addClass('glyphicon glyphicon-check'); //已選擇span
var uncheckSpan = $('<span>').addClass('glyphicon glyphicon-unchecked'); //未選擇span
if (labels[key].show == true) { //該項目要顯示,隱藏未選
uncheckSpan.hide();
} else {
checkSpan.hide();
}
var optBtn = $('<button>').addClass('btn btn-primary btn-sm').html('').append(checkSpan).append(uncheckSpan).append(labels[key].name)
.attr('title', '隱藏/展示-' + labels[key].name + '列').attr('id', key);
optBtn.click(function() { //表格列工具點擊函數(shù)
var me = $(this);
var hideColumId = me.attr('id');
if (lyhGanttuConfig.labels[hideColumId].show == true) { //隱藏
lyhGanttuConfig.labels[hideColumId].show = false;
} else {
lyhGanttuConfig.labels[hideColumId].show = true; //展示
}
lyhGanttuInit(target); //重新繪圖
})
var optd = $('<td>').css('padding', '5px 10px').append(optBtn);
optr.append(optd);
}
}
//當(dāng)前進(jìn)度按鈕
var optBtnToday = $('<button>').addClass('btn btn-danger btn-sm').html('<span class="glyphicon glyphicon-pushpin"></span>今天進(jìn)度').attr('id', key);
optBtnToday.click(function() { //跳轉(zhuǎn)到今天的點擊函數(shù)
var todayBtn = $('#' + target + ' .table thead tr #date').find('.todayDiv');
todayBtn.prev().prev().click();
})
optr.append($('<td>').css('padding', '5px 10px').append(optBtnToday));
var opt = $('<caption>').append(optr);
//組裝table
var thead = $('<thead>').append(htr).css('background-color', '#cccccc');
var table = $('<table>').append(opt).append(thead).append(tbody).addClass('table table-bordered table-hover');
return table;
}
/**
* 根據(jù)甘特圖生成canvas線條連接linked的函數(shù)
*/
function drawLink(target) {
var temp = $('#' + target);
var dw = parseInt(temp.find('.table #date').css('width').split('px')[0]);
var offset = temp.find('.table #date').position().left;
var dh = parseInt(temp.find('.table').css('height').split('px')[0]) - 80;
var data = lyhGanttuData.data;
var canvas = $('<canvas>').css({
'position' : 'absolute',
'top' : '0px',
'left' : '0px',
'z-index' : 10,
'margin-top' : '95px', //高偏移量
'margin-left' : offset + 'px',
}).attr('width', dw + 'px').attr('height', dh + 'px');
//刪除target下的所有的canvas
temp.find('canvas').remove()
for (var i = 0; i < data.length; i++) {
var before = data[i]['before'];
var id = data[i]['id'];
if (before.length > 0) {
for (var k = 0; k < before.length; k++) {
var eDiv = $('#' + target).find('div[sId=' + id + ']')
var sDiv = $('#' + target).find('div[eId=' + before[k] + ']')
if (eDiv.is(':hidden')) { //若已經(jīng)被隱藏,則不繪制線條
break;
}
var sy = sDiv.position().top - 88; //設(shè)置高度偏移量
var sx = sDiv.position().left + 55 - offset; //設(shè)置寬度偏移量
var ey = eDiv.position().top - 88;
var ex = eDiv.position().left - offset;
var c = canvas.clone();
$('#' + target).append(c); //加載畫布
var ctx = c[0].getContext("2d"); //創(chuàng)建畫布
//繪制連接線條
ctx.beginPath();
ctx.strokeStyle = lyhGanttuConfig.lineColor; //綠色線條
ctx.moveTo(sx, sy); //起點
ctx.lineTo(sx + 15, sy); //右移15
ctx.lineTo(sx + 15, sy + 26); //下移32
ctx.lineTo(sx - 15, sy + 26); //左移30
ctx.lineTo(sx - 15, ey); //下移到終點行
ctx.lineTo(ex, ey); //到終點
ctx.stroke(); //描邊。stroke不會自動closePath()
//繪制起點球球
ctx.beginPath();
ctx.fillStyle = lyhGanttuConfig.lineColor;
ctx.arc(sx, sy, 2, 0, 2 * Math.PI, false); //x,y,半徑,*,弧長,時針
ctx.fill(); //填充
//繪制終點箭頭
ctx.beginPath();
ctx.strokeStyle = lyhGanttuConfig.lineColor;
ctx.moveTo(ex - 7, ey - 3);
ctx.lineTo(ex, ey);
ctx.lineTo(ex - 7, ey + 3);
ctx.stroke(); //描邊。stroke不會自動closePath()
}
}
}
}
var dateLabelClickFlag = null;
/**
* 以過濾后的日期制作head中的日期div
*/
function lyhGanttuHeadDivs(target) {
var start = lyhGanttuConfig.start;
var end = lyhGanttuConfig.end;
var diff = lyhGanttuDateDiff(end, start); //獲取時間差
var arr = [];
var temp = null;
for (var i = 0; i < diff; i++) {
if (null == temp) {
var next = lyhGanttuDatePlus(start);
} else {
var next = lyhGanttuDatePlus(temp);
}
temp = next;
var div = $('<div>').css({
'border-left' : '1px solid #ddd',
'display' : 'inline-block',
'padding' : '9px 9px',
'title' : next,
'cursor' : 'pointer',
}).attr('title', next).html(next.substr(5, 5));
div.click(function() { //date題頭點擊的函數(shù),隱藏之前的所有內(nèi)容
var me = $(this);
if (dateLabelClickFlag != me.attr('title')) { //檢驗第幾次點擊,第一次點擊則隱藏,再次點擊則展示之前內(nèi)容
dateClickHide(target, me); //隱藏內(nèi)容
dateLabelClickFlag = me.attr('title'); //更新flag
} else {
dateClickShow(target); //隱藏內(nèi)容
dateLabelClickFlag = null; //更新flag
}
})
arr.push(div);
}
return arr; //寫回div的jquery的對象的數(shù)組
}
/**
* 隱藏點擊的日期之前的所有甘特圖內(nèi)容的函數(shù)
*/
function dateClickHide(target, me) {
var count = 0;
var temp = me.prev();
while (temp.length != 0) { //隱藏題頭
var prev = temp;
temp.hide();
temp = temp.prev();
count++;
}
var trs = $('#' + target + ' tbody tr');
for (var i = 0; i < trs.length; i++) {
var td = $(trs[i]).children("td:last-child");
var divs = td.find('.Gout');
for (var k = 0; k < count; k++) {
$(divs[k]).hide();
}
}
drawLink(target); //重新繪制
}
/**
* 展示點擊的日期之前的所有甘特圖的內(nèi)容的函數(shù)
*/
function dateClickShow(target) {
$('#' + target + ' div').show();
drawLink(target); //重新繪制
}
/**
* 初始化日期,最早時間-5,最長時間+5
*/
function lyhGanttuConfigModifyByDate() {
for (var i = 0; i < lyhGanttuData.data.length; i++) {
if (lyhGanttuConfig.start == '1900/01/01') {
lyhGanttuConfig.start = lyhGanttuData.data[i].planStartAt;
}
if (lyhGanttuConfig.end == '1900/01/10') {
lyhGanttuConfig.end = lyhGanttuData.data[i].planEndAt;
}
if (str2Date(lyhGanttuConfig.start, '/').getTime() > str2Date(lyhGanttuData.data[i].planStartAt, '/').getTime()) {
lyhGanttuConfig.start = lyhGanttuData.data[i].planStartAt;
}
if (str2Date(lyhGanttuConfig.start, '/').getTime() > str2Date(lyhGanttuData.data[i].startAt, '/').getTime()) {
lyhGanttuConfig.start = lyhGanttuData.data[i].startAt;
}
if (str2Date(lyhGanttuConfig.end, '/').getTime() < str2Date(lyhGanttuData.data[i].planEndAt, '/').getTime()) {
lyhGanttuConfig.end = lyhGanttuData.data[i].planEndAt;
}
if (str2Date(lyhGanttuConfig.end, '/').getTime() < str2Date(lyhGanttuData.data[i].endAt, '/').getTime()) {
lyhGanttuConfig.end = lyhGanttuData.data[i].endAt;
}
}
lyhGanttuConfig.start = lyhGanttuDate(new Date(str2Date(lyhGanttuConfig.start, '/').getTime() - (3 * 24 * 60 * 60 * 1000)))
lyhGanttuConfig.end = lyhGanttuDate(new Date(str2Date(lyhGanttuConfig.end, '/').getTime() + (8 * 24 * 60 * 60 * 1000)))
}
/**
* json date轉(zhuǎn)換日期工具
*/
function lyhGanttuDateStr(dateStr) {
var date = str2Date(dateStr, '-');
var year = date.getFullYear().toString();
var month = (date.getMonth() + 1) <= 9 ? "0"
+ (date.getMonth() + 1) : (date.getMonth() + 1);
var day = date.getDate() <= 9 ? "0" + date.getDate() : date
.getDate();
return year + "/" + month + "/" + day;
}
/**
* json date轉(zhuǎn)換日期工具 date 對象轉(zhuǎn)化為固定格式/日期的函數(shù)
*/
function lyhGanttuDate(date) {
var year = date.getFullYear().toString();
var month = (date.getMonth() + 1) <= 9 ? "0"
+ (date.getMonth() + 1) : (date.getMonth() + 1);
var day = date.getDate() <= 9 ? "0" + date.getDate() : date
.getDate();
return year + "/" + month + "/" + day;
}
/**
* 固定格式的字符串轉(zhuǎn)換成date格式函數(shù)
*/
function str2Date(dateStr, separator) {
if (!separator) {
separator = "/";
}
var dateArr = dateStr.split(separator);
var year = parseInt(dateArr[0]);
var month;
//處理月份為04這樣的情況
if (dateArr[1].indexOf("0") == 0) {
month = parseInt(dateArr[1].substring(1));
} else {
month = parseInt(dateArr[1]);
}
var day = parseInt(dateArr[2]);
var date = new Date(year, month - 1, day);
return date;
}
/**
* 計算兩個日期之間的天數(shù)
*/
function lyhGanttuDateDiff(dateStr1, dateStr2) { //sDate1和sDate2是2006-12-18格式
var dateSpan,
tempDate,
iDays;
dateStr1 = Date.parse(dateStr1);
dateStr2 = Date.parse(dateStr2);
dateSpan = dateStr2 - dateStr1;
dateSpan = Math.abs(dateSpan);
iDays = Math.floor(dateSpan / (24 * 3600 * 1000));
return iDays
}
/**
* 當(dāng)前日期時間以原格式+1的函數(shù)
*/
function lyhGanttuDatePlus(dateStr, days) {
var date = str2Date(dateStr);
if (days == undefined || days == '') {
days = 1;
}
date.setDate(date.getDate() + days); //日期+1
var year = date.getFullYear().toString();
var month = (date.getMonth() + 1) <= 9 ? "0"
+ (date.getMonth() + 1) : (date.getMonth() + 1);
var day = date.getDate() <= 9 ? "0" + date.getDate() : date
.getDate();
return year + "/" + month + "/" + day;
}
</script>
</html>
(4)在Controller層中利用Http請求傳參
@RequestMapping(value = "/gantee",method = RequestMethod.GET)
public String gantee(Model model) throws JSONException {
Renwu renwu = renwuService.queryById(new Integer("1"));
Map jsonData = new HashMap();
List<Map> jsonArray = new ArrayList<>();
Map jsonObject = new HashMap();
Integer id = renwu.getProjectid();
Integer pid = renwu.getPid();
String projectName = renwu.getProjectname();
String projectCode = renwu.getProjectcode();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
Date planStartDate = renwu.getPlanstartat();
Date planEndDate = renwu.getPlanendat();
Date startDate = renwu.getStartat();
Date endDate = renwu.getEndat();
String planStartStr = dateFormat.format(planStartDate);
String planEndStr = dateFormat.format(planEndDate);
String startStr = dateFormat.format(startDate);
String endStr = dateFormat.format(endDate);
String persent = renwu.getPersent();
String resps = renwu.getResps();
String actors = renwu.getActors();
String insiders = renwu.getInsiders();
Integer dur = renwu.getDur();
Integer before = renwu.getBefore();
jsonObject.put("id",id);
jsonObject.put("pid",pid);
jsonObject.put("projectName",projectName);
jsonObject.put("projectCode",projectCode);
jsonObject.put("planStartAt",planStartStr);
jsonObject.put("planEndAt",planEndStr);
jsonObject.put("startAt",startStr);
jsonObject.put("endAt",endStr);
jsonObject.put("persent",persent);
jsonObject.put("resps",resps);
jsonObject.put("actors",actors);
jsonObject.put("insiders",insiders);
jsonObject.put("dur",dur);
jsonObject.put("before",new Object[]{before});
jsonArray.add(jsonObject);
jsonData.put("data",jsonArray);
model.addAttribute("lyhGanttuData",jsonData);
return "ganttu";
}
(5)直接啟動SpringBoot項目即可。

這個是Springboot項目,自然也是可以轉(zhuǎn)到SpringCloud的子項目中。
注意:HTML并不是我原創(chuàng)沒我只是在其基礎(chǔ)上改了一下JS。在這個開放的時代,我覺得大家應(yīng)該把學(xué)到的東西開放出來,不管多好或是很差。
到此這篇關(guān)于springboot+thymeleaf+mybatis實現(xiàn)甘特圖的詳細(xì)過程的文章就介紹到這了,更多相關(guān)springboot+thymeleaf+mybatis實現(xiàn)甘特圖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入理解Java責(zé)任鏈模式實現(xiàn)靈活的請求處理流程
本文詳細(xì)介紹了Java中的責(zé)任鏈模式,幫助您理解其工作原理,以及如何在代碼中實現(xiàn)。該模式可以將請求沿著處理鏈路傳遞,實現(xiàn)靈活的請求處理流程。通過本文的學(xué)習(xí),您將獲得在Java應(yīng)用程序中使用責(zé)任鏈模式的知識和技能2023-04-04
SpringBoot使用@EnableAutoConfiguration實現(xiàn)自動配置詳解
你有想過SpringBoot為什么能夠自動的幫我們創(chuàng)建一個Bean對象么?或許在我們使用的時候只需要在自己自定義的配置文件中加入@Bean對象就可以,但SpringBoot是如何來創(chuàng)建的呢2022-08-08
SpringBoot使用JdbcTemplate操作數(shù)據(jù)庫
這篇文章主要介紹了SpringBoot使用JdbcTemplate操作數(shù)據(jù)庫,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-07-07
如何在Intellij中安裝LeetCode刷題插件方便Java刷題
這篇文章主要介紹了如何在Intellij中安裝LeetCode刷題插件方便Java刷題,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08
IDEA 項目創(chuàng)建Mapper的xml文件的方法
這篇文章主要介紹了IDEA 項目創(chuàng)建Mapper的xml文件的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11

