This commit is contained in:
holan20180123
2020-08-21 15:44:57 +08:00
5 changed files with 273 additions and 9 deletions
+60 -2
View File
@@ -705,7 +705,7 @@ class block extends control
foreach($programs as $programID => $program)
{
$members = $this->project->getTeamMemberPairs($programID);
$consumed = $this->dao->select('sum(consumed) as consumed')->from(TABLE_TASK)->where('program')->eq($programID)->andWhere('deleted')->eq(0)->andWhere('status')->ne('cancel')->fetch('consumed');
$consumed = $this->dao->select('sum(consumed) as consumed')->from(TABLE_TASK)->where('program')->eq($programID)->andWhere('deleted')->eq(0)->andWhere('parent')->lt(1)->fetch('consumed');
$leftTasks = $this->dao->select('count(*) as leftTasks')->from(TABLE_TASK)->where('program')->eq($programID)->andWhere('deleted')->eq(0)->andWhere('status')->in('wait,doing,pause')->fetch('leftTasks');
$leftStories = $this->dao->select('count(*) as leftStories')->from(TABLE_STORY)->where('program')->eq($programID)->andWhere('deleted')->eq(0)->andWhere('status')->eq('active')->fetch('leftStories');
$leftBugs = $this->dao->select('count(*) as leftBugs')->from(TABLE_BUG)->where('program')->eq($programID)->andWhere('deleted')->eq(0)->andWhere('status')->eq('active')->fetch('leftBugs');
@@ -762,6 +762,64 @@ class block extends control
$this->$func();
}
/**
* Print project statistic block.
*
* @access public
* @return void
*/
public function printProgramStatisticBlock()
{
if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
$this->loadModel('project');
$this->app->loadLang('task');
$this->app->loadLang('story');
$status = isset($this->params->type) ? $this->params->type : 'all';
$num = isset($this->params->num) ? (int)$this->params->num : 15;
/* Get projects. */
$programs = $this->loadModel('program')->getUserPrograms($status, 'id_desc', $num);
if(empty($programs))
{
$this->view->programs = $programs;
return false;
}
foreach($programs as $programID => $program)
{
$program->allStories = $program->doneStories = $program->leftStories = 0;
$program->consumed = $this->dao->select('sum(consumed) as consumed')->from(TABLE_TASK)
->where('program')->eq($programID)
->andWhere('deleted')->eq(0)
->andWhere('parent')->lt(1)
->fetch('consumed');
$members = $this->project->getTeamMemberPairs($programID);
$program->countMembers = count($members) ? count($members) - 1 : 0;
$stories = $this->dao->select('id, status')->from(TABLE_STORY)
->where('deleted')->eq(0)
->andWhere('type')->eq('story')
->andWhere('status')->ne('draft')
->andWhere('program')->eq($programID)
->fetchPairs();
foreach($stories as $id => $status)
{
$program->allStories ++;
if($status == 'closed') $program->doneStories ++;
if($status != 'closed') $program->leftStories ++;
}
$program->progress = $program->allStories == 0 ? 0 : ceil($program->doneStories / $program->allStories) * 100;
//$program->projects = $this->dao->select('*')
}
$this->view->programs = $programs;
}
/**
* Print product statistic block.
*
@@ -1089,7 +1147,7 @@ class block extends control
$this->view->people = $this->dao->select('sum(people) as people')->from(TABLE_DURATIONESTIMATION)->where('program')->eq($this->session->program)->fetch('people');
$this->view->members = count($members) ? count($members) - 1 : 0;
$this->view->consumed = $this->dao->select('sum(consumed) as consumed')->from(TABLE_TASK)->where('program')->eq($programID)->andWhere('deleted')->eq(0)->andWhere('status')->ne('cancel')->fetch('consumed');
$this->view->consumed = $this->dao->select('sum(consumed) as consumed')->from(TABLE_TASK)->where('program')->eq($programID)->andWhere('deleted')->eq(0)->andWhere('parent')->lt(1)->fetch('consumed');
$this->view->budget = $budget;
}
+9 -7
View File
@@ -245,8 +245,10 @@ $lang->block->default['full']['my']['3']['grid'] = 4;
$lang->block->default['full']['my']['3']['source'] = 'todo';
$lang->block->default['full']['my']['3']['params']['num'] = '20';
$lang->block->default['full']['my']['4'] = $lang->block->default['project']['1'];
$lang->block->default['full']['my']['4']['source'] = 'project';
$lang->block->default['full']['my']['4']['title'] = '项目统计';
$lang->block->default['full']['my']['4']['block'] = 'statistic';
$lang->block->default['full']['my']['4']['source'] = 'program';
$lang->block->default['full']['my']['4']['grid'] = 8;
$lang->block->default['full']['my']['5']['title'] = '个人贡献';
$lang->block->default['full']['my']['5']['block'] = 'contribute';
@@ -268,12 +270,12 @@ $lang->block->default['full']['my']['8']['title'] = '项目人力投入';
$lang->block->default['full']['my']['8']['block'] = 'programteam';
$lang->block->default['full']['my']['8']['grid'] = 8;
$lang->block->default['full']['my']['8']['title'] = '项目列表';
$lang->block->default['full']['my']['8']['block'] = 'program';
$lang->block->default['full']['my']['8']['grid'] = 8;
$lang->block->default['full']['my']['9']['title'] = '项目列表';
$lang->block->default['full']['my']['9']['block'] = 'program';
$lang->block->default['full']['my']['9']['grid'] = 8;
$lang->block->default['full']['my']['8']['params']['orderBy'] = 'id_desc';
$lang->block->default['full']['my']['8']['params']['num'] = '15';
$lang->block->default['full']['my']['9']['params']['orderBy'] = 'id_desc';
$lang->block->default['full']['my']['9']['params']['num'] = '15';
$lang->block->num = '数量';
$lang->block->type = '类型';
@@ -0,0 +1,152 @@
<style>
.types-line {display: table; padding: 0; margin: 0 auto;}
.types-line > li {display: table-cell;}
.types-line > li > div {position: relative; padding: 18px 5px 5px; text-align: center;}
.types-line > li > div:before {content: ''; display: block; background: #eee; width: 100%; height: 2px; position: absolute; left: 50%; top: 4px;}
.types-line > li:last-child > div:before {display: none;}
.types-line > li > div:after {content: ''; display: block; background: #FFFFFF; box-shadow: 0 2px 4px 0 rgba(170,170,170,0.50), 0 0 5px 0 rgba(0,0,0,0.1); width: 10px; height: 10px; position: absolute; border-radius: 50%; top: 0; left: 50%; margin-left: -2px;}
.types-line > li > div > small {display: block; color: #A6AAB8;}
.types-line > li > div > span {display: block; color: #CBD0DB; font-size: 16px;}
.product-info {position: relative; height: 65px;}
.product-info + .product-info {margin-top: 10px;}
.product-info .progress {position: absolute; left: 10px; top: 35px; right: 100px;}
.product-info .progress-info {position: absolute; left: 8px; top: 10px; width: 180px; font-size: 12px;}
.product-info .type-info {color: #A6AAB8; text-align: center; position: absolute; right: 0; top: 6px; width: 100px;}
html[lang="en"] .product-info .type-info {color: #A6AAB8; text-align: center; position: absolute; right: 0; top: 6px; width: 110px;}
.product-info .type-value,
.product-info .type-label {font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
.product-info .type-value {font-size: 14px;}
.product-info .type-value > strong {font-size: 20px; color: #3C4353;}
.product-info .actions {position: absolute; left: 10px; top: 14px;}
.block-statistic .panel-body {padding-top: 0}
.block-statistic .tile {margin-bottom: 30px;}
.block-statistic .tile-title {font-size: 18px; color: #A6AAB8;}
.block-statistic .tile-amount {font-size: 48px; margin-bottom: 10px;}
.block-statistic .col-nav {border-right: 1px solid #EBF2FB; width: 260px; padding: 0;}
.block-statistic .nav-secondary > li {position: relative}
.block-statistic .nav-secondary > li > a {font-size: 14px; color: #838A9D; position: relative; box-shadow: none; padding-left: 20px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; transition: all .2s;}
.block-statistic .nav-secondary > li > a:first-child {padding-right: 36px;}
.block-statistic .nav-secondary > li.active > a:first-child {color: #3C4353; background: transparent; box-shadow: none;}
.block-statistic .nav-secondary > li.active > a:first-child:hover,
.block-statistic .nav-secondary > li.active > a:first-child:focus,
.block-statistic .nav-secondary > li > a:first-child:hover {box-shadow: none; border-radius: 4px 0 0 4px;}
.block-statistic .nav-secondary > li.active > a:first-child:before {content: ' '; display: block; left: -1px; top: 10px; bottom: 10px; width: 4px; background: #006af1; position: absolute;}
.block-statistic .nav-secondary > li > a.btn-view {position: absolute; top: 0; right: 0; bottom: 0; padding: 8px; width: 36px; text-align: center; opacity: 0;}
.block-statistic .nav-secondary > li:hover > a.btn-view {opacity: 1}
.block-statistic .nav-secondary > li.active > a.btn-view {box-shadow: none}
.block-statistic .nav-secondary > li.switch-icon {display: none;}
.block-statistic.block-sm .panel-body {padding-bottom: 10px; position: relative; padding-top: 45px; border-radius: 3px;}
.block-statistic.block-sm .panel-body > .table-row,
.block-statistic.block-sm .panel-body > .table-row > .col {display: block; width: auto;}
.block-statistic.block-sm .panel-body > .table-row > .tab-content {padding: 0; margin: 0 -5px;}
.block-statistic.block-sm .tab-pane > .table-row > .col-5 {width: 125px;}
.block-statistic.block-sm .tab-pane > .table-row > .col-5 > .table-row {padding: 5px 0;}
.block-statistic.block-sm .col-nav {border-left: none; position: absolute; top: 0; left: 15px; right: 15px; background: #f5f5f5;}
.block-statistic.block-sm .nav-secondary {display: table; width: 100%; padding: 0; table-layout: fixed;}
.block-statistic.block-sm .nav-secondary > li {display: none}
.block-statistic.block-sm .nav-secondary > li.switch-icon,
.block-statistic.block-sm .nav-secondary > li.active {display: table-cell; width: 100%; text-align: center;}
.block-statistic.block-sm .nav-secondary > li.active > a:hover {cursor: default; background: none;}
.block-statistic.block-sm .nav-secondary > li.switch-icon > a:hover {background: rgba(0,0,0,0.07);}
.block-statistic.block-sm .nav-secondary > li > a {padding: 5px 10px; border-radius: 4px;}
.block-statistic.block-sm .nav-secondary > li > a:before {display: none;}
.block-statistic.block-sm .nav-secondary > li.switch-icon {width: 40px;}
.block-statistic.block-sm .nav-secondary > li.active > a:first-child:before {display: none}
.block-statistic.block-sm .nav-secondary > li.active > a.btn-view {width: auto; left: 0; right: 0;}
.block-statistic.block-sm .nav-secondary > li.active > a.btn-view > i {display: none;}
.block-statistic.block-sm .nav-secondary > li.active > a.btn-view:hover {cursor: pointer; background: rgba(0,0,0,.1)}
.status-count{margin:auto}
.status-count tr:first-child td:last-child{color:#000;font-weight:bold}
</style>
<script>
<?php $blockNavId = 'nav-' . uniqid(); ?>
$(function()
{
var $nav = $('#<?php echo $blockNavId;?>');
$nav.on('click', '.switch-icon', function(e)
{
var isPrev = $(this).is('.prev');
var $activeItem = $nav.children('.active');
var $next = $activeItem[isPrev ? 'prev' : 'next']('li:not(.switch-icon)');
if ($next.length) $next.find('a').trigger('click');
else $nav.children('li:not(.switch-icon)')[isPrev ? 'last' : 'first']().find('a').trigger('click');
e.preventDefault();
});
var $programLi = $('#activeProject');
if($programLi.length)
{
var programLi = $programLi[0];
$(".col ul.nav").animate({scrollTop: programLi.offsetTop}, "slow");
}
});
</script>
<div class="panel-body">
<div class="table-row">
<?php if(empty($programs)):?>
<div class="table-empty-tip">
<p><span class="text-muted"><?php echo $lang->block->noData;?></span></p>
</div>
<?php else:?>
<div class="col col-nav">
<ul class="nav nav-stacked nav-secondary scrollbar-hover" id='<?php echo $blockNavId;?>'>
<li class='switch-icon prev'><a><i class='icon icon-arrow-left'></i></a></li>
<?php $selected = empty($_SESSION['program']) ? key($programs) : $this->session->program;?>
<?php foreach($programs as $program):?>
<li <?php if($program->id == $selected) echo "class='active' id='activeProject'";?> programID='<?php echo $program->id;?>'>
<a href="###" data-target="#tab3Content<?php echo $program->id;?>" data-toggle="tab"><?php echo $program->name;?></a>
<?php echo html::a(helper::createLink('program', 'index', "programID=$program->id"), "<i class='icon-arrow-right text-primary'></i>", '', "class='btn-view' title={$lang->program->index}");?>
</li>
<?php endforeach;?>
<li class='switch-icon next'><a><i class='icon icon-arrow-right'></i></a></li>
</ul>
</div>
<div class="col tab-content">
<?php foreach($programs as $program):?>
<div class="tab-pane fade<?php if($program->id == $selected) echo ' active in';?>" id="tab3Content<?php echo $program->id;?>">
<div class="table-row">
<div class="col-5 text-middle text-center">
<div class="progress-pie inline-block space" data-value="<?php echo $program->progress;?>" data-doughnut-size="84">
<canvas width="120" height="120"></canvas>
<div class="progress-info">
<small><?php echo $lang->story->common . $lang->program->doneStories;?></small>
<strong><?php echo $program->doneStories;?></strong>
</div>
</div>
<div class="table-row text-center small text-muted with-padding">
<div class="col-4 text-bottom">
<div><?php echo $lang->program->allStories;?></div>
<div><?php echo $program->allStories;?></div>
</div>
<div class="col-4">
<span class="label label-dot label-primary"></span>
<div><?php echo $lang->program->doneStories;?></div>
<div><?php echo $program->doneStories;?></div>
</div>
<div class="col-4">
<span class="label label-dot label-pale"></span>
<div><?php echo $lang->program->leftStories;?></div>
<div><?php echo $program->leftStories;?></div>
</div>
</div>
</div>
<div class="col-7">
<div class="program-info">
<div class='title'><?php echo $lang->program->allInput;?></div>
<div class='info'>
<span><i class='icon icon-group'></i><?php echo $program->countMembers;?></span>
<span><i class='icon icon-clock'></i><?php echo $program->consumed;?></span>
<span><i class='icon icon-yen'></i><?php echo $program->budget;?></span>
</div>
</div>
<div class="project-info">
</div>
</div>
</div>
</div>
<?php endforeach;?>
</div>
<?php endif;?>
</div>
</div>
+48
View File
@@ -0,0 +1,48 @@
<?php
$lang->design->common = 'Design';
$lang->design->browse = 'List';
$lang->design->commit = 'Link Commit';
$lang->design->submission = 'Commit';
$lang->design->version = 'Revision';
$lang->design->assignedTo = 'AssignedTo';
$lang->design->actions = 'Actions';
$lang->design->delete = 'Delete';
$lang->design->confirmDelete = 'Do you want to delete this design?';
$lang->design->edit = 'Edit';
$lang->design->products = 'Linked Product';
$lang->design->story = 'Linked Story';
$lang->design->file = 'File';
$lang->design->type = 'Type';
$lang->design->name = 'Name';
$lang->design->create = 'Create Design';
$lang->design->view = 'View';
$lang->design->desc = 'Description';
$lang->design->product = 'Linked Product';
$lang->design->basicInfo = 'Basic Information';
$lang->design->commitDate = 'Committed Date';
$lang->design->affectedStory = "{$lang->storyCommon}";
$lang->design->affectedTasks = 'Task';
$lang->design->submit = 'Submit Review';
$lang->design->revision = 'Linked Code';
$lang->design->designView = 'Details';
$lang->design->reviewObject = 'Review Object';
$lang->design->createdBy = 'CreatedBy';
$lang->design->createdDate = 'CreatedDate';
$lang->design->basicInfo = 'Basic Information';
$lang->design->typeList = array();
$lang->design->typeList['HLDS'] = 'High-Level';
$lang->design->typeList['DDS'] = 'Detailed';
$lang->design->typeList['DBDS'] = 'Database';
$lang->design->typeList['ADS'] = 'API';
$lang->design->range = 'Impact';
$lang->design->errorSelection = 'No record selected!';
$lang->design->noDesign = 'No record.';
$lang->design->rangeList = array();
$lang->design->rangeList['all'] = 'All';
$lang->design->rangeList['assign'] = 'Selected';
$lang->design->featureBar['all'] = 'All';
$lang->design->featureBar += $lang->design->typeList;
+4
View File
@@ -53,6 +53,10 @@ $lang->program->leftTasks = '剩余任务';
$lang->program->leftBugs = '剩余Bug';
$lang->program->children = '子项目';
$lang->program->parent = '父项目';
$lang->program->allStories = '总需求';
$lang->program->doneStories = '已完成';
$lang->program->leftStories = '剩余需求';
$lang->program->allInput = '项目总投入';
$lang->program->unitList[''] = '';
$lang->program->unitList['yuan'] = '元';