554 lines
14 KiB
HTML
554 lines
14 KiB
HTML
|
{extend name="../../base/view/common/base" /}
|
|||
|
{block name="style"}
|
|||
|
<style>
|
|||
|
.hover-view i,.hover-edit i{margin-left:4px; font-weight:800; cursor:pointer; opacity:0}
|
|||
|
.hover-edit.hover-on i{opacity:1}
|
|||
|
.layui-tab-title .layui-this{background-color:#fff;}
|
|||
|
.layui-tab-card,.layui-card{box-shadow:0 0 0 0 rgb(0 0 0 / 10%); border-radius:0;}
|
|||
|
.layui-card-tips {color: #969696;}
|
|||
|
.layui-card-value {padding: 4px 0 16px;font-size: 18px;color: #1E9FFF;}
|
|||
|
|
|||
|
.log-timeline{ position: relative; min-height:600px; padding-left: 48px; background-color:#fff;}
|
|||
|
.log-timeline:after {content: ""; position: absolute; top: 0; left: 24px; width: 1px; height: 100%; background: #e3e9ed;}
|
|||
|
.log-timeline dl{padding-bottom: 8px; position: relative;}
|
|||
|
.log-timeline dt{font-size: 16px; line-height: 2.4; color: #323232; font-weight:600}
|
|||
|
.log-timeline dd{font-size: 14px; line-height: 1.6; padding:5px 0}
|
|||
|
.log-timeline .date-second-point{width: 10px; height: 10px; display: block; border-radius: 50%; border: 3px solid #FBBC05; background: #fff; position: absolute; z-index: 99; left:-32px; top:9px}
|
|||
|
.log-timeline .log-thumb{width: 24px; height: 24px; border-radius: 50%; margin-right:4px;}
|
|||
|
.log-timeline .open-a{margin:0 4px;}
|
|||
|
.log-item i{font-weight:800; color:#323232}
|
|||
|
.log-content strong{margin:0 4px; color:#323232}
|
|||
|
.layui-timeline-item{color:#c9c9c9; padding-bottom:8px}
|
|||
|
.layui-timeline-item.delete_0{color:#646464;}
|
|||
|
|
|||
|
.comment-input .comment-image{width:40px; height:40px; border-radius:50%}
|
|||
|
.comment-item .comment-avatar{width:50px; float:left}
|
|||
|
.comment-item .comment-image{width:36px; height:36px; border-radius:50%}
|
|||
|
.comment-item .comment-body{margin-left:50px;}
|
|||
|
.comment-item .comment-content blockquote{border-left:3px solid #f1f1f1; padding:4px 8px;}
|
|||
|
.comment-item .comment-actions a{color:#8c95a8; cursor:pointer; font-size:12px;}
|
|||
|
.comment-item .comment-actions a:hover{color:#3582fb;}
|
|||
|
.comment-meta span{font-size:12px;}
|
|||
|
|
|||
|
.check-items{overflow-x: auto; padding: 2px 0;}
|
|||
|
.flow-flex-row {box-direction: row;
|
|||
|
box-orient: horizontal;
|
|||
|
-webkit-box-orient: horizontal;
|
|||
|
-ms-flex-direction: row;
|
|||
|
flex-direction: row;
|
|||
|
}
|
|||
|
.flow-flexbox { width: 100%;text-align: left;
|
|||
|
display: -webkit-box;
|
|||
|
display: -ms-flexbox;
|
|||
|
display: flex;
|
|||
|
display: -webkit-flex;
|
|||
|
box-align: center;
|
|||
|
-webkit-box-align: center;
|
|||
|
-ms-flex-align: center;
|
|||
|
align-items: center;
|
|||
|
flex-wrap: wrap;
|
|||
|
}
|
|||
|
.check-item{width: auto; -ms-flex-negative: 0; flex-shrink: 0; padding:4px 0;}
|
|||
|
.check-item i{font-size:20px; margin-right:3px;}
|
|||
|
.check-item span{color:#999;margin:0 1px;}
|
|||
|
.layui-icon[data-ok]{color:#34a853}
|
|||
|
.layui-icon[data-no]{color:#FF5722;}
|
|||
|
.layui-icon[data-on]{color:#4285f4;}
|
|||
|
.check-item-status{color:#969696; font-size:12px; margin-left:3px;}
|
|||
|
.check-item:last-child .layui-icon-right{display:none;}
|
|||
|
|
|||
|
tr[data-level="1"] td{
|
|||
|
background-color: #f9f9f9;
|
|||
|
}
|
|||
|
tr[data-level="2"] td{
|
|||
|
background-color: #fbfbfb;
|
|||
|
}
|
|||
|
tr[data-level="2"] td{
|
|||
|
background-color: #fdfdfd;
|
|||
|
}
|
|||
|
</style>
|
|||
|
{/block}
|
|||
|
<!-- 主体 -->
|
|||
|
{block name="body"}
|
|||
|
<div class="p-3">
|
|||
|
<h2 class="pb-3 hover-edit">
|
|||
|
<span class="font20" id="name_{$detail.id}" data-val="">{$detail.name}</span>
|
|||
|
<i class="iconfont icon-wodedianping" title="编辑" data-id="{$detail.id}" data-name="name"></i>
|
|||
|
</h2>
|
|||
|
<div>
|
|||
|
<span class="layui-badge layui-bg-gray">#P{$detail.id}</span>
|
|||
|
<span class="mx-2">{$detail.admin_name}</span>
|
|||
|
<span class="gray">创建于{$detail.times}<span id="editTips">{gt name="$detail.update_time"
|
|||
|
value="0"},最近更新于 {:time_trans($detail.update_time)}{/gt}</span></span>
|
|||
|
{eq name="$detail.admin_id" value="$login_admin.id"}
|
|||
|
<span class="layui-btn layui-btn-xs layui-btn-danger ml-4" id="delProject"><i
|
|||
|
class="layui-icon"></i>删除</span>
|
|||
|
{/eq}
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="layui-tab layui-tab-card" style="margin:0;" lay-filter="project" id="projectTab">
|
|||
|
<ul class="layui-tab-title">
|
|||
|
<li class="layui-this" data-load="true">项目概览</li>
|
|||
|
<li data-load="">项目任务</li>
|
|||
|
<li data-load="">工作记录</li>
|
|||
|
<li data-load="">项目文档</li>
|
|||
|
<li data-load="">项目人员</li>
|
|||
|
<li data-load="">项目动态</li>
|
|||
|
<li data-load="">项目评论</li>
|
|||
|
</ul>
|
|||
|
<div class="layui-tab-content" style="padding:0">
|
|||
|
<div class="layui-tab-item layui-show">
|
|||
|
{include file="/index/view_overview" /}
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="layui-tab-item">
|
|||
|
{include file="/index/view_task" /}
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="layui-tab-item">
|
|||
|
{include file="/index/view_schedule" /}
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="layui-tab-item">
|
|||
|
{include file="/index/view_document" /}
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="layui-tab-item">
|
|||
|
{include file="/index/view_user" /}
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="layui-tab-item">
|
|||
|
{include file="/index/view_log" /}
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="layui-tab-item">
|
|||
|
{include file="/index/view_comment" /}
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
{/block}
|
|||
|
<!-- /主体 -->
|
|||
|
|
|||
|
<!-- 脚本 -->
|
|||
|
{block name="script"}
|
|||
|
<script src="{__GOUGU__}/third_party/echart/echarts.min.js"></script>
|
|||
|
<script>
|
|||
|
var project_id = '{$detail.id}';
|
|||
|
var project_start_time = '{$detail.start_time| date="Y-m-d"}';
|
|||
|
const opsData = {
|
|||
|
status: [
|
|||
|
{ 'id': 1, 'title': '未开始' },
|
|||
|
{ 'id': 2, 'title': '进行中' },
|
|||
|
{ 'id': 3, 'title': '已完成' },
|
|||
|
{ 'id': 4, 'title': '已关闭' }
|
|||
|
]
|
|||
|
}
|
|||
|
|
|||
|
var chartProgress = document.getElementById('progress');
|
|||
|
var progressChart = echarts.init(chartProgress);
|
|||
|
var optionA;
|
|||
|
optionA = {
|
|||
|
backgroundColor: "#ffffff",
|
|||
|
title: {
|
|||
|
text: '67.45%',//主标题文本
|
|||
|
subtext: '任务完成率',//副标题文本
|
|||
|
x: 'center',
|
|||
|
y: '39%',
|
|||
|
textStyle: {
|
|||
|
fontWeight: 'normal',
|
|||
|
fontSize: 18,
|
|||
|
color: '#FF974C',
|
|||
|
align: 'center'
|
|||
|
},
|
|||
|
subtextStyle: {
|
|||
|
fontSize: 12,
|
|||
|
color: '#6c7a89',
|
|||
|
}
|
|||
|
},
|
|||
|
tooltip: {
|
|||
|
trigger: "item",
|
|||
|
formatter: '{b}:<br/><strong>{c}</strong>',
|
|||
|
show: true,
|
|||
|
},
|
|||
|
series: [
|
|||
|
{
|
|||
|
type: 'pie',
|
|||
|
radius: ['60%', '80%'],
|
|||
|
center: ['50%', '50%'],
|
|||
|
avoidLabelOverlap: false,
|
|||
|
label: {
|
|||
|
show: false
|
|||
|
},
|
|||
|
data: [
|
|||
|
{ value: 1048, name: '待处理' },
|
|||
|
{ value: 735, name: '已完成' }
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
|
|||
|
var chartDelay = document.getElementById('delay');
|
|||
|
var delayChart = echarts.init(chartDelay);
|
|||
|
var optionB;
|
|||
|
optionB = {
|
|||
|
backgroundColor: "#ffffff",
|
|||
|
title: {
|
|||
|
text: '40.25%',//主标题文本
|
|||
|
subtext: '任务延迟率',//副标题文本
|
|||
|
x: 'center',
|
|||
|
y: '39%',
|
|||
|
textStyle: {
|
|||
|
fontWeight: 'normal',
|
|||
|
fontSize: 18,
|
|||
|
color: '#FF974C',
|
|||
|
align: 'center',
|
|||
|
marginLeft: '-10px'
|
|||
|
},
|
|||
|
subtextStyle: {
|
|||
|
fontSize: 12,
|
|||
|
color: '#6c7a89',
|
|||
|
}
|
|||
|
},
|
|||
|
tooltip: {
|
|||
|
trigger: "item",
|
|||
|
formatter: '{b}:<br/><strong>{c}</strong>',
|
|||
|
show: true,
|
|||
|
},
|
|||
|
series: [
|
|||
|
{
|
|||
|
type: 'pie',
|
|||
|
radius: ['60%', '80%'],
|
|||
|
center: ['50%', '50%'],
|
|||
|
avoidLabelOverlap: false,
|
|||
|
label: {
|
|||
|
show: false
|
|||
|
},
|
|||
|
data: [{
|
|||
|
value: 1048,
|
|||
|
name: '延迟',
|
|||
|
itemStyle: {
|
|||
|
color: "#ED6666",
|
|||
|
}
|
|||
|
},
|
|||
|
{
|
|||
|
value: 735,
|
|||
|
name: '未延迟',
|
|||
|
itemStyle: {
|
|||
|
color: "#91CC75",
|
|||
|
}
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
var chartCross = document.getElementById('cross');
|
|||
|
var crossChart = echarts.init(chartCross);
|
|||
|
var optionD;
|
|||
|
optionD = {
|
|||
|
backgroundColor: "#ffffff",
|
|||
|
color: ['#8C92A4', '#2C7EF8'],
|
|||
|
tooltip: {
|
|||
|
trigger: 'axis',
|
|||
|
axisPointer: {
|
|||
|
type: 'cross',
|
|||
|
label: {
|
|||
|
backgroundColor: '#6a7985'
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
legend: {
|
|||
|
data: ['任务计划剩余', '任务实际剩余']
|
|||
|
},
|
|||
|
grid: {
|
|||
|
top: 36,
|
|||
|
left: 8,
|
|||
|
right: 36,
|
|||
|
bottom: 0,
|
|||
|
containLabel: true
|
|||
|
},
|
|||
|
xAxis: [
|
|||
|
{
|
|||
|
type: 'category',
|
|||
|
boundaryGap: false,
|
|||
|
splitLine: {
|
|||
|
show: true,
|
|||
|
lineStyle: {
|
|||
|
type: 'dashed'
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
],
|
|||
|
yAxis: [{
|
|||
|
axisLine: {
|
|||
|
show: true
|
|||
|
},
|
|||
|
boundaryGap: false,
|
|||
|
splitLine: {
|
|||
|
show: true,
|
|||
|
lineStyle: {
|
|||
|
type: 'dashed'
|
|||
|
}
|
|||
|
},
|
|||
|
type: 'value'
|
|||
|
}
|
|||
|
]
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
var chartPlan = document.getElementById('plan');
|
|||
|
var planChart = echarts.init(chartPlan);
|
|||
|
var optionE;
|
|||
|
|
|||
|
optionE = {
|
|||
|
backgroundColor: "#ffffff",
|
|||
|
title: {
|
|||
|
top: 0,
|
|||
|
left: 0,
|
|||
|
text: ''
|
|||
|
},
|
|||
|
tooltip: {
|
|||
|
padding: 6,
|
|||
|
formatter: function (obj) {
|
|||
|
var value = obj.value;
|
|||
|
var tips = '<div style="font-size: 12px;">' + value[0] + '<br>';
|
|||
|
tips += '共 ' + value[1] + ' 个工作任务';
|
|||
|
tips += '</div>';
|
|||
|
return tips;
|
|||
|
}
|
|||
|
},
|
|||
|
visualMap: {
|
|||
|
min: 0,
|
|||
|
max: 10,
|
|||
|
show: false,
|
|||
|
inRange: {
|
|||
|
color: ['#fafafa', '#20BF3F']
|
|||
|
}
|
|||
|
},
|
|||
|
calendar: {
|
|||
|
top: 24,
|
|||
|
left: 36,
|
|||
|
right: 4,
|
|||
|
cellSize: ['auto', 16],
|
|||
|
range: ['2022-03-01', '2022-08-01'],
|
|||
|
splitLine: {
|
|||
|
lineStyle: {
|
|||
|
color: '#333',
|
|||
|
type: 'dashed',
|
|||
|
}
|
|||
|
},
|
|||
|
itemStyle: {
|
|||
|
borderWidth: 0.5
|
|||
|
},
|
|||
|
yearLabel: { show: false },
|
|||
|
monthLabel: {
|
|||
|
nameMap: 'cn',
|
|||
|
fontSize: 12
|
|||
|
},
|
|||
|
dayLabel: {
|
|||
|
show: true,
|
|||
|
formatter: '{start} 1st',
|
|||
|
fontWeight: 'lighter',
|
|||
|
nameMap: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
|
|||
|
fontSize: 12
|
|||
|
}
|
|||
|
},
|
|||
|
series: {
|
|||
|
type: 'heatmap',
|
|||
|
coordinateSystem: 'calendar',
|
|||
|
data: []
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
var chartWork = document.getElementById('work');
|
|||
|
var workChart = echarts.init(chartWork);
|
|||
|
var optionF;
|
|||
|
|
|||
|
optionF = {
|
|||
|
backgroundColor: "#ffffff",
|
|||
|
title: {
|
|||
|
top: 0,
|
|||
|
left: 0,
|
|||
|
text: ''
|
|||
|
},
|
|||
|
tooltip: {
|
|||
|
padding: 6,
|
|||
|
formatter: function (obj) {
|
|||
|
var value = obj.value;
|
|||
|
var tips = '<div style="font-size: 12px;">' + value[0] + '<br>';
|
|||
|
tips += '共 ' + value[1] + ' 个工时';
|
|||
|
tips += '</div>';
|
|||
|
return tips;
|
|||
|
}
|
|||
|
},
|
|||
|
visualMap: {
|
|||
|
min: 0,
|
|||
|
max: 10,
|
|||
|
show: false,
|
|||
|
inRange: {
|
|||
|
color: ['#fafafa', '#359AEF']
|
|||
|
}
|
|||
|
},
|
|||
|
calendar: {
|
|||
|
top: 24,
|
|||
|
left: 36,
|
|||
|
right: 4,
|
|||
|
cellSize: ['auto', 16],
|
|||
|
range: ['2022-03-01', '2022-08-01'],
|
|||
|
splitLine: {
|
|||
|
lineStyle: {
|
|||
|
color: '#333',
|
|||
|
type: 'dashed',
|
|||
|
}
|
|||
|
},
|
|||
|
itemStyle: {
|
|||
|
borderWidth: 0.5
|
|||
|
},
|
|||
|
yearLabel: { show: false },
|
|||
|
monthLabel: {
|
|||
|
nameMap: 'cn',
|
|||
|
fontSize: 12
|
|||
|
},
|
|||
|
dayLabel: {
|
|||
|
show: true,
|
|||
|
formatter: '{start} 1st',
|
|||
|
fontWeight: 'lighter',
|
|||
|
nameMap: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
|
|||
|
fontSize: 12
|
|||
|
}
|
|||
|
},
|
|||
|
series: {
|
|||
|
type: 'heatmap',
|
|||
|
coordinateSystem: 'calendar',
|
|||
|
data: []
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
function getCalendarData(arr) {
|
|||
|
var rangeArray = [];
|
|||
|
for (var property in arr) {
|
|||
|
rangeArray.push(property);
|
|||
|
}
|
|||
|
var rangeArray = [rangeArray[0], rangeArray[rangeArray.length - 1]];
|
|||
|
var start = +echarts.number.parseDate(rangeArray[0]);
|
|||
|
var end = +echarts.number.parseDate(rangeArray[1]);
|
|||
|
if (start + 7776000000 > end) {
|
|||
|
end = start + 8640000000;
|
|||
|
rangeArray[1] = echarts.format.formatTime('yyyy-MM-dd', end);
|
|||
|
}
|
|||
|
var dayTime = 3600 * 24 * 1000;
|
|||
|
var data = [];
|
|||
|
for (var time = start; time < end; time += dayTime) {
|
|||
|
var this_date = echarts.format.formatTime('yyyy-MM-dd', time);
|
|||
|
if (arr[this_date]) {
|
|||
|
data.push([this_date, arr[this_date]]);
|
|||
|
} else {
|
|||
|
data.push([this_date, 0]);
|
|||
|
}
|
|||
|
}
|
|||
|
var res = { 'range': rangeArray, 'data': data };
|
|||
|
return res;
|
|||
|
}
|
|||
|
|
|||
|
//燃尽图统计
|
|||
|
function cross_count(arr, arr2) {
|
|||
|
var planArray = [], doArray = [];
|
|||
|
var today = new Date();
|
|||
|
var todayStr = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
|
|||
|
for (var a in arr) {
|
|||
|
planArray.push(a);
|
|||
|
}
|
|||
|
var rangeArray = [planArray[0], planArray[planArray.length - 1]];
|
|||
|
if (arr2 instanceof Array == false) {
|
|||
|
for (var b in arr2) {
|
|||
|
doArray.push(b);
|
|||
|
}
|
|||
|
if ((+echarts.number.parseDate(doArray[doArray.length - 1])) < (+echarts.number.parseDate(todayStr))) {
|
|||
|
doArray.push(todayStr);
|
|||
|
}
|
|||
|
if ((+echarts.number.parseDate(planArray[planArray.length - 1])) < (+echarts.number.parseDate(doArray[doArray.length - 1]))) {
|
|||
|
rangeArray[1] = doArray[doArray.length - 1];
|
|||
|
}
|
|||
|
}
|
|||
|
var start = +echarts.number.parseDate(rangeArray[0]);
|
|||
|
var end = +echarts.number.parseDate(rangeArray[1]);
|
|||
|
var todayInt = +echarts.number.parseDate(todayStr);
|
|||
|
var dayTime = 3600 * 24 * 1000;
|
|||
|
var xArray = [], yArray = [], yArray2 = [], done = 0, doneArray = [];
|
|||
|
for (var time = start; time <= end; time += dayTime) {
|
|||
|
var this_date = echarts.format.formatTime('yyyy-MM-dd', time);
|
|||
|
xArray.push(this_date);
|
|||
|
var plan = cross_recursion(time, end, arr);
|
|||
|
yArray.push(plan);
|
|||
|
|
|||
|
if (arr2[this_date]) {
|
|||
|
done += arr2[this_date];
|
|||
|
}
|
|||
|
if (time <= todayInt) {
|
|||
|
doneArray.push(done);
|
|||
|
}
|
|||
|
}
|
|||
|
for (var i = 0; i < doneArray.length; i++) {
|
|||
|
yArray2.push(yArray[0] - doneArray[i]);
|
|||
|
}
|
|||
|
var start_time = +echarts.number.parseDate(project_start_time), tem_x_array = [], tem_y_array = [];
|
|||
|
if (start_time < start) {
|
|||
|
for (var tem_time = start_time; tem_time < start; tem_time += dayTime) {
|
|||
|
var this_date = echarts.format.formatTime('yyyy-MM-dd', tem_time);
|
|||
|
tem_x_array.push(this_date);
|
|||
|
tem_y_array.push(yArray[0]);
|
|||
|
}
|
|||
|
xArray = tem_x_array.concat(xArray);
|
|||
|
yArray = tem_y_array.concat(yArray);
|
|||
|
yArray2 = tem_y_array.concat(yArray2);
|
|||
|
}
|
|||
|
return { 'x': xArray, 'y': yArray, 'y2': yArray2 };
|
|||
|
}
|
|||
|
|
|||
|
function cross_recursion(start, end, arr) {
|
|||
|
var count = 0;
|
|||
|
var dayTime = 3600 * 24 * 1000;
|
|||
|
for (var time = start; time <= end; time += dayTime) {
|
|||
|
var this_date = echarts.format.formatTime('yyyy-MM-dd', time);
|
|||
|
if (arr[this_date]) {
|
|||
|
count += arr[this_date];
|
|||
|
}
|
|||
|
}
|
|||
|
return count;
|
|||
|
}
|
|||
|
|
|||
|
const moduleInit = ['tool','oaEdit','oaSchedule','oaComment','oaTool'];
|
|||
|
|
|||
|
function gouguInit() {
|
|||
|
var element = layui.element;
|
|||
|
overview();
|
|||
|
element.on('tab(project)', function(data){
|
|||
|
let index = data.index;
|
|||
|
if(index == 1){
|
|||
|
project_task();
|
|||
|
}
|
|||
|
else if(index == 2){
|
|||
|
project_schedule();
|
|||
|
}
|
|||
|
else if(index == 3){
|
|||
|
project_document();
|
|||
|
}
|
|||
|
else if(index == 4){
|
|||
|
project_user();
|
|||
|
}
|
|||
|
else if(index == 5){
|
|||
|
project_log();
|
|||
|
}
|
|||
|
else if(index == 6){
|
|||
|
project_comment();
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
</script>
|
|||
|
{/block}
|
|||
|
<!-- /脚本 -->
|