* finish task #6769,6768.

This commit is contained in:
wangyidong
2019-12-25 09:33:40 +08:00
parent 1c33392243
commit 5eb7f1c04c
10 changed files with 615 additions and 100 deletions
+8
View File
@@ -122,6 +122,7 @@ $lang->menu->my = '<span>Dashboard</span>|my|index';
$lang->menu->product = $lang->productCommon . '|product|index|locate=no';
$lang->menu->project = $lang->projectCommon . '|project|index|locate=no';
$lang->menu->qa = 'QA|qa|index';
$lang->menu->repo = 'Code|repo|log';
$lang->menu->doc = 'Doc|doc|index';
$lang->menu->report = 'Report|report|index';
$lang->menu->company = 'Company|company|index';
@@ -330,6 +331,12 @@ $lang->caselib->menu->testsuite = array('link' => 'Suite|testsuite|browse|');
$lang->caselib->menu->report = array('link' => 'Report|testreport|browse|');
$lang->caselib->menu->caselib = array('link' => 'Case Library|caselib|browse|libID=%s', 'alias' => 'create,createcase,view,edit,batchcreatecase,showimport', 'subModule' => 'tree,testcase');
$lang->repo = new stdclass();
$lang->repo->menu = new stdclass();
$lang->repo->menu->browse = array('link' =>'Browse|repo|log|repoID=%s&entry=', 'alias' => 'diff,view,revision,showsynccomment');
$lang->repo->menu->settings = 'Settings|repo|settings|repoID=%s';
$lang->repo->menu->delete = array('link' => 'Delete|repo|delete|repoID=%s', 'target' => 'hiddenwin');
/* Doc menu settings. */
$lang->doc = new stdclass();
$lang->doc->menu = new stdclass();
@@ -874,6 +881,7 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyTest')
/* Adjust menu group. */
$lang->menugroup->bug = 'bug';
$lang->menugroup->testcase = 'testcase';
$lang->menugroup->case = 'testcase';
$lang->menugroup->testtask = 'testtask';
$lang->menugroup->testsuite = 'testsuite';
$lang->menugroup->caselib = 'caselib';
+1
View File
@@ -94,6 +94,7 @@ $lang->report->menuOrder[5] = 'product';
$lang->report->menuOrder[10] = 'prj';
$lang->report->menuOrder[15] = 'test';
$lang->report->menuOrder[20] = 'staff';
$lang->report->menuOrder[25] = 'annual';
/* company menu order. */
$lang->company->menuOrder[5] = 'browseUser';
+1 -1
View File
@@ -101,7 +101,6 @@ $lang->loading = '稍候...';
$lang->notFound = '抱歉,您访问的对象并不存在!';
$lang->notPage = '抱歉,您访问的功能正在开发中!';
$lang->showAll = '[[全部显示]]';
$lang->selectedItems = '已选择 <strong>{0}</strong> 项';
$lang->future = '未来';
$lang->year = '年';
@@ -354,6 +353,7 @@ $lang->report->menu->product = array('link' => $lang->productCommon . '|report|p
$lang->report->menu->prj = array('link' => $lang->projectCommon . '|report|projectdeviation');
$lang->report->menu->test = array('link' => '测试|report|bugcreate', 'alias' => 'bugassign');
$lang->report->menu->staff = array('link' => '组织|report|workload');
$lang->report->menu->annual = array('link' => '年度总结|report|annualData', 'target' => '_blank');
$lang->report->notice = new stdclass();
$lang->report->notice->help = '注:统计报表的数据来源于列表页面的检索结果,生成统计报表前请先在列表页面进行检索。比如列表页面我们检索的是%tab%,那么报表就是基于之前检索的%tab%的结果集进行统计。';
+18
View File
@@ -6,3 +6,21 @@ $config->report->dailyreminder->bug = true;
$config->report->dailyreminder->task = true;
$config->report->dailyreminder->todo = true;
$config->report->dailyreminder->testTask = true;
$config->report->annualData['po']['block1'] = array('title' => 'baseInfo', 'data' => array('logins', 'involvedProducts', 'createdPlans', 'createdStories'));
$config->report->annualData['po']['block2'] = array('title' => 'productOverview', 'data' => array());
$config->report->annualData['po']['block3'] = array('title' => '', 'data' => array('products'));
$config->report->annualData['po']['block4'] = array('title' => 'poData', 'data' => array('storyPri', 'storyStage'));
$config->report->annualData['po']['block5'] = array('title' => 'poStatistics', 'data' => array('storyMonth'));
$config->report->annualData['dev']['block1'] = array('title' => 'baseInfo', 'data' => array('logins', 'actions', 'efforts', 'consumed'));
$config->report->annualData['dev']['block2'] = array('title' => 'projectOverview', 'data' => array('doneProject', 'doingProject', 'suspendProject'));
$config->report->annualData['dev']['block3'] = array('title' => '', 'data' => array('projects'));
$config->report->annualData['dev']['block4'] = array('title' => 'devData', 'data' => array('finishedTaskPri', 'resolvedBugPri'));
$config->report->annualData['dev']['block5'] = array('title' => 'devStatistics', 'data' => array('effortMonth'));
$config->report->annualData['qa']['block1'] = array('title' => 'baseInfo', 'data' => array('logins', 'actions', 'foundBugs', 'createdCases'));
$config->report->annualData['qa']['block2'] = array('title' => 'projectOverview', 'data' => array('doneProject', 'doingProject', 'suspendProject'));
$config->report->annualData['qa']['block3'] = array('title' => '', 'data' => array('projects'));
$config->report->annualData['qa']['block4'] = array('title' => 'qaData', 'data' => array('bugPri', 'casePri'));
$config->report->annualData['qa']['block5'] = array('title' => 'qaStatistics', 'data' => array('bugMonth', 'caseMonth'));
+101 -1
View File
@@ -244,8 +244,108 @@ class report extends control
* @access public
* @return void
*/
public function annualData()
public function annualData($year = '')
{
if(empty($year)) $year = date('Y');
$account = $this->app->user->account;
$role = 'po';
if($this->app->user->role == 'dev' or $this->app->user->role == 'td' or $this->app->user->role == 'pm') $role = 'dev';
if($this->app->user->role == 'qd' or $this->app->user->role == 'qa') $role = 'qa';
$role = 'qa';
$data = array();
$data['logins'] = $this->report->getUserYearLogins($account, $year);
if($role == 'po')
{
$products = $this->report->getUserYearProducts($account, $year);
$data['involvedProducts'] = count($products);
$planGroups = $this->report->getPlansByProducts($products, $year);
$planCount = 0;
foreach($planGroups as $plans) $planCount += $plans;
$data['createdPlans'] = $planCount;
$data['productStat'] = $this->report->getStatByProducts($products, $account, $year);
$storyInfo = $this->report->getUserYearStory($account, $year);
$data['createdStories'] = $storyInfo['count'];
$data['storyPri'] = $storyInfo['pri'];
$data['storyStage'] = $storyInfo['stage'];
$data['storyMonth'] = $storyInfo['month'];
$storyGroups = $this->report->getStoriesByProducts($products, $year);
foreach($products as $productID => $product)
{
$product->plans = zget($planGroups, $productID, 0);
$product->stories = zget($storyGroups, $productID, 0);
}
$data['products'] = $products;
}
elseif($role == 'dev')
{
$data['actions'] = $this->report->getUserYearActions($account, $year);
$efforts = $this->report->getUserYearEfforts($account, $year);
$data['efforts'] = $efforts->count;
$data['consumed'] = $efforts->consumed;
$projects = $this->report->getUserYearProjects($account, $year, $role);
$projectStat = $this->report->getStatByProjects($projects);
$tasks = $this->report->getUserYearFinishedTasks($account, $year);
$bugs = $this->report->getUserYearResolvedBugs($account, $year);
$data['finishedTaskPri'] = $tasks['pri'];
$data['resolvedBugPri'] = $bugs['pri'];
$data['effortMonth'] = $this->report->getEffort4Month($account, $year);;
$stories = $this->report->getFinishedStoryByProjects($projects, $year);
$tasks = $this->report->getFinishedTaskByProjects($projects, $account, $year);
$bugs = $this->report->getResolvedBugByProjects($projects, $account, $year);
foreach($projects as $projectID => $project)
{
$project->stories = zget($stories, $projectID, 0);
$project->tasks = zget($tasks, $projectID, 0);
$project->bugs = zget($bugs, $projectID, 0);
}
$data['projects'] = $projects;
$data['projectStat'] = $projectStat;
}
elseif($role == 'qa')
{
$data['actions'] = $this->report->getUserYearActions($account, $year);
$bugInfo = $this->report->getUserYearCreatedBugs($account, $year);
$data['foundBugs'] = $bugInfo['count'];
$data['bugPri'] = $bugInfo['pri'];
$data['bugMonth'] = $bugInfo['month'];
$caseInfo = $this->report->getUserYearCreatedCases($account, $year);
$data['createdCases'] = $caseInfo['count'];
$data['casePri'] = $caseInfo['pri'];
$data['caseMonth'] = $caseInfo['month'];
$projects = $this->report->getUserYearProjects($account, $year, $role);
$projectStat = $this->report->getStatByProjects($projects);
$bugs = $this->report->getCreatedBugByProjects($projects, $year);
foreach($projects as $projectID => $project) $project->bugs = zget($bugs, $projectID, 0);
$data['projects'] = $projects;
$data['projectStat'] = $projectStat;
}
$firstAction = $this->dao->select('*')->from(TABLE_ACTION)->orderBy('id')->limit(1)->fetch();
$firstYear = substr($firstAction->date, 0, 4);
$currentYear = date('Y');
$years = array();
for($thisYear = $firstYear; $thisYear <= $currentYear; $thisYear ++) $years[$thisYear] = $thisYear;
$this->view->title = sprintf($this->lang->report->annualData->title, $year, $this->app->user->realname);
$this->view->data = $data;
$this->view->role = $role;
$this->view->year = $year;
$this->view->years = $years;
die($this->display());
}
}
+2
View File
@@ -16,6 +16,8 @@ body {height: 100vh; padding: 0;}
#header > h1 {width: 500px; margin: 40px auto 0; height: 58px; font-weight: normal; text-align: center; font-size: 20px; display: block; line-height: 58px; position: relative; left: -30px;}
#toolbar {position: absolute; right: 33px; top: 80px; text-align: center;}
#toolbar #year{width:70px; display:inline-block; margin-right:5px; padding-top:2px; border-color: #1a77a5; background-color: transparent; color:#fff;}
#toolbar #year option{background: #141414;}
.exporting #toolbar {display: none;}
#toolbar .btn-primary {border-color: #1a77a5; background-color: transparent; padding: 6px 7px;}
#toolbar .btn-primary:hover,
+5
View File
@@ -194,4 +194,9 @@ $(function()
{
exportAnnualImage();
});
$('#toolbar #year').change(function()
{
location.href = createLink('report', 'annualData', 'year=' + $(this).val());
});
});
+46
View File
@@ -100,3 +100,49 @@ $lang->report->mailTitle->testTask = " 测试版本(%s),";
$lang->report->proVersion = '<a href="https://api.zentao.net/goto.php?item=proversion&from=reportpage" target="_blank">更多精彩,尽在专业版!</a>';
$lang->report->proVersionEn = '<a href="http://api.zentao.pm/goto.php?item=proversion&from=reportpage" target="_blank">Try ZenTao Pro for more!</a>';
$lang->report->annualData = new stdclass();
$lang->report->annualData->title = "%s年工作内容统计一览表 ——%s";
$lang->report->annualData->baseInfo = "基本数据信息";
$lang->report->annualData->logins = "累计登录次数";
$lang->report->annualData->actions = "累计动态数";
$lang->report->annualData->efforts = "累计日志数";
$lang->report->annualData->consumed = "累计工时数";
$lang->report->annualData->foundBugs = "累计发现Bug数";
$lang->report->annualData->createdCases = "累计创建用例数";
$lang->report->annualData->involvedProducts = "累计参与产品数";
$lang->report->annualData->createdPlans = "累计创建计划数";
$lang->report->annualData->createdStories = "累计创建需求数";
$lang->report->annualData->productOverview = "产品创建的需求数及占比";
$lang->report->annualData->projectOverview = "参与项目概览";
$lang->report->annualData->doneProject = "已完成的项目";
$lang->report->annualData->doingProject = "正在进行的项目";
$lang->report->annualData->suspendProject = "已挂起的项目";
$lang->report->annualData->projectName = '项目名称';
$lang->report->annualData->finishedStory = '完成需求数';
$lang->report->annualData->finishedTask = '完成任务数';
$lang->report->annualData->foundBug = '发现Bug数';
$lang->report->annualData->resolvedBug = '解决Bug数';
$lang->report->annualData->productName = '产品名称';
$lang->report->annualData->planCount = '计划数';
$lang->report->annualData->storyCount = '需求数';
$lang->report->annualData->qaData = "完成任务与解决Bug数据";
$lang->report->annualData->totalCreatedBug = '累计发现的Bug数';
$lang->report->annualData->totalCreatedCase = '累计创建的用例数';
$lang->report->annualData->devData = "完成的任务数和解决的Bug数";
$lang->report->annualData->totalFinishedTask = '完成的任务数';
$lang->report->annualData->totalResolvedBug = '解决的Bug数';
$lang->report->annualData->poData = "所创建的需求数对应的优先级及状态";
$lang->report->annualData->totalStoryPri = "创建需求优先级分布";
$lang->report->annualData->totalStoryStage = "创建需求阶段分布";
$lang->report->annualData->qaStatistics = "完成任务与解决bug工时统计";
$lang->report->annualData->poStatistics = "月创建需求数";
$lang->report->annualData->devStatistics = "月完成任务累计工时";
$lang->report->annualData->unit = "个";
+288
View File
@@ -503,6 +503,294 @@ class reportModel extends model
->andWhere("(t1.status='wait' OR t1.status='doing')")
->fetchGroup('user');
}
public function getUserYearLogins($account, $year)
{
return $this->dao->select('count(*) as count')->from(TABLE_ACTION)->where('actor')->eq($account)->andWhere('LEFT(date, 4)')->eq($year)->andWhere('action')->eq('login')->fetch('count');
}
public function getUserYearActions($account, $year)
{
return $this->dao->select('count(*) as count')->from(TABLE_ACTION)->where('actor')->eq($account)->andWhere('LEFT(date, 4)')->eq($year)->fetch('count');
}
public function getUserYearEfforts($account, $year)
{
return $this->dao->select('count(*) as count, sum(consumed) as consumed')->from(TABLE_TASKESTIMATE)->where('account')->eq($account)->andWhere('LEFT(date, 4)')->eq($year)->fetch();
}
public function getUserYearStory($account, $year)
{
$stories = $this->dao->select('*')->from(TABLE_STORY)->where('openedBy')->eq($account)->andWhere('LEFT(openedDate, 4)')->eq($year)->andWhere('deleted')->eq(0)->fetchAll();
$storyInfo = array();
$storyInfo['count'] = 0;
$storyInfo['pri'] = array();
$storyInfo['stage'] = array('wait' => 0, 'projected' => 0, 'developing' => 0, 'developed' => 0, 'released' => 0, 'closed' => 0);
$storyInfo['month'] = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
foreach($stories as $story)
{
$storyInfo['count'] ++;
if(!isset($storyInfo['pri'][$story->pri])) $storyInfo['pri'][$story->pri] = 0;
$storyInfo['pri'][$story->pri] ++;
if(isset($storyInfo['stage'][$story->stage])) $storyInfo['stage'][$story->stage] ++;
$month = (int)substr($story->openedDate, 5, 2) - 1;
$storyInfo['month'][$month] ++;
}
return $storyInfo;
}
public function getUserYearCreatedBugs($account, $year)
{
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where('openedBy')->eq($account)->andWhere('LEFT(openedDate, 4)')->eq($year)->andWhere('deleted')->eq(0)->fetchAll();
$bugInfo = array();
$bugInfo['count'] = 0;
$bugInfo['pri'] = array();
$bugInfo['month'] = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
foreach($bugs as $bug)
{
$bugInfo['count'] ++;
if(!isset($bugInfo['pri'][$bug->pri])) $bugInfo['pri'][$bug->pri] = 0;
$bugInfo['pri'][$bug->pri] ++;
$month = (int)substr($bug->openedDate, 5, 2) - 1;
$bugInfo['month'][$month] ++;
}
return $bugInfo;
}
public function getUserYearResolvedBugs($account, $year)
{
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where('resolvedBy')->eq($account)->andWhere('LEFT(resolvedDate, 4)')->eq($year)->andWhere('deleted')->eq(0)->fetchAll();
$bugInfo = array();
$bugInfo['count'] = 0;
$bugInfo['pri'] = array();
foreach($bugs as $bug)
{
$bugInfo['count'] ++;
if(!isset($bugInfo['pri'][$bug->pri])) $bugInfo['pri'][$bug->pri] = 0;
$bugInfo['pri'][$bug->pri] ++;
}
return $bugInfo;
}
public function getUserYearFinishedTasks($account, $year)
{
$tasks = $this->dao->select('*')->from(TABLE_TASK)->where('finishedBy')->eq($account)->andWhere('LEFT(finishedDate, 4)')->eq($year)->andWhere('deleted')->eq(0)->fetchAll();
$taskInfo = array();
$taskInfo['count'] = 0;
$taskInfo['pri'] = array();
foreach($tasks as $task)
{
$taskInfo['count'] ++;
if(!isset($taskInfo['pri'][$task->pri])) $taskInfo['pri'][$task->pri] = 0;
$taskInfo['pri'][$task->pri] ++;
}
return $taskInfo;
}
public function getUserYearCreatedCases($account, $year)
{
$cases = $this->dao->select('*')->from(TABLE_CASE)->where('openedBy')->eq($account)->andWhere('LEFT(openedDate, 4)')->eq($year)->andWhere('deleted')->eq(0)->fetchAll();
$caseInfo = array();
$caseInfo['count'] = 0;
$caseInfo['pri'] = array();
$caseInfo['month'] = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
foreach($cases as $case)
{
$caseInfo['count'] ++;
if(!isset($caseInfo['pri'][$case->pri])) $caseInfo['pri'][$case->pri] = 0;
$caseInfo['pri'][$case->pri] ++;
$month = (int)substr($case->openedDate, 5, 2) - 1;
$caseInfo['month'][$month] ++;
}
return $caseInfo;
}
public function getUserYearProducts($account, $year)
{
$products = $this->dao->select('id,name,status')->from(TABLE_PRODUCT)
->where('deleted')->eq(0)
->andWhere('LEFT(createdDate, 4)')->eq($year)
->andWhere('createdBy', true)->eq($account)
->orWhere('PO')->eq($account)
->orWhere('QD')->eq($account)
->orWhere('RD')->eq($account)
->markRight(1)
->fetchAll('id');
$storyProducts = $this->dao->select('DISTINCT product')->from(TABLE_STORY)->where('openedBy')->eq($account)->andWhere('LEFT(openedDate, 4)')->eq($year)->fetchPairs('product', 'product');
$planProducts = $this->dao->select('DISTINCT t1.product')->from(TABLE_PRODUCTPLAN)->alias('t1')
->leftJoin(TABLE_ACTION)->alias('t2')->on("t1.id=t2.objectID and t2.objectType='productplan'")
->where('t1.deleted')->eq(0)
->andWhere('LEFT(t2.date, 4)')->eq($year)
->andWhere('t2.action')->eq('opened')
->groupBy('t1.product')
->fetchPairs('product', 'product');
$products += $this->dao->select('id,name,status')->from(TABLE_PRODUCT)
->where('deleted')->eq(0)
->andWhere('id')->in($storyProducts + $planProducts)
->fetchAll('id');
return $products;
}
public function getPlansByProducts($products, $year)
{
return $this->dao->select('t1.product, count(DISTINCT t1.id) as plans')->from(TABLE_PRODUCTPLAN)->alias('t1')
->leftJoin(TABLE_ACTION)->alias('t2')->on("t1.id=t2.objectID and t2.objectType='productplan'")
->where('t1.deleted')->eq(0)
->andWhere('t1.product')->in(array_keys($products))
->andWhere('LEFT(t2.date, 4)')->eq($year)
->andWhere('t2.action')->eq('opened')
->groupBy('t1.product')
->fetchPairs('product', 'plans');
}
public function getStoriesByProducts($products, $year)
{
return $this->dao->select('product, count(*) as stories')->from(TABLE_STORY)
->where('deleted')->eq(0)
->andWhere('product')->in(array_keys($products))
->andWhere('LEFT(openedDate, 4)')->eq($year)
->groupBy('product')
->fetchPairs('product', 'stories');
}
public function getUserYearProjects($account, $year, $role = 'dev')
{
$projects = $this->dao->select('id,name,status')->from(TABLE_PROJECT)->where('deleted')->eq(0)
->andWhere('LEFT(begin, 4)', true)->eq($year)
->orWhere('LEFT(end, 4)')->le($year)
->markRight(1)
->andWhere('openedBy', true)->eq($account)
->orWhere('PO')->eq($account)
->orWhere('PM')->eq($account)
->orWhere('QD')->eq($account)
->orWhere('RD')->eq($account)
->markRight(1)
->fetchAll('id');
$teamProjects = $this->dao->select('*')->from(TABLE_TEAM)->where('type')->eq('project')->andWhere('account')->eq($account)->andWhere('LEFT(`join`, 4)')->eq($year)->fetchPairs('root', 'root');
$taskProjects = array();
if($role == 'dev') $taskProjects = $this->dao->select('project')->from(TABLE_TASK)->where('finishedBy')->eq($account)->andWhere('LEFT(finishedDate, 4)')->eq($year)->andWhere('deleted')->eq(0)->fetchPairs('project', 'project');
$projects += $this->dao->select('id,name,status')->from(TABLE_PROJECT)->where('deleted')->eq(0)
->andWhere('id')->in($teamProjects + $taskProjects)
->fetchAll('id');
return $projects;
}
public function getCreatedBugByProjects($projects, $year)
{
return $this->dao->select('project, count(*) as bugs')->from(TABLE_BUG)
->where('deleted')->eq(0)
->andWhere('project')->in(array_keys($projects))
->andWhere('LEFT(openedDate, 4)')->eq($year)
->groupBy('project')
->fetchPairs('project', 'bugs');
}
public function getFinishedStoryByProjects($projects, $year)
{
return $this->dao->select('t1.project, count(DISTINCT t1.story) as stories')->from(TABLE_PROJECTSTORY)->alias('t1')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id')
->where('t2.deleted')->eq(0)
->andWhere('t1.project')->in(array_keys($projects))
->andWhere('LEFT(t2.closedDate, 4)')->eq($year)
->groupBy('t1.project')
->fetchPairs('project', 'stories');
}
public function getFinishedTaskByProjects($projects, $account, $year)
{
return $this->dao->select('project, count(*) as tasks')->from(TABLE_TASK)
->where('deleted')->eq(0)
->andWhere('project')->in(array_keys($projects))
->andWhere('LEFT(finishedDate, 4)')->eq($year)
->andWhere('finishedBy')->eq($account)
->groupBy('project')
->fetchPairs('project', 'tasks');
}
public function getResolvedBugByProjects($projects, $account, $year)
{
return $this->dao->select('project, count(*) as bugs')->from(TABLE_BUG)
->where('deleted')->eq(0)
->andWhere('project')->in(array_keys($projects))
->andWhere('LEFT(resolvedDate, 4)')->eq($year)
->andWhere('resolvedBy')->eq($account)
->groupBy('project')
->fetchPairs('project', 'bugs');
}
public function getStatByProjects($projects)
{
$projectStat = array();
$projectStat['count'] = 0;
$projectStat['doing'] = 0;
$projectStat['done'] = 0;
$projectStat['suspended'] = 0;
foreach($projects as $project)
{
$projectStat['count']++;
if($project->status == 'closed' or $project->status == 'done') $projectStat['done']++;
if($project->status == 'wait' or $project->status == 'doing') $projectStat['doing']++;
if($project->status == 'suspended') $projectStat['suspended']++;
}
return $projectStat;
}
public function getStatByProducts($products, $account, $year)
{
$allStories = $this->dao->select('product, count(*) as count')->from(TABLE_STORY)->where('deleted')->eq(0)
->andWhere('product')->in(array_keys($products))
->andWhere('LEFT(openedDate, 4)')->eq($year)
->groupBy('product')
->fetchPairs('product', 'count');
$mineStories = $this->dao->select('product, count(*) as count')->from(TABLE_STORY)->where('deleted')->eq(0)
->andWhere('product')->in(array_keys($products))
->andWhere('openedBy')->eq($account)
->andWhere('LEFT(openedDate, 4)')->eq($year)
->groupBy('product')
->fetchPairs('product', 'count');
$productStat = array();
foreach($products as $productID => $product)
{
$productStat[$productID]['name'] = $product->name;
$productStat[$productID]['count'] = zget($allStories, $productID, 0);
$productStat[$productID]['mine'] = zget($mineStories, $productID, 0);
}
return $productStat;
}
public function getEffort4Month($account, $year)
{
$efforts = $this->dao->select('*')->from(TABLE_TASKESTIMATE)->where('account')->eq($account)
->andWhere('LEFT(date, 4)')->eq($year)
->orderBy('date')
->fetchAll();
$months = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
foreach($efforts as $effort)
{
$month = (int)substr($effort->date, 5, 2) - 1;
$months[$month] += $effort->consumed;
}
return $months;
}
}
/**
+145 -98
View File
@@ -68,6 +68,7 @@
<canvas id='block5Chart' width='520' height='240'></canvas>
</section>
<div id='toolbar'>
<?php echo html::select('year', $years, $year, "class='form-control'");?>
<button type='button' class='btn btn-primary' id='exportBtn'><i class='icon icon-export'></i></button>
<a id='imageDownloadBtn' class='hidden' download='annual_data.png'></a>
</div>
@@ -75,115 +76,161 @@
<div id='loadIndicator' class='load-indicator'></div>
</div>
<script>
// 年度数据示例
var annualData =
{
// 大标题
title: '2019年工作内容统计一览表 ── XXX',
title: '<?php echo $title;?>',
// 区块1
block1:
<?php foreach($config->report->annualData[$role] as $blockKey => $blockConfig):?>
<?php echo $blockKey;?>:
{
title: '基本数据信息',
data:
[
{title: '累计登录次数', value: 344},
{title: '累计动态数', value: 1543},
{title: '累计日志数', value: 629},
{title: '累计工时数', value: 772}
]
},
// 区块2
block2:
{
title: '参与项目概览',
data:
[
{title: '已完成的项目', value: 20, percent: '71.4%'},
{title: '正在进行的项目', value: 7, percent: '25%'},
{title: '已挂起的项目', value: 1, percent: '3.5%'}
],
unit: '个'
},
// 区块3
block3:
{
cols:
[
{title: '项目名称', width: 'auto', align: 'left'},
{title: '完成需求数', width: 80, align: 'center'},
{title: '完成任务数', width: 80, align: 'center'},
{title: '解决bug数', width: 72, align: 'center'}
],
rows:
[
['项目名称一', 22, 2, '0%'],
['项目名称二', 22, 2, '0%'],
['项目名称三', 22, 2, '0%'],
['项目名称四', 22, 2, '0%'],
['项目名称五', 22, 2, '0%'],
['项目名称六', 22, 2, '0%'],
['项目名称七', 22, 2, '0%'],
['项目名称八', 22, 2, '0%'],
['项目名称九', 22, 2, '0%'],
['项目名称十', 22, 2, '0%'],
['项目名称十一', 22, 2, '0%'],
['项目名称十二', 22, 2, '0%']
]
},
// 区块4
block4:
{
title: '完成任务与解决bug数据',
chart1:
<?php if(!empty($blockConfig['title'])):?>
title: '<?php echo $lang->report->annualData->{$blockConfig['title']};?>',
<?php endif;?>
<?php
$blockData = array();
if($blockKey == 'block1')
{
title: '累计完成任务数',
unit: '个',
data:
[
// legend 属性可选,如果留空,则不再下方的图例上显示标题
{value: 42, title: '优先级1', legend: 'P1'},
{value: 172, title: '优先级2', legend: 'P2'},
{value: 212, title: '优先级3', legend: 'P3'},
{value: 86, title: '优先级4', legend: 'P4'}
],
},
chart2:
{
title: '累计修复bug数',
unit: '个',
data:
[
{value: 42, title: '优先级1'},
{value: 32, title: '优先级2'},
{value: 20, title: '优先级3'},
{value: 34, title: '优先级4'}
],
foreach($blockConfig['data'] as $name) $blockData[] = array('title' => $lang->report->annualData->{$name}, 'value' => $data[$name]);
echo "data :" . json_encode($blockData);
}
},
block5:
{
title: '完成任务与解决bug工时统计',
labels: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
datasets:
[
elseif($blockKey == 'block2')
{
echo "unit: '" . $lang->report->annualData->unit . "',";
if($role == 'qa' or $role == 'dev')
{
label: '完成任务累计工时',
data: [110, 154, 184, 220, 212, 250, 130, 146, 201, 89, 140, 59],
},
{
label: '解决bug累计工时',
data: [10, 5, 11, 20, 30, 14, 3, 20, 50, 27, 13, 3],
$count = $data['projectStat']['count'];
$blockData[] = array('title' => $lang->report->annualData->doneProject, 'value' => $data['projectStat']['done'], 'percent' => (empty($count) ? 0 : round($data['projectStat']['done'] / $count, 4) * 100 . '%'));
$blockData[] = array('title' => $lang->report->annualData->doingProject, 'value' => $data['projectStat']['doing'], 'percent' => (empty($count) ? 0 : round($data['projectStat']['doing'] / $count, 4) * 100 . '%'));
$blockData[] = array('title' => $lang->report->annualData->suspendProject, 'value' => $data['projectStat']['suspended'], 'percent' => (empty($count) ? 0 : round($data['projectStat']['suspended'] / $count, 4) * 100 . '%'));
echo "data: " . json_encode($blockData);
}
]
elseif($role == 'po')
{
foreach($data['productStat'] as $productStat)
{
$count = $productStat['count'];
$blockData[] = array('title' => $productStat['name'], 'value' => (int)$productStat['mine'], 'percent' => (empty($count) ? '0' : round($productStat['mine'] / $count, 3) * 100 . '%'));
}
echo "data: " . json_encode($blockData);
}
}
elseif($blockKey == 'block3')
{
$cols = array();
$rows = array();
if($role == 'po')
{
$cols[] = array('title' => $lang->report->annualData->productName, 'width' => 'auto', 'align' => 'left');
$cols[] = array('title' => $lang->report->annualData->planCount, 'width' => '80', 'align' => 'center');
$cols[] = array('title' => $lang->report->annualData->storyCount, 'width' => '80', 'align' => 'center');
foreach($data['products'] as $product) $rows[] = array($product->name, $product->plans, $product->stories);
}
elseif($role == 'dev')
{
$cols[] = array('title' => $lang->report->annualData->projectName, 'width' => 'auto', 'align' => 'left');
$cols[] = array('title' => $lang->report->annualData->finishedStory, 'width' => '80', 'align' => 'center');
$cols[] = array('title' => $lang->report->annualData->finishedTask, 'width' => '80', 'align' => 'center');
$cols[] = array('title' => $lang->report->annualData->resolvedBug, 'width' => '80', 'align' => 'center');
foreach($data['projects'] as $project) $rows[] = array($project->name, $project->stories, $project->tasks, $project->bugs);
}
elseif($role == 'qa')
{
$cols[] = array('title' => $lang->report->annualData->projectName, 'width' => 'auto', 'align' => 'left');
$cols[] = array('title' => $lang->report->annualData->foundBug, 'width' => '80', 'align' => 'center');
foreach($data['projects'] as $project) $rows[] = array($project->name, $project->bugs);
}
echo "cols: " . json_encode($cols) . ',';
echo "rows: " . json_encode($rows);
}
elseif($blockKey == 'block4')
{
if($role == 'qa')
{
foreach($blockConfig['data'] as $i => $name)
{
$totalData = array();
foreach($data[$name] as $pri => $value) $totalData[] = array('title' => $pri, 'value' => $value, 'legend' => 'P' . $pri);
if($name == 'bugPri') $title = $lang->report->annualData->totalCreatedBug;
if($name == 'casePri') $title = $lang->report->annualData->totalCreatedCase;
$chart = array('title' => $title, 'unit' => $lang->report->annualData->unit, 'data' => $totalData);
echo "chart" . ($i + 1) . ': ' . json_encode($chart) . ',';
}
}
elseif($role == 'po')
{
$this->app->loadLang('story');
foreach($blockConfig['data'] as $i => $name)
{
$totalData = array();
foreach($data[$name] as $key => $value)
{
$totalData[] = array('title' => $key, 'value' => $value, 'legend' => ($name == 'storyPri' ? ('P' . $key) : $lang->story->stageList[$key]));
}
if($name == 'storyPri') $title = $lang->report->annualData->totalStoryPri;
if($name == 'storyStage') $title = $lang->report->annualData->totalStoryStage;
$chart = array('title' => $title, 'unit' => $lang->report->annualData->unit, 'data' => $totalData);
echo "chart" . ($i + 1) . ': ' . json_encode($chart) . ',';
}
}
elseif($role == 'dev')
{
foreach($blockConfig['data'] as $i => $name)
{
$totalData = array();
foreach($data[$name] as $key => $value) $totalData[] = array('title' => $key, 'value' => $value, 'legend' => 'P' . $key);
if($name == 'finishedTaskPri') $title = $lang->report->annualData->totalFinishedTask;
if($name == 'resolvedBugPri') $title = $lang->report->annualData->totalResolvedBug;
$chart = array('title' => $title, 'unit' => $lang->report->annualData->unit, 'data' => $totalData);
echo "chart" . ($i + 1) . ': ' . json_encode($chart) . ',';
}
}
}
elseif($blockKey == 'block5')
{
echo 'labels:' . json_encode($lang->datepicker->monthNames) . ',';
if($role == 'qa')
{
$datasets = array();
foreach($blockConfig['data'] as $i => $name)
{
if($name == 'bugMonth') $label = $lang->report->annualData->totalCreatedBug;
if($name == 'caseMonth') $label = $lang->report->annualData->totalCreatedCase;
$datasets[] = array('label' => $label, 'data' => $data[$name]);
}
}
elseif($role == 'po')
{
$datasets = array();
foreach($blockConfig['data'] as $i => $name)
{
if($name == 'storyMonth') $label = $lang->report->annualData->poStatistics;
$datasets[] = array('label' => $label, 'data' => $data[$name]);
}
}
elseif($role == 'dev')
{
$datasets = array();
foreach($blockConfig['data'] as $i => $name)
{
if($name == 'effortMonth') $label = $lang->report->annualData->devStatistics;
$datasets[] = array('label' => $label, 'data' => $data[$name]);
}
}
echo "datasets: " . json_encode($datasets);
}
?>
},
<?php endforeach;?>
};
// 显示年度数据
$(function()
{
showAnnualData(annualData);