diff --git a/module/bug/lang/zh-cn.php b/module/bug/lang/zh-cn.php index 64926625b7..7c979512fe 100644 --- a/module/bug/lang/zh-cn.php +++ b/module/bug/lang/zh-cn.php @@ -284,6 +284,7 @@ $lang->bug->report->bugsPerResolution = new stdclass(); $lang->bug->report->bugsPerStatus = new stdclass(); $lang->bug->report->bugsPerActivatedCount = new stdclass(); $lang->bug->report->bugsPerType = new stdclass(); +$lang->bug->report->bugsPerPri = new stdclass(); $lang->bug->report->bugsPerAssignedTo = new stdclass(); $lang->bug->report->bugLiveDays = new stdclass(); $lang->bug->report->bugHistories = new stdclass(); @@ -302,6 +303,7 @@ $lang->bug->report->bugsPerResolution->graph = new stdclass(); $lang->bug->report->bugsPerStatus->graph = new stdclass(); $lang->bug->report->bugsPerActivatedCount->graph = new stdclass(); $lang->bug->report->bugsPerType->graph = new stdclass(); +$lang->bug->report->bugsPerPri->graph = new stdclass(); $lang->bug->report->bugsPerAssignedTo->graph = new stdclass(); $lang->bug->report->bugLiveDays->graph = new stdclass(); $lang->bug->report->bugHistories->graph = new stdclass(); @@ -327,6 +329,7 @@ $lang->bug->report->bugsPerSeverity->graph->xAxisName = '严重程度'; $lang->bug->report->bugsPerResolution->graph->xAxisName = '解决方案'; $lang->bug->report->bugsPerStatus->graph->xAxisName = '状态'; $lang->bug->report->bugsPerActivatedCount->graph->xAxisName = '激活次数'; +$lang->bug->report->bugsPerPri->graph->xAxisName = '优先级'; $lang->bug->report->bugsPerType->graph->xAxisName = '类型'; $lang->bug->report->bugsPerAssignedTo->graph->xAxisName = '指派给'; $lang->bug->report->bugLiveDays->graph->xAxisName = '处理时间'; diff --git a/module/bug/model.php b/module/bug/model.php index d89f4abc79..f087bdee56 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -1632,7 +1632,7 @@ class bugModel extends model { $datas = $this->dao->select('pri AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name'); if(!$datas) return array(); - foreach($datas as $status => $data) if(isset($this->lang->bug->statusList[$status])) $data->name = $this->lang->bug->statusList[$status]; + foreach($datas as $status => $data) $data->name = $this->lang->bug->report->bugsPerPri->graph->xAxisName . ':' . $data->name; return $datas; } diff --git a/module/product/control.php b/module/product/control.php index abfbb21ac9..716696efdb 100644 --- a/module/product/control.php +++ b/module/product/control.php @@ -201,6 +201,7 @@ class product extends control $this->view->storyBugs = $storyBugs; $this->view->storyCases = $storyCases; $this->view->param = $param; + $this->view->products = $this->products; $this->display(); } @@ -573,9 +574,22 @@ class product extends control */ public function ajaxGetMatchedItems($keywords, $module, $method, $extra) { - $products = $this->dao->select('*')->from(TABLE_PRODUCT)->where('deleted')->eq(0)->andWhere('name')->like("%$keywords%")->orderBy('`order` desc')->fetchAll(); + $products = $this->dao->select('*')->from(TABLE_PRODUCT)->where('deleted')->eq(0)->orderBy('`order` desc')->fetchAll(); + $toPinyin = $this->product->toPinyin($products); + + foreach($toPinyin as $key => $value) { + if(!strstr($value ,$keywords) && !strstr($key,$keywords)) { + unset($toPinyin[$key]); + } + } + foreach($products as $key => $product) { + if(!isset($toPinyin[$product->name])) { + unset($products[$key]); + continue; + } + if(!$this->product->checkPriv($product)) unset($products[$key]); } diff --git a/module/product/model.php b/module/product/model.php index 6916f224c8..a63cf8244c 100644 --- a/module/product/model.php +++ b/module/product/model.php @@ -900,4 +900,52 @@ class productModel extends model ->limit(1) ->fetch(); } + + public function toPinyin($products) + { + global $app; + static $pinyin; + static $dataKeys; + if(empty($pinyin)) $pinyin = $app->loadClass('pinyin'); + + $joinOptions = ''; + $sign = ' aNd '; + foreach($products as $value) + { + if(!isset($dataKeys[$value->name])) $joinOptions .= str_replace($sign, ' and ', $value->name) . $sign; + } + + if($joinOptions) + { + $valuesPinyin = $pinyin->romanize($joinOptions); + $signLenth = strlen($sign); + $pinyinSign = trim($sign); + $pySignLenth = strlen($pinyinSign); + while($joinOptions) + { + $valuePinyin = ''; + $value = ''; + + $pinyinPos = strpos($valuesPinyin, $pinyinSign); + if($pinyinPos !== false) + { + $valuePinyin = substr($valuesPinyin, 0, $pinyinPos); + $valuesPinyin = substr($valuesPinyin, $pinyinPos + $pySignLenth); + } + + $valuePos = strpos($joinOptions, $sign); + if($valuePos === false) break; + $value = substr($joinOptions, 0, $valuePos); + $joinOptions = substr($joinOptions, $valuePos + $signLenth); + + $valuePinyin = preg_split('/[^a-z]+/iu', trim($valuePinyin)); + $valueAbbr = ''; + foreach($valuePinyin as $wordPinyin) if($wordPinyin) $valueAbbr .= $wordPinyin[0]; + + $dataKeys[$value] = empty($valuePinyin) ? '' : join($valuePinyin) . ' ' . $valueAbbr; + } + } + + return $dataKeys; + } } diff --git a/module/project/control.php b/module/project/control.php index a88f0f50cb..a35f88cafd 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -1896,9 +1896,22 @@ class project extends control */ public function ajaxGetMatchedItems($keywords, $module, $method, $extra) { - $projects = $this->dao->select('*')->from(TABLE_PROJECT)->where('deleted')->eq(0)->andWhere('name')->like("%$keywords%")->orderBy('order desc')->fetchAll(); + $projects = $this->dao->select('*')->from(TABLE_PROJECT)->where('deleted')->eq(0)->orderBy('order desc')->fetchAll(); + $toPinyin = $this->project->toPinyin($projects); + + foreach($toPinyin as $key => $value) { + if(!strstr($value ,$keywords) && !strstr($key,$keywords)) { + unset($toPinyin[$key]); + } + } + foreach($projects as $key => $project) { + if(!isset($toPinyin[$project->name])) { + unset($projects[$key]); + continue; + } + if(!$this->project->checkPriv($project)) unset($projects[$key]); } diff --git a/module/project/model.php b/module/project/model.php index 2a52400245..40aa7703e4 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -2389,4 +2389,52 @@ class projectModel extends model if(isset($fullTrees[0]) and empty($fullTrees[0]->children)) array_shift($fullTrees); return array_values($fullTrees); } + + public function toPinyin($products) + { + global $app; + static $pinyin; + static $dataKeys; + if(empty($pinyin)) $pinyin = $app->loadClass('pinyin'); + + $joinOptions = ''; + $sign = ' aNd '; + foreach($products as $value) + { + if(!isset($dataKeys[$value->name])) $joinOptions .= str_replace($sign, ' and ', $value->name) . $sign; + } + + if($joinOptions) + { + $valuesPinyin = $pinyin->romanize($joinOptions); + $signLenth = strlen($sign); + $pinyinSign = trim($sign); + $pySignLenth = strlen($pinyinSign); + while($joinOptions) + { + $valuePinyin = ''; + $value = ''; + + $pinyinPos = strpos($valuesPinyin, $pinyinSign); + if($pinyinPos !== false) + { + $valuePinyin = substr($valuesPinyin, 0, $pinyinPos); + $valuesPinyin = substr($valuesPinyin, $pinyinPos + $pySignLenth); + } + + $valuePos = strpos($joinOptions, $sign); + if($valuePos === false) break; + $value = substr($joinOptions, 0, $valuePos); + $joinOptions = substr($joinOptions, $valuePos + $signLenth); + + $valuePinyin = preg_split('/[^a-z]+/iu', trim($valuePinyin)); + $valueAbbr = ''; + foreach($valuePinyin as $wordPinyin) if($wordPinyin) $valueAbbr .= $wordPinyin[0]; + + $dataKeys[$value] = empty($valuePinyin) ? '' : join($valuePinyin) . ' ' . $valueAbbr; + } + } + + return $dataKeys; + } } diff --git a/module/testcase/control.php b/module/testcase/control.php index e5fc58592a..42cb6cce05 100644 --- a/module/testcase/control.php +++ b/module/testcase/control.php @@ -186,6 +186,47 @@ class testcase extends control $this->display(); } + /** + * The report page. + * + * @param int $productID + * @param string $browseType + * @param int $branchID + * @param int $moduleID + * @access public + * @return void + */ + public function report($productID, $browseType, $branchID, $moduleID) + { + $this->loadModel('report'); + $this->view->charts = array(); + + if(!empty($_POST)) + { + foreach($this->post->charts as $chart) + { + $chartFunc = 'getDataOf' . $chart; + $chartData = $this->testcase->$chartFunc(); + $chartOption = $this->lang->testcase->report->$chart; + $this->testcase->mergeChartOption($chart); + + $this->view->charts[$chart] = $chartOption; + $this->view->datas[$chart] = $this->report->computePercent($chartData); + } + } + + $this->testcase->setMenu($this->products, $productID, $branchID); + $this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->common . $this->lang->colon . $this->lang->testcase->reportChart; + $this->view->position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->testcase->reportChart; + $this->view->productID = $productID; + $this->view->browseType = $browseType; + $this->view->moduleID = $moduleID; + $this->view->checkedCharts = $this->post->charts ? join(',', $this->post->charts) : ''; + + $this->display(); + } + /** * Create a test case. * diff --git a/module/testcase/lang/zh-cn.php b/module/testcase/lang/zh-cn.php index ef6db81af1..cb8539166b 100644 --- a/module/testcase/lang/zh-cn.php +++ b/module/testcase/lang/zh-cn.php @@ -76,6 +76,7 @@ $lang->testcase->import = "导入"; $lang->testcase->showImport = "显示导入内容"; $lang->testcase->exportTemplet = "导出模板"; $lang->testcase->export = "导出数据"; +$lang->testcase->reportChart = '报表统计'; $lang->testcase->confirmChange = '确认用例变动'; $lang->testcase->confirmStoryChange = '确认需求变动'; $lang->testcase->copy = '复制用例'; @@ -161,3 +162,28 @@ $lang->testcase->featureBar['browse']['group'] = '分组查看'; $lang->testcase->featureBar['browse']['zerocase'] = '零用例需求'; $lang->testcase->featureBar['browse']['suite'] = '套件'; $lang->testcase->featureBar['groupcase'] = $lang->testcase->featureBar['browse']; + +/* 统计报表。*/ +$lang->testcase->report = new stdclass(); +$lang->testcase->report->common = '报表'; +$lang->testcase->report->select = '请选择报表类型'; +$lang->testcase->report->create = '生成报表'; + +$lang->testcase->report->charts['testCasePerRunResult'] = '测试用例结果统计'; +$lang->testcase->report->charts['testCasePerStatus'] = '测试用例状态统计'; +$lang->testcase->report->charts['testCasePerType'] = '测试用例类型统计'; + +$lang->testcase->report->options = new stdclass(); +$lang->testcase->report->options->graph = new stdclass(); +$lang->testcase->report->options->type = 'pie'; +$lang->testcase->report->options->width = 500; +$lang->testcase->report->options->height = 140; + +$lang->testcase->report->testCasePerRunResult = new stdclass(); +$lang->testcase->report->testCasePerStatus = new stdclass(); +$lang->testcase->report->testCasePerType = new stdclass(); + +$lang->testcase->report->testCasePerRunResult->graph = new stdclass(); +$lang->testcase->report->testCasePerStatus->graph = new stdclass(); +$lang->testcase->report->testCasePerType->graph = new stdclass(); + diff --git a/module/testcase/model.php b/module/testcase/model.php index 5ef93d7cec..6e4103d1f1 100644 --- a/module/testcase/model.php +++ b/module/testcase/model.php @@ -1164,4 +1164,83 @@ class testcaseModel extends model return $cases; } + + /** + * Get report data of testcase per run result. + * + * @access public + * @return array + */ + public function getDataOfTestCasePerRunResult() + { + $datas = $this->dao->select('lastRunResult AS name, COUNT(*) AS value')->from(TABLE_CASE)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + foreach($datas as $result => $data) if(isset($this->lang->testcase->resultList[$result])) $data->name = $this->lang->testcase->resultList[$result]; + return $datas; + } + + /** + * Get report data of testcase per status. + * + * @access public + * @return array + */ + public function getDataOfTestCasePerStatus() + { + $datas = $this->dao->select('status AS name, COUNT(*) AS value')->from(TABLE_CASE)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + foreach($datas as $result => $data) if(isset($this->lang->testcase->statusList[$result])) $data->name = $this->lang->testcase->statusList[$result]; + return $datas; + } + + /** + * Get report data of testcase per Type. + * + * @access public + * @return array + */ + public function getDataOfTestCasePerType() + { + $datas = $this->dao->select('type AS name, COUNT(*) AS value')->from(TABLE_CASE)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + foreach($datas as $result => $data) if(isset($this->lang->testcase->typeList[$result])) $data->name = $this->lang->testcase->typeList[$result]; + return $datas; + } + + /** + * Get report condition from session. + * + * @access public + * @return void + */ + public function reportCondition() + { + if(isset($_SESSION['testcaseQueryCondition'])) + { + if(!$this->session->testcaseOnlyCondition) return 'id in (' . preg_replace('/SELECT .* FROM/', 'SELECT t1.id FROM', $this->session->testcaseQueryCondition) . ')'; + return $this->session->testcaseQueryCondition; + } + return true; + } + + /** + * Merge the default chart settings and the settings of current chart. + * + * @param string $chartType + * @access public + * @return void + */ + public function mergeChartOption($chartType) + { + $chartOption = $this->lang->testcase->report->$chartType; + $commonOption = $this->lang->testcase->report->options; + + $chartOption->graph->caption = $this->lang->testcase->report->charts[$chartType]; + if(!isset($chartOption->type)) $chartOption->type = $commonOption->type; + if(!isset($chartOption->width)) $chartOption->width = $commonOption->width; + if(!isset($chartOption->height)) $chartOption->height = $commonOption->height; + + /* 合并配置。*/ + foreach($commonOption->graph as $key => $value) if(!isset($chartOption->graph->$key)) $chartOption->graph->$key = $value; + } } diff --git a/module/testcase/view/caseheader.html.php b/module/testcase/view/caseheader.html.php index e56d5587a3..ccbc52523a 100644 --- a/module/testcase/view/caseheader.html.php +++ b/module/testcase/view/caseheader.html.php @@ -94,6 +94,7 @@ +