1684 lines
75 KiB
HTML
1684 lines
75 KiB
HTML
{extend name="../../base/view/common/base" /}
|
||
{block name="style"}
|
||
<style>
|
||
.layui-timeline.pt-2 .layui-timeline-item {
|
||
padding-bottom: 12px;
|
||
text-decoration: line-through;
|
||
color: #acacac;
|
||
padding-bottom: 10px;
|
||
}
|
||
|
||
.layui-timeline.pt-2 .layui-timeline-item.delete-0 {
|
||
text-decoration: none;
|
||
color: #323232;
|
||
}
|
||
|
||
.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;
|
||
}
|
||
</style>
|
||
{/block}
|
||
{block name="breadcrumb"}
|
||
<span class="layui-breadcrumb">
|
||
<a href="http://www.meteteme.com/" target="_blank">江苏美天科技</a>
|
||
<a href="/project/index/index">项目中心</a>
|
||
<a><cite>项目详情</cite></a>
|
||
</span>
|
||
{/block}
|
||
<!-- 主体 -->
|
||
{block name="body"}
|
||
<div class="main-content" style="min-height:100%; height:auto;">
|
||
{include file="/index/submenu" /}
|
||
<div id="pageBox" class="main-page-content p-3" style="background-color:#F5F8FA;padding-bottom: 0;">
|
||
<div class="layui-row">
|
||
<div class="layui-col-xs12">
|
||
<div class="layui-card">
|
||
<div class="layui-card-header" style="height:45px;">
|
||
<div class="layui-row">
|
||
<div class="layui-col-md9">
|
||
<h4 class="hover-edit"><span id="name_{$detail.id}" data-val="">{$detail.name}</span><i
|
||
class="iconfont icon-wodedianping" title="编辑" data-id="{$detail.id}"
|
||
data-name="name"></i></h4>
|
||
</div>
|
||
<div class="layui-col-md3" style="text-align:right">
|
||
{eq name="$role" value="2"}
|
||
<button type="button" class="layui-btn layui-btn-danger layui-btn-sm"
|
||
id="delProject">删除项目
|
||
</button>
|
||
<button type="button" class="layui-btn layui-btn-sm layui-bg-blue" id="editProject">编辑项目
|
||
</button>
|
||
{eq name="$detail.status" value="4"}
|
||
<button type="button" class="layui-btn layui-btn-normal layui-btn-sm"
|
||
id="reopenProject">开启项目
|
||
</button>
|
||
{else/}
|
||
<button type="button" class="layui-btn layui-btn-waring layui-btn-sm"
|
||
id="closeProject">关闭项目
|
||
</button>
|
||
{/eq}
|
||
{/eq}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class='layui-card-body {$role=="0"?"hover-view":"hover-edit"}'>
|
||
<div class="py-1">
|
||
<span class="font-gray">项目ID:</span>
|
||
<span id="{$detail.id}" data-val="{$detail.id}">{$detail.id}</span>
|
||
<input type="hidden" name="id" value="{$detail.id}">
|
||
<!-- <i class="iconfont icon-wodedianping" title="编辑" data-id="{$detail.id}"-->
|
||
<!-- data-name="id"></i>-->
|
||
<!-- <button data-id="{$detail.id}" data-name="business_id">编辑</button> -->
|
||
</div>
|
||
<hr>
|
||
<div class="py-1">
|
||
<span class="font-gray">客户名称:</span>
|
||
<span id="business_id_{$detail.id}"
|
||
data-val="{$detail.business_id}">{$detail.business_id}</span>
|
||
<!-- <i class="iconfont icon-wodedianping" title="编辑" data-id="{$detail.id}"-->
|
||
<!-- data-name="business_id"></i>-->
|
||
<!-- <button data-id="{$detail.id}" data-name="business_id">编辑</button> -->
|
||
</div>
|
||
<hr>
|
||
<div class="py-1">
|
||
<span class="font-gray">合同周期:</span>
|
||
<span id="start_time_{$detail.id}" data-val="">{$detail.start_time|date='Y-m-d'}</span>
|
||
~ <span id="end_time_{$detail.id}" data-val="">{$detail.end_time|
|
||
date='Y-m-d'}</span>
|
||
</div>
|
||
<hr>
|
||
<div class="py-1">
|
||
<span class="font-gray">项目周期:</span>
|
||
<span id="project_start_time_{$detail.id}"
|
||
data-val="">{$detail.project_start_time|date='Y-m-d'}</span>
|
||
~
|
||
<span id="project_end_time_{$detail.id}" data-val="">
|
||
{if $detail.project_end_time == '1970-01-01' || $detail.project_end_time == 0 ||
|
||
$detail.project_end_time == ''}
|
||
至今
|
||
{else}
|
||
{$detail.project_end_time|date='Y-m-d'}
|
||
{/if}
|
||
</span>
|
||
</div>
|
||
<hr>
|
||
<div class="py-1">
|
||
<span class="font-gray">创建人:</span>{$detail.admin_name}
|
||
<span class="font-gray" style="margin-left:32px">负责人:</span>
|
||
<span id="director_uid_{$detail.id}"
|
||
data-val="{$detail.director_uid}">{$detail.director_name}</span>
|
||
<!-- <i class="iconfont icon-wodedianping" title="编辑" data-id="{$detail.id}"-->
|
||
<!-- data-name="director_uid"></i>-->
|
||
<span class="font-gray" style="margin-left:32px">项目成员:</span>{$detail.team_admin_names}
|
||
</div>
|
||
<hr>
|
||
<div class="py-1">
|
||
<span class="font-gray">项目简介:</span>
|
||
<span id="content_{$detail.id}" data-val="{$detail.content}">{$detail.content}</span>
|
||
<!-- <i class="iconfont icon-wodedianping" title="编辑" data-id="{$detail.id}"-->
|
||
<!-- data-name="content"></i>-->
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="layui-col-xs12">
|
||
<div class="layui-card">
|
||
<div class="layui-card-header" style="height:45px;">
|
||
<div class="layui-row">
|
||
<div class="layui-col-md6">
|
||
<h4>项目阶段</h4>
|
||
</div>
|
||
{gt name="$role" value="0"}
|
||
{neq name="$detail.status" value="4"}
|
||
<div class="layui-col-md6" style="margin-top:10px">
|
||
<span data-href="/project/index/editstep/id/{$detail.id}"
|
||
class="layui-btn layui-btn-normal layui-btn-sm open-a fr">编辑项目阶段</span>
|
||
</div>
|
||
{/neq}
|
||
{/gt}
|
||
</div>
|
||
</div>
|
||
{notempty name="$step" id="vo"}
|
||
<div class="p-3 border-b jieduan">
|
||
<span class="gray">当前阶段:</span>{$step.flow_name}
|
||
<span class="gray" style="margin-left:20px">负责人:</span>{$step.check_name}
|
||
<span class="gray" style="margin-left:20px">成员:</span>{$step.flow_names}
|
||
<!-- <span class="gray" style="margin-left:20px">周期:</span>{$step.start_time|time_format=###,'Y-m-d'}-->
|
||
<!-- 到 {$step.end_time|time_format=###,'Y-m-d'}-->
|
||
{eq name="$step.flow_uid" value="$login_user"}
|
||
{neq name="$detail.status" value="4"}
|
||
<div class="pt-3">
|
||
<span class="layui-btn layui-btn-normal layui-btn-sm" data-event="step"
|
||
data-check="1">确认</span>
|
||
{gt name="$detail.step_sort" value="0"}
|
||
<span class="layui-btn layui-btn-danger layui-btn-sm" data-event="step"
|
||
data-check="2">退回</span>
|
||
{/gt}
|
||
</div>
|
||
{/neq}
|
||
{/eq}
|
||
</div>
|
||
{/notempty}
|
||
<div class="px-3 py-1 border-b">
|
||
<div class="flow-flexbox check-items flow-flex-row">
|
||
{volist name="$step_array" id="vo"}
|
||
<div class="flow-flexbox check-item flow-flex-row">
|
||
{gt name="$vo.sort" value="$detail.step_sort"}
|
||
<i class="layui-icon layui-icon-time"></i>
|
||
{/gt}
|
||
{eq name="$vo.sort" value="$detail.step_sort"}
|
||
<!-- <i class="layui-icon layui-icon-username" data-on=""></i>-->
|
||
{/eq}
|
||
{lt name="$vo.sort" value="$detail.step_sort"}
|
||
<i class="layui-icon layui-icon-ok-circle" data-ok=""></i>
|
||
{/lt}
|
||
<div class="check-item-name">{$vo.flow_name}</div>
|
||
<div class="check-item-status">{$vo.check_name}</div>
|
||
<span class="layui-icon layui-icon-right"></span>
|
||
</div>
|
||
{/volist}
|
||
</div>
|
||
</div>
|
||
<div class="p-3">
|
||
<p><strong>阶段流转记录</strong></p>
|
||
{notempty name="$step_record"}
|
||
<ul class="layui-timeline pt-2">
|
||
{volist name="$step_record" id="vo"}
|
||
<li class="layui-timeline-item delete-{$vo.delete_time}">
|
||
<i class="layui-icon layui-timeline-axis"></i>
|
||
{if ($vo.status == 0)}
|
||
<p style="padding-left:24px">{$vo.check_time_str}<span
|
||
class="black mx-1">{$vo.check_name}</span><span
|
||
class="mr-1 green">{$vo.status_str}</span>了项目阶段的内容。</p>
|
||
{elseif ($vo.status == 1)}
|
||
<p style="padding-left:24px">{$vo.check_time_str}<span
|
||
class="black mx-1">{$vo.check_name}</span><span
|
||
class="mr-1 green">{$vo.status_str}</span>了{$vo.flow_name}的工作。</p>
|
||
{elseif ($vo.status == 2) /}
|
||
<p style="padding-left:24px">{$vo.check_time_str}<span
|
||
class="black mx-1">{$vo.check_name}</span>在{$vo.flow_name}执行了<span
|
||
class="mx-1 red">{$vo.status_str}</span>操作。操作意见:<span
|
||
class="red">{$vo.content}</span></p>
|
||
{else /}
|
||
<p style="padding-left:24px">{$vo.check_time_str}<span
|
||
class="black mx-1">{$vo.check_name}</span><span
|
||
class="mr-1 layui-color-{$vo.status}">{$vo.status_str}</span>了该阶段流程。操作意见:<span
|
||
class="red">{$vo.content}</span></p>
|
||
{/if}
|
||
</li>
|
||
{/volist}
|
||
</ul>
|
||
{else/}
|
||
<div class="layui-data-none">暂无记录</div>
|
||
{/notempty}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="layui-col-xs12">
|
||
<div class="layui-card">
|
||
<div class="layui-card-header" style="height:45px;">
|
||
<div class="layui-row">
|
||
<div class="layui-col-md6">
|
||
<h4>项目附件</h4>
|
||
</div>
|
||
<div class="layui-col-md6" style="margin-top: 10px;">
|
||
<button type="button" class="layui-btn layui-btn-normal layui-btn-sm fr"
|
||
style="margin-left: 10px" id="fileBtn">选择文件
|
||
</button>
|
||
<button type="button" class="layui-btn layui-btn-sm layui-btn-sm2 fr" id="test9">开始上传
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="layui-row p-2" id="fileList">
|
||
{volist name="file_array" id="vo"}
|
||
<div class="layui-col-md4">
|
||
<div class="file-card">
|
||
<i class="file-icon iconfont icon-ziyuan"></i>
|
||
<div class="file-title" title="上传人:{$vo.admin_name}">
|
||
{$vo.name}
|
||
</div>
|
||
<div class="file-tool">
|
||
<a href="{$vo.filepath}" download="{$vo.name}" data-id="{$vo.id}" target="_blank"
|
||
title="大小:{$vo.filesize/1048576|round=2}MB">
|
||
<i class="iconfont icon-shujudaoru" style="color: #12bb37;"></i>
|
||
</a>
|
||
<i class="btn-delete iconfont icon-shanchu" data-id="{$vo.id}"
|
||
style="color: #FF5722;"></i>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{/volist}
|
||
{empty name="$file_array" }
|
||
<div class="content-none">暂无附件</div>
|
||
{/empty}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="layui-col-xs12">
|
||
<div class="layui-card">
|
||
<div class="layui-card-header" style="height:45px;">
|
||
<div class="layui-row">
|
||
<div class="layui-col-md6">
|
||
<h4>关联链接</h4>
|
||
</div>
|
||
<div class="layui-col-md6" style="margin-top: 10px;">
|
||
<button type="button" class="layui-btn layui-btn-sm layui-btn-sm2 fr" id="linkBtn">新增链接
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="layui-card-body">
|
||
<table class="layui-table">
|
||
<thead>
|
||
<tr>
|
||
<th width="50%">链接URL</th>
|
||
<th width="30%" style="text-align:center">链接说明</th>
|
||
<th width="10%" style="text-align:center">添加人</th>
|
||
<th width="10%" style="text-align:center">操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="linkList">
|
||
{volist name="link_array" id="vo"}
|
||
<tr>
|
||
<td><a href="{$vo.url}" target="_blank">{$vo.url}</a></td>
|
||
<td>{$vo.desc}</td>
|
||
<td style="text-align: center;">{$vo.admin_name}</td>
|
||
<td style="text-align: center;">
|
||
<div class="layui-btn-group" style="width:66px">
|
||
<button type="button" class="layui-btn layui-btn-xs link-edit"
|
||
data-id="{$vo.id}" data-href="{$vo.url}" data-desc="{$vo.desc}"><i
|
||
class="layui-icon"></i></button>
|
||
<button type="button"
|
||
class="layui-btn layui-btn-danger layui-btn-xs link-delete"
|
||
data-id="{$vo.id}"><i class="layui-icon"></i></button>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
{/volist}
|
||
{empty name="$link_array" }
|
||
<tr>
|
||
<td colspan="4" class="content-none">暂无链接</td>
|
||
</tr>
|
||
{/empty}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="layui-col-xs12">
|
||
<div class="layui-card">
|
||
<div class="layui-card-header">
|
||
<h4>项目概况</h4>
|
||
</div>
|
||
<div class="layui-card-body">
|
||
<div style="height: 200px; text-align: center;">
|
||
<dl>
|
||
<dt class="layui-card-tips">工作记录</dt>
|
||
<dd class="layui-card-value" title="工作记录数">{$detail.schedules}</dd>
|
||
</dl>
|
||
<dl>
|
||
<dt class="layui-card-tips">项目工时</dt>
|
||
<dd class="layui-card-value" title="实际工时/计划工时">{$detail.hours} /
|
||
{$detail.plan_hours}
|
||
</dd>
|
||
</dl>
|
||
{volist name="$detail.task_cate" id="vo"}
|
||
<dl>
|
||
<dt class="layui-card-tips">{$vo.title}任务</dt>
|
||
<dd class="layui-card-value" title="已完成/总任务数">{$vo.unfinish} / {$vo.count}</dd>
|
||
</dl>
|
||
{/volist}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="layui-col-xs12 ">
|
||
<div class="layui-card">
|
||
<div class="layui-card-header">
|
||
<h4>项目进度</h4>
|
||
</div>
|
||
<div class="layui-card-body">
|
||
<div class="layui-row">
|
||
<div class="layui-col-md6">
|
||
<!-- 任务完成率 -->
|
||
<div id="progress" class="data-none" style="width:100%;min-height: 200px;"></div>
|
||
</div>
|
||
<div class="layui-col-md6">
|
||
<!-- 任务延迟率 -->
|
||
<div id="delay" class="data-none" style="width:100%;min-height: 200px;"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="layui-col-xs12 ">
|
||
<div class="layui-card">
|
||
<div class="layui-card-header">
|
||
<h4>项目缺陷</h4>
|
||
</div>
|
||
<div class="layui-card-body">
|
||
<div id="rose" class="data-none" style="width:100%;min-height: 200px;"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="layui-col-xs12 layui-col-md12">
|
||
<div class="layui-card">
|
||
<div class="layui-card-header">
|
||
<h4>项目燃尽图</h4>
|
||
</div>
|
||
<div class="layui-card-body">
|
||
<div id="cross" class="data-none" style="width:100%; height:360px;"
|
||
data-tips="任务数:{$detail.tasks},已完成:{$detail.tasks_finish},未完成:{$detail.tasks_unfinish}">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="layui-col-xs12">
|
||
<div class="layui-card">
|
||
<div class="layui-card-header">
|
||
<h4>任务分配情况</h4>
|
||
</div>
|
||
<div class="layui-card-body">
|
||
<div id="plan" class="data-none" style="width:100%; height:150px;"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="layui-col-xs12">
|
||
<div class="layui-card">
|
||
<div class="layui-card-header">
|
||
<h4>工时登记情况</h4>
|
||
</div>
|
||
<div class="layui-card-body">
|
||
<div id="work" class="data-none" style="width:100%; height:150px;"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{/block}
|
||
<!-- /主体 -->
|
||
|
||
<!-- 脚本 -->
|
||
{block name="script"}
|
||
<script src="{__JS__}/echarts.min.js"></script>
|
||
|
||
<script>
|
||
//弹出上传附件框
|
||
function popUploadFile(id) {
|
||
//弹出框
|
||
layer.open({
|
||
title: '上传附件',
|
||
type: 1,
|
||
icon: 0,
|
||
area: ["600px", "400px"],
|
||
btn: ["确定", "取消"],
|
||
btn1: function (index, layro) {
|
||
//先删除要删除的已提交文件
|
||
if (deleteFilePaths) {
|
||
$.ajax({
|
||
url: basePath + 'deleteFile.do',
|
||
data: { deleteFilePaths: deleteFilePaths },
|
||
dataType: 'JSON',
|
||
Type: 'POST',
|
||
async: false,
|
||
success: function (data) {
|
||
if (data.code != 0) {
|
||
layer.msg(data.info);
|
||
return;
|
||
}
|
||
|
||
//更新弹出框对应的input
|
||
var deleteFilePathsArry = deleteFilePaths.split(",");
|
||
var newFileJsons = new Array();
|
||
for (var i in fileJsons) {
|
||
var fileData = JSON.parse(fileJsons[i]);
|
||
var isDelete = false;
|
||
for (var j in deleteFilePathsArry) {
|
||
if (fileData.filePath == deleteFilePathsArry[j]) {
|
||
isDelete = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!isDelete) {
|
||
var newFileJson = {};
|
||
newFileJson.code = fileData.code;
|
||
newFileJson.filePath = fileData.filePath;
|
||
newFileJson.size = fileData.size;
|
||
newFileJson.fileDir = fileData.fileDir;
|
||
newFileJsons.push(newFileJson);
|
||
}
|
||
}
|
||
|
||
//赋值给弹出框对应的input
|
||
$("#" + id).val('');
|
||
for (var i in newFileJsons) {
|
||
var value = JSON.stringify(newFileJsons[i]);
|
||
if ($("#" + id).val() == '') {
|
||
$("#" + id).val(value);
|
||
} else {
|
||
$("#" + id).val($("#" + id).val() + ";" + value);
|
||
}
|
||
}
|
||
},
|
||
error: function (data) {
|
||
layer.msg("未知错误,请联系管理员");
|
||
return;
|
||
}
|
||
});
|
||
}
|
||
//开始上传新的文件
|
||
if (files && files.length != 0) {
|
||
$("#testListAction").click();
|
||
} else {
|
||
if ($("#" + id).val() != '') {
|
||
$("#" + id + "State").text("已上传");
|
||
} else {
|
||
$("#" + id + "State").text("未上传");
|
||
}
|
||
layer.closeAll('page'); //关闭所有页面层
|
||
}
|
||
},
|
||
btn2: function (index, layro) {
|
||
},
|
||
closeBtn: 1,
|
||
content: content
|
||
});
|
||
|
||
var deleteFilePaths;//删除已上传的文件路径列表
|
||
var fileDirIndex;//上传到本地的文件目录
|
||
var fileJsons;//已上传的文件基本数据
|
||
if ($("#" + id).val() == '') {
|
||
fileDirIndex = new Date().getTime();
|
||
} else {
|
||
fileJsons = $("#" + id).val().split(";");
|
||
fileDirIndex = JSON.parse(fileJsons[0]).fileDir;
|
||
}
|
||
var demoListView = $('#demoList');
|
||
var files;
|
||
|
||
//加载上传文件组件
|
||
layui.use('upload', function () {
|
||
var $ = layui.jquery
|
||
, upload = layui.upload
|
||
, uploadListIns = upload.render({
|
||
elem: '#testList'
|
||
, url: basePath + 'upload.do'
|
||
, data: { fileDir: fileDirIndex }
|
||
, accept: 'file'
|
||
, multiple: true
|
||
, auto: false
|
||
, bindAction: '#testListAction'
|
||
, choose: function (obj) {
|
||
files = this.files = obj.pushFile(); //将每次选择的文件追加到文件队列
|
||
//读取本地文件
|
||
obj.preview(function (index, file, result) {
|
||
var tr = $(['<tr id="upload-' + index + '">'
|
||
, '<td>' + file.name + '</td>'
|
||
, '<td>' + (file.size / 1024).toFixed(1) + 'kb</td>'
|
||
, '<td>等待上传</td>'
|
||
, '<td>'
|
||
, '<button class="layui-btn layui-btn-xs demo-reload layui-hide">重传</button>'
|
||
, '<button class="layui-btn layui-btn-xs layui-btn-danger notUpload-delete">删除</button>'
|
||
, '</td>'
|
||
, '</tr>'].join(''));
|
||
|
||
//单个重传
|
||
tr.find('.demo-reload').on('click', function () {
|
||
obj.upload(index, file);
|
||
});
|
||
|
||
//删除
|
||
tr.find('.notUpload-delete').on('click', function () {
|
||
delete files[index]; //删除对应的文件
|
||
tr.remove();
|
||
uploadListIns.config.elem.next()[0].value = ''; //清空 input file 值,以免删除后出现同名文件不可选
|
||
});
|
||
demoListView.append(tr);
|
||
});
|
||
}
|
||
, allDone: function (obj) { //当文件全部被提交后,才触发
|
||
$("#" + id + "State").text("已上传");
|
||
layer.closeAll('page'); //关闭所有页面层
|
||
}
|
||
, done: function (res, index, upload) {
|
||
if (res.code == 0) { //上传成功
|
||
var tr = demoListView.find('tr#upload-' + index)
|
||
, tds = tr.children();
|
||
tds.eq(2).html('<span style="color: #5FB878;">上传成功</span>');
|
||
tds.eq(3).html(''); //清空操作
|
||
|
||
//赋值给弹出框对应的input
|
||
var value = JSON.stringify(res);
|
||
if ($("#" + id).val() == '') {
|
||
$("#" + id).val(value);
|
||
} else {
|
||
$("#" + id).val($("#" + id).val() + ";" + value);
|
||
}
|
||
|
||
return delete this.files[index]; //删除文件队列已经上传成功的文件
|
||
}
|
||
this.error(index, upload);
|
||
}
|
||
, error: function (index, upload) {
|
||
var tr = demoListView.find('tr#upload-' + index)
|
||
, tds = tr.children();
|
||
tds.eq(2).html('<span style="color: #FF5722;">上传失败</span>');
|
||
tds.eq(3).find('.demo-reload').removeClass('layui-hide'); //显示重传
|
||
}
|
||
});
|
||
});
|
||
|
||
//添加已上传文件列表
|
||
for (var i in fileJsons) {
|
||
var fileJson = JSON.parse(fileJsons[i]);
|
||
var filePath = fileJson.filePath;
|
||
var fileName = fileJson.filePath.split("\\")[fileJson.filePath.split("\\").length - 1];
|
||
var fileSize = fileJson.size;
|
||
var tr = $(['<tr id="upload-' + i + '">'
|
||
, '<td>' + fileName + '</td>'
|
||
, '<td>' + (fileSize / 1024).toFixed(1) + 'kb</td>'
|
||
, '<td>已上传</td>'
|
||
, '<td>'
|
||
, '<input class="layui-btn layui-hide" type="text" value="' + filePath + '"/>'
|
||
, '<button class="layui-btn layui-btn-xs layui-btn-danger upload-delete">删除</button>'
|
||
, '</td>'
|
||
, '</tr>'].join(''));
|
||
//删除
|
||
tr.find('.upload-delete').on('click', function () {
|
||
//拼接要删除的已上传文件路径
|
||
var deleteFilePath = $(this).prev().val();
|
||
if (deleteFilePaths) {
|
||
deleteFilePaths += "," + deleteFilePath;
|
||
} else {
|
||
deleteFilePaths = deleteFilePath;
|
||
}
|
||
$(this).parent().parent().remove();
|
||
|
||
});
|
||
demoListView.append(tr);
|
||
}
|
||
|
||
}
|
||
</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 chartRose = document.getElementById('rose');
|
||
var roseChart = echarts.init(chartRose);
|
||
var optionC;
|
||
|
||
optionC = {
|
||
backgroundColor: "#ffffff",
|
||
legend: {
|
||
orient: 'vertical',
|
||
left: 'left'
|
||
},
|
||
tooltip: {
|
||
trigger: 'item',
|
||
formatter: '{a} <br/>{b} : {c} ({d}%)'
|
||
},
|
||
series: [
|
||
{
|
||
name: 'Bugfixed',
|
||
type: 'pie',
|
||
radius: ['25%', '75%'],
|
||
center: ['60%', '50%'],
|
||
data: [
|
||
{ value: 40, name: '待解决' },
|
||
{ value: 38, name: '进行中' },
|
||
{ value: 32, name: '已解决' },
|
||
{ value: 28, name: '不解决' },
|
||
{ value: 26, name: '已关闭' }
|
||
]
|
||
}
|
||
]
|
||
};
|
||
|
||
|
||
var chartCross = document.getElementById('cross');
|
||
var crossChart = echarts.init(chartCross);
|
||
var optionD;
|
||
var tips = $('#cross').data('tips');
|
||
optionD = {
|
||
backgroundColor: "#ffffff",
|
||
color: ['#8C92A4', '#2C7EF8'],
|
||
title: {
|
||
text: '',
|
||
subtext: tips,
|
||
top: -10,
|
||
},
|
||
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', 'gouguEdit', 'gouguComment', 'gouguSchedule', 'employeepicker', 'editormd'];
|
||
|
||
function gouguInit() {
|
||
const layer = layui.layer, tool = layui.tool, edit = layui.gouguEdit, comment = layui.gouguComment,
|
||
upload = layui.upload;
|
||
|
||
$('#subMenu').on('click', '[data-event="subpage"]', function () {
|
||
let page = $(this).data('page');
|
||
$('#subMenu').find('li').removeClass('active');
|
||
$(this).addClass('active');
|
||
tool.page(page);
|
||
})
|
||
|
||
$('#subMenu').on('click', '[data-event="open"]', function () {
|
||
let url = $(this).data('url');
|
||
tool.open(url);
|
||
})
|
||
|
||
$('.hover-edit').hover(function () {
|
||
$(this).addClass('hover-on');
|
||
}, function () {
|
||
$(this).removeClass('hover-on');
|
||
})
|
||
|
||
$('.hover-edit').on('click', 'i', function () {
|
||
let name = $(this).data('name');
|
||
let show_txt = $('#' + name + '_' + project_id).text().replace(/[\r\n\t]/g, "");
|
||
let real_txt = $('#' + name + '_' + project_id).data('val');
|
||
if (real_txt === '') {
|
||
real_txt = show_txt;
|
||
}
|
||
editShow(project_id, name, show_txt, real_txt);
|
||
})
|
||
|
||
let loading = false;
|
||
let editPost = function (id, name, show_val, real_val) {
|
||
let callback = function (e) {
|
||
layer.closeAll();
|
||
layer.msg(e.msg);
|
||
if (e.code == 0) {
|
||
setTimeout(function () {
|
||
location.reload();
|
||
}, 1000)
|
||
}
|
||
}
|
||
let postData = { id: id };
|
||
postData[name] = real_val;
|
||
tool.post("/project/index/edit", postData, callback);
|
||
}
|
||
|
||
function editShow(id, name, show_txt, real_txt) {
|
||
if (loading == true) {
|
||
return false;
|
||
}
|
||
if (name == "name") {
|
||
edit.text(id, name, real_txt, editPost);
|
||
}
|
||
if (name == "start_time" || name == "end_time") {
|
||
edit.date(id, name, real_txt, editPost);
|
||
}
|
||
if (name == "director_uid") {
|
||
edit.employee_one(id, name, show_txt, real_txt, editPost);
|
||
}
|
||
if (name == "status") {
|
||
edit.dropdown(id, name, real_txt, opsData[name], editPost);
|
||
}
|
||
if (name == "product_id") {
|
||
loading = true;
|
||
tool.get("/api/index/get_product", {}, function (res) {
|
||
let data = res.data;
|
||
loading = false;
|
||
edit.dropdown(id, name, real_txt, data, editPost, 1);
|
||
});
|
||
}
|
||
if (name == "content") {
|
||
edit.textarea(id, name, real_txt, editPost);
|
||
}
|
||
}
|
||
|
||
|
||
$('#delProject').on('click', function () {
|
||
layer.confirm('确定要删除该项目吗?请慎重', { icon: 3, title: '提示' }, function (index) {
|
||
let callback = function (e) {
|
||
layer.closeAll();
|
||
layer.msg(e.msg);
|
||
if (e.code == 0) {
|
||
setTimeout(function () {
|
||
location.href = '/project/index/index';
|
||
}, 1000)
|
||
}
|
||
}
|
||
let postData = { "id": project_id };
|
||
tool.delete("/project/index/delete", postData, callback);
|
||
});
|
||
})
|
||
|
||
function formatLocalDate(timestamp) {
|
||
let date = new Date(timestamp * 1000);
|
||
let offset = date.getTimezoneOffset() * 60000; // 获取当前时区偏移
|
||
date = new Date(date.getTime() - offset); // 调整为本地时间
|
||
return date.toISOString().slice(0, 10); // 格式化为 YYYY-MM-DD
|
||
}
|
||
|
||
$(document).ready(function () {
|
||
$('#editProject').on('click', function () {
|
||
// 获取项目数据
|
||
$.ajax({
|
||
url: '/project/index/edit',
|
||
method: 'GET',
|
||
data: { "id": project_id },
|
||
success: function (response) {
|
||
if (response.code === 0) {
|
||
var detail = response.data.detail;
|
||
|
||
// 获取客户名称列表后再打开弹出层
|
||
$.ajax({
|
||
url: '/business/index/getlistsmore',
|
||
method: 'GET',
|
||
success: function (businessResponse) {
|
||
if (businessResponse.code === 1) {
|
||
// 创建一个映射对象来快速查找业务ID对应的名称
|
||
var businessMap = {};
|
||
businessResponse.data.forEach(function (item) {
|
||
businessMap[item.id] = item.name; // 将ID和名称存储在映射中
|
||
});
|
||
|
||
// 创建下拉选项
|
||
var businessOptions = businessResponse.data.map(function (item) {
|
||
return `<option value="${item.id}">${item.name}</option>`;
|
||
}).join('');
|
||
|
||
// 获取当前项目的 business_id,以便找到对应的名称
|
||
var selectedBusinessName = businessMap[detail.business_id] || '';
|
||
|
||
layer.open({
|
||
type: 1,
|
||
title: '编辑项目',
|
||
area: ['700px', '500px'],
|
||
content: `
|
||
<form class="layui-form" style="padding: 20px;">
|
||
<input type="hidden" name="id" value="${detail.id}">
|
||
<div class="layui-form-item" style="display:flex">
|
||
<div class="layui-inline" style="display:flex;align-items:center;justify-content:center;">
|
||
<label class="layui-form-label">客户名称</label>
|
||
<div class="">
|
||
<select name="business_id" required lay-verify="required" lay-search>
|
||
<option value="${detail.business_id}">${selectedBusinessName}</option>
|
||
${businessOptions}
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="layui-inline" style="display:flex;align-items:center;justify-content:center;">
|
||
<label class="layui-form-label">创建人</label>
|
||
<div class="" style="width: 212px">
|
||
<input type="text" name="admin_name" disabled class="layui-input" value="${detail.admin_name}">
|
||
<input type="hidden" name="admin_id" value="${detail.admin_id}">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="layui-form-item" style="display:flex">
|
||
<div class="layui-inline" style="display:flex;align-items:center;justify-content:center;">
|
||
<label class="layui-form-label">负责人</label>
|
||
<div class="" style="width: 212px">
|
||
<input type="text" name="director_name" autocomplete="off" readonly placeholder="选择阶段负责人" class="layui-input picker-one" value="${detail.director_name}">
|
||
<input type="hidden" name="director_uid" value="${detail.director_uid}">
|
||
</div>
|
||
</div>
|
||
<div class="layui-inline" style="display:flex;align-items:center;justify-content:center;">
|
||
<label class="layui-form-label">项目成员</label>
|
||
<div class="" style="width: 212px">
|
||
<input type="text" name="team_admin_names" autocomplete="off" readonly placeholder="选择阶段成员,可多选" class="layui-input picker-more" value="${detail.team_admin_names}">
|
||
<input type="hidden" name="team_admin_ids" value="${detail.team_admin_ids}">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="layui-form-item" style="display:flex">
|
||
<div class="layui-inline" style="display:flex;align-items:center;justify-content:center;">
|
||
<label class="layui-form-label">合同开始</label>
|
||
<div class="" style="width: 212px">
|
||
<input type="text" name="start_time" placeholder="请输入开始时间" autocomplete="off"
|
||
class="layui-input" id="start_time" value="${new Date(detail.start_time * 1000).toLocaleDateString('en-CA')}"
|
||
onclick="layui.use('laydate', function(){ laydate({ elem: '#start_time', format: 'YYYY-MM-DD' }); })">
|
||
</div>
|
||
</div>
|
||
<div class="layui-inline" style="display:flex;align-items:center;justify-content:center;">
|
||
<label class="layui-form-label">合同结束</label>
|
||
<div class="" style="width: 212px">
|
||
<input type="text" name="end_time" placeholder="请输入结束时间" autocomplete="off"
|
||
class="layui-input" id="end_time" value="${formatLocalDate(detail.end_time)}"
|
||
onclick="layui.use('laydate', function(){ laydate({ elem: '#end_time', format: 'YYYY-MM-DD' }); })">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="layui-form-item" style="display:flex">
|
||
<div class="layui-inline" style="display:flex;align-items:center;justify-content:center;">
|
||
<label class="layui-form-label">项目开始</label>
|
||
<div class="" style="width: 212px">
|
||
<input type="text" name="project_start_time" placeholder="请输入开始时间" autocomplete="off"
|
||
class="layui-input" id="project_start_time" value="${new Date(detail.project_start_time * 1000).toLocaleDateString('en-CA')}"
|
||
onclick="layui.use('laydate', function(){ laydate({ elem: '#project_start_time', format: 'YYYY-MM-DD' }); })">
|
||
</div>
|
||
</div>
|
||
<div class="layui-inline" style="display:flex;align-items:center;justify-content:center;">
|
||
<label class="layui-form-label">项目结束</label>
|
||
<div class="" style="width: 212px">
|
||
<input type="text" name="project_end_time" placeholder="请输入结束时间" autocomplete="off"
|
||
class="layui-input" id="project_end_time" value="${formatLocalDate(detail.project_end_time)}"
|
||
onclick="layui.use('laydate', function(){ laydate({ elem: '#project_end_time', format: 'YYYY-MM-DD' }); })">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="layui-form-item layui-form-text">
|
||
<label class="layui-form-label">项目简介</label>
|
||
<div class="layui-input-block">
|
||
<textarea name="content" required lay-verify="required" placeholder="请输入项目简介" class="layui-textarea" style="width: 530px">${detail.content}</textarea>
|
||
</div>
|
||
</div>
|
||
<div class="layui-form-item">
|
||
<div class="layui-input-block">
|
||
<button class="layui-btn" lay-submit lay-filter="saveProject">保存</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
`,
|
||
success: function (layero, index) {
|
||
layui.use(['form', 'laydate'], function () {
|
||
var form = layui.form;
|
||
var laydate = layui.laydate;
|
||
|
||
laydate.render({ elem: '#start_time', type: 'date', format: 'yyyy-MM-dd' });
|
||
laydate.render({ elem: '#end_time', type: 'date', format: 'yyyy-MM-dd' });
|
||
laydate.render({ elem: '#project_start_time', type: 'date', format: 'yyyy-MM-dd' });
|
||
laydate.render({ elem: '#project_end_time', type: 'date', format: 'yyyy-MM-dd' });
|
||
|
||
form.on('submit(saveProject)', function (data) {
|
||
$.ajax({
|
||
url: '/project/index/edit?id=' + detail.id,
|
||
method: 'POST',
|
||
data: data.field,
|
||
success: function (response) {
|
||
if (response.code === 0) {
|
||
layer.msg('保存成功');
|
||
layer.close(index);
|
||
location.reload();
|
||
} else {
|
||
layer.msg(response.msg || '保存失败');
|
||
}
|
||
},
|
||
error: function () {
|
||
layer.msg('保存失败,请检查网络');
|
||
}
|
||
});
|
||
return false;
|
||
});
|
||
|
||
form.render();
|
||
form.val('editProjectForm', { 'business_id': detail.business_id });
|
||
});
|
||
}
|
||
});
|
||
} else {
|
||
layer.msg(businessResponse.msg || '客户名称加载失败');
|
||
}
|
||
},
|
||
error: function () {
|
||
layer.msg('请求客户名称失败,请检查网络');
|
||
}
|
||
});
|
||
} else {
|
||
layer.msg(response.msg || '获取项目详情失败');
|
||
}
|
||
},
|
||
error: function () {
|
||
layer.msg('请求失败,请检查网络');
|
||
}
|
||
});
|
||
});
|
||
});
|
||
|
||
|
||
//关闭项目
|
||
$('#closeProject').on('click', function () {
|
||
layer.confirm('确定要关闭该项目吗?请慎重', { icon: 3, title: '提示' }, function (index) {
|
||
$.ajax({
|
||
url: "/project/index/close",
|
||
type: "POST",
|
||
data: { "id": project_id },
|
||
success: function (e) {
|
||
layer.closeAll();
|
||
layer.msg(e.msg);
|
||
if (e.code == 0) {
|
||
setTimeout(function () {
|
||
window.location.href = '/project/index/index';
|
||
}, 1000);
|
||
}
|
||
},
|
||
error: function () {
|
||
layer.msg('请求失败,请检查网络或联系管理员');
|
||
}
|
||
});
|
||
});
|
||
});
|
||
|
||
//开启项目
|
||
$('#reopenProject').on('click', function () {
|
||
layer.confirm('确定要开启该项目吗?请慎重', { icon: 3, title: '提示' }, function (index) {
|
||
$.ajax({
|
||
url: "/project/index/open",
|
||
type: "POST", // 根据实际情况调整请求类型
|
||
data: { "id": project_id },
|
||
success: function (e) {
|
||
layer.closeAll();
|
||
layer.msg(e.msg);
|
||
if (e.code == 0) {
|
||
setTimeout(function () {
|
||
window.location.href = '/project/index/index';
|
||
}, 1000);
|
||
}
|
||
},
|
||
error: function () {
|
||
layer.msg('请求失败,请检查网络或联系管理员');
|
||
}
|
||
});
|
||
});
|
||
});
|
||
|
||
$('body').on('click', '[data-event="step"]', function () {
|
||
let check = $(this).data('check');
|
||
let callback = function (e) {
|
||
layer.msg(e.msg);
|
||
if (e.code == 0) {
|
||
setTimeout(function () {
|
||
location.reload();
|
||
}, 2000)
|
||
}
|
||
}
|
||
if (check == 2) {
|
||
layer.open({
|
||
type: 1,
|
||
title: '请输入退回的原因或理由',
|
||
area: ['800px', '360px'],
|
||
content: '<div style="padding:5px;"><textarea class="layui-textarea" id="remarkTextarea" style="width: 100%; height: 240px;"></textarea></div>',
|
||
btnAlign: 'c',
|
||
btn: ['提交保存'],
|
||
yes: function () {
|
||
let remark = $("#remarkTextarea").val();
|
||
if (remark != '') {
|
||
tool.post("/api/project/step_check", {
|
||
id: project_id,
|
||
check: check,
|
||
content: remark
|
||
}, callback);
|
||
} else {
|
||
layer.msg('请输入原因或理由');
|
||
}
|
||
}
|
||
})
|
||
} else {
|
||
layer.confirm('确认已完成该阶段工作,进入下个阶段?', {
|
||
icon: 3,
|
||
title: '提示'
|
||
},
|
||
function (index) {
|
||
tool.post("/api/project/step_check", { id: project_id, check: check }, callback);
|
||
})
|
||
}
|
||
});
|
||
|
||
//选完文件后不自动上传
|
||
upload.render({
|
||
elem: '#fileBtn'
|
||
, url: '/api/index/upload' //此处配置你自己的上传接口即可
|
||
, exts: 'jpeg|jpg|png|gif|doc|docx|ppt|pptx|xls|xlsx|pdf|zip|rar|7z|ai|psd|drawio|txt|xmind' //只允许上传文件
|
||
, auto: false
|
||
//,multiple: true
|
||
, bindAction: '#test9'
|
||
, before: function (obj) {
|
||
layer.msg('上传中...', { time: 3600000 });
|
||
}
|
||
, done: function (res, index, upload) {
|
||
let callback = function (e) {
|
||
layer.msg('上传成功');
|
||
setTimeout(function () {
|
||
location.reload();
|
||
}, 2000)
|
||
}
|
||
let postData = {
|
||
'topic_id': project_id,
|
||
'file_id': res.data.id,
|
||
'file_name': res.data.name,
|
||
'module': 'project'
|
||
};
|
||
console.log('输出了:' + postData.file_name);
|
||
console.log('输出了:' + postData.file_id);
|
||
tool.post("/api/appendix/add", postData, callback);
|
||
}
|
||
, error: function (index, upload) {
|
||
layer.msg('上传失败');
|
||
}
|
||
});
|
||
|
||
$('#fileList').on('click', '.btn-delete', function () {
|
||
let id = $(this).data('id');
|
||
layer.confirm('确定要删除该附件吗?', { icon: 3, title: '提示' }, function (index) {
|
||
let callback = function (e) {
|
||
layer.closeAll();
|
||
layer.msg(e.msg);
|
||
setTimeout(function () {
|
||
location.reload();
|
||
}, 2000)
|
||
}
|
||
let postData = { "id": id };
|
||
tool.delete("/api/appendix/delete", postData, callback);
|
||
});
|
||
})
|
||
|
||
$('#linkBtn').on('click', function () {
|
||
comment.addLink(0, project_id, 'project', '', '');
|
||
})
|
||
$('#linkList').on('click', '.link-edit', function () {
|
||
let id = $(this).data('id');
|
||
let url = $(this).data('url');
|
||
let desc = $(this).data('desc');
|
||
comment.addLink(id, project_id, 'project', url, desc);
|
||
})
|
||
$('#linkList').on('click', '.link-delete', function () {
|
||
let id = $(this).data('id');
|
||
layer.confirm('确定要删除该链接吗?', { icon: 3, title: '提示' }, function (index) {
|
||
let callback = function (e) {
|
||
layer.closeAll();
|
||
layer.msg(e.msg);
|
||
setTimeout(function () {
|
||
location.reload();
|
||
}, 2000)
|
||
}
|
||
let postData = { "id": id };
|
||
tool.delete("/api/appendix/delete_link", postData, callback);
|
||
});
|
||
})
|
||
|
||
let callback = function (res) {
|
||
if (res.data.date_tasks instanceof Array == false) {
|
||
optionA.title.text = res.data.task_pie.ok_lv + '%';
|
||
optionA.series = [
|
||
{
|
||
type: 'pie',
|
||
radius: ['60%', '80%'],
|
||
center: ['50%', '50%'],
|
||
avoidLabelOverlap: false,
|
||
label: {
|
||
show: false
|
||
},
|
||
data: [
|
||
{ value: res.data.task_pie.count - res.data.task_pie.count_ok, name: '待处理' },
|
||
{ value: res.data.task_pie.count_ok, name: '已完成' }
|
||
]
|
||
}
|
||
];
|
||
optionA && progressChart.setOption(optionA);
|
||
|
||
optionB.title.text = res.data.task_pie.delay_lv + '%';
|
||
optionB.series = [
|
||
{
|
||
type: 'pie',
|
||
radius: ['60%', '80%'],
|
||
center: ['50%', '50%'],
|
||
avoidLabelOverlap: false,
|
||
label: {
|
||
show: false
|
||
},
|
||
data: [{
|
||
value: res.data.task_pie.delay,
|
||
name: '延误',
|
||
itemStyle: {
|
||
color: "#ED6666",
|
||
}
|
||
},
|
||
{
|
||
value: res.data.task_pie.count - res.data.task_pie.delay,
|
||
name: '按时完成',
|
||
itemStyle: {
|
||
color: "#91CC75",
|
||
}
|
||
}
|
||
]
|
||
}
|
||
];
|
||
optionB && delayChart.setOption(optionB);
|
||
|
||
optionC.series = [
|
||
{
|
||
name: 'Bugfixed',
|
||
type: 'pie',
|
||
radius: ['25%', '75%'],
|
||
center: ['60%', '50%'],
|
||
data: [
|
||
{ value: res.data.bug_status.status_a, name: '待解决' },
|
||
{ value: res.data.bug_status.status_b, name: '进行中' },
|
||
{ value: res.data.bug_status.status_c, name: '已解决' },
|
||
{ value: res.data.bug_status.status_d, name: '不解决' },
|
||
{ value: res.data.bug_status.status_e, name: '已关闭' }
|
||
]
|
||
}
|
||
]
|
||
optionC && roseChart.setOption(optionC);
|
||
|
||
|
||
var dataD = cross_count(res.data.date_tasks, res.data.date_tasks_ok);
|
||
optionD.xAxis = {
|
||
type: 'category',
|
||
boundaryGap: false,
|
||
splitLine: {
|
||
show: true,
|
||
lineStyle: {
|
||
type: 'dashed'
|
||
}
|
||
},
|
||
data: dataD.x,
|
||
axisLabel: {
|
||
rotate: 30,
|
||
formatter: function (value, index) {
|
||
return value.slice(5);
|
||
}
|
||
}
|
||
};
|
||
optionD.series = [
|
||
{
|
||
name: '任务计划剩余',
|
||
type: 'line',
|
||
showSymbol: false,
|
||
markLine: {
|
||
data: [{ type: 'average', name: 'Avg' }],
|
||
},
|
||
lineStyle: {
|
||
width: 2
|
||
},
|
||
data: dataD.y
|
||
},
|
||
{
|
||
name: '任务实际剩余',
|
||
type: 'line',
|
||
showSymbol: false,
|
||
areaStyle: {
|
||
opacity: 0.1
|
||
},
|
||
markLine: {
|
||
data: [{ type: 'average', name: 'Avg' }],
|
||
},
|
||
lineStyle: {
|
||
width: 2
|
||
},
|
||
data: dataD.y2
|
||
}
|
||
]
|
||
optionD && crossChart.setOption(optionD)
|
||
|
||
var dataE = getCalendarData(res.data.date_tasks);
|
||
optionE.calendar.range = dataE.range,
|
||
optionE.series = {
|
||
type: 'heatmap',
|
||
coordinateSystem: 'calendar',
|
||
data: dataE.data
|
||
}
|
||
optionE && planChart.setOption(optionE);
|
||
|
||
if (res.data.date_schedules instanceof Array == false) {
|
||
var dataF = getCalendarData(res.data.date_schedules);
|
||
optionF.calendar.range = dataF.range,
|
||
optionF.series = {
|
||
type: 'heatmap',
|
||
coordinateSystem: 'calendar',
|
||
data: dataF.data
|
||
}
|
||
optionF && workChart.setOption(optionF);
|
||
}
|
||
}
|
||
}
|
||
tool.get('/api/project/get_chart_data', { 'project_id': project_id }, callback);
|
||
|
||
window.onresize = function () {
|
||
progressChart.resize();
|
||
delayChart.resize();
|
||
roseChart.resize();
|
||
crossChart.resize();
|
||
planChart.resize();
|
||
workChart.resize();
|
||
}
|
||
}
|
||
</script>
|
||
{/block}
|
||
<!-- /脚本 --> |