一、创建BUG界面
1.在/opt/zbox/app/zentao/module/bug/ext/view路径下创建create.yyt.html.hook.php文件,在文件中增加要添加的字段代码:
<?php
$html = '<tr>';
$html .= '<th></th>';
$html .= '<th hidden>';
$html .= $lang->bug->probability;
$html .= '</th>';
$html .= '<td>';
$html .= '<div class="input-group">';
$html .= '<span class="input-group-addon" style="border-radius: 4px;">';
$html .= $lang->bug->probability;
$html .= '</span>';
$html .= '<select id="probability" name="probability" style="width: 100px" autocomplete="off" class="form-control" >';
$html .= '<option>必现</option>';
$html .= '<option>高概率</option>';
$html .= '<option>低概率</option>';
$html .= '<option>极低概率</option>';
$html .= '</select>';
$html .= '<span class="input-group-addon step-type-toggle">';
$html .= '<div class="checkbox-primary">';
$html .= '<input value="否" name="iscasefind" id="iscasefind" type="checkbox" class="step-group-toggle">';
$html .= '<label class="checkbox-inline">';
$html .= $lang->bug->iscasefind;
$html .= '</label>';
$html .= '</div>';
$html .= '</span>';
$html .= '<span class="input-group-addon" style="border-radius: 4px;">';
$html .= $lang->bug->caseno;
$html .= '</span>';
$html .= '<span class="input-control has-icon-right">';
$html .= '<input type="text" value style="width: 210px" name="caseno" id="caseno" autocomplete="off" class="form-control" ;">';
$html .= '</span>';
$html .= '</div>';
$html .= '<div style="visibility:hidden;color: #ff5d5d" id="casenoerror">『用例编号』不能为空</div>';
$html .= '</td>';
$html .= '</div>';
$html .= '</tr>';
?>
<script>
$('#severity').closest('tr').after(<?php echo json_encode($html);?>);
</script>
<script>
document.getElementById('submit').onclick=function check(){
var iscasefind = document.getElementById('iscasefind').checked;
if (iscasefind==true){
document.getElementById('iscasefind').value='是';
}else{
document.getElementById('iscasefind').value='否';
}
if(document.getElementById('iscasefind').value == '是'){
var no = document.getElementById('caseno').value;
if (no==''){
document.getElementById('casenoerror').style.visibility="visible";
return false;
}else{
document.getElementById('casenoerror').style.visibility="hidden";
}
}
}
</script>
2.在/opt/zbox/app/zentao/module/bug/ext/lang/zh-cn路径创建create.php文件,里面设置增加的界面需要访问的属性的值
<?php
$lang->bug->probability = '出现概率';
$lang->bug->iscasefind = '用例发现';
$lang->bug->caseno = '用例编号';
二、在model文件的create方法中增加iscasefind字段的默认值
三、在数据库中给表增加字段
alter table zt_bug add column `probability` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
alter table zt_bug add column `iscasefind` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
alter table zt_bug add column `caseno` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
四、要在BUG浏览界面能够自定义展示新增的字段
1.在/opt/zbox/app/zentao/module/bug/ext/config路径下创建bug模块config.php文件的扩展文件create.php
<?php
$config->bug->datatable->fieldList['probability']['title'] = 'probability';
$config->bug->datatable->fieldList['probability']['fixed'] = 'left';
$config->bug->datatable->fieldList['probability']['width'] = '100';
$config->bug->datatable->fieldList['probability']['required'] = 'no';
$config->bug->datatable->fieldList['iscasefind']['title'] = 'iscasefind';
$config->bug->datatable->fieldList['iscasefind']['fixed'] = 'right';
$config->bug->datatable->fieldList['iscasefind']['width'] = '100';
$config->bug->datatable->fieldList['iscasefind']['required'] = 'no';
$config->bug->datatable->fieldList['caseno']['title'] = 'caseno';
$config->bug->datatable->fieldList['caseno']['fixed'] = 'right';
$config->bug->datatable->fieldList['caseno']['width'] = '100';
$config->bug->datatable->fieldList['caseno']['required'] = 'no';
2.在/opt/zbox/app/zentao/module/bug/ext/model路径下增加model的扩展printCell.php
<?php
public function printCell($col, $bug, $users, $builds, $branches, $modulePairs, $executions = array(), $plans = array(), $stories = array(), $tasks = array(), $mode = 'datatable')
{
$canBeChanged = common::canBeChanged('bug', $bug);
$canBatchEdit = ($canBeChanged and common::hasPriv('bug', 'batchEdit'));
$canBatchConfirm = ($canBeChanged and common::hasPriv('bug', 'batchConfirm'));
$canBatchClose = common::hasPriv('bug', 'batchClose');
$canBatchActivate = ($canBeChanged and common::hasPriv('bug', 'batchActivate'));
$canBatchChangeBranch = ($canBeChanged and common::hasPriv('bug', 'batchChangeBranch'));
$canBatchChangeModule = ($canBeChanged and common::hasPriv('bug', 'batchChangeModule'));
$canBatchResolve = ($canBeChanged and common::hasPriv('bug', 'batchResolve'));
$canBatchAssignTo = ($canBeChanged and common::hasPriv('bug', 'batchAssignTo'));
$canBatchAction = ($canBatchEdit or $canBatchConfirm or $canBatchClose or $canBatchActivate or $canBatchChangeBranch or $canBatchChangeModule or $canBatchResolve or $canBatchAssignTo);
$canView = common::hasPriv('bug', 'view');
$hasCustomSeverity = false;
foreach($this->lang->bug->severityList as $severityKey => $severityValue)
{
if(!empty($severityKey) and (string)$severityKey != (string)$severityValue)
{
$hasCustomSeverity = true;
break;
}
}
$bugLink = helper::createLink('bug', 'view', "bugID=$bug->id");
$account = $this->app->user->account;
$id = $col->id;
if($col->show)
{
$class = "c-$id";
$title = '';
if($id == 'id') $class .= ' cell-id';
if($id == 'status')
{
$class .= ' bug-' . $bug->status;
$title = "title='" . $this->processStatus('bug', $bug) . "'";
}
if($id == 'confirmed')
{
$class .= ' text-center';
}
if ($id == 'probability')
{
$class .=' text-left';
}
if ($id == 'iscasefind')
{
$class .=' text-left';
}
if($id == 'title')
{
$class .= ' text-left';
$title = "title='{$bug->title}'";
}
if($id == 'type')
{
$title = "title='" . zget($this->lang->bug->typeList, $bug->type) . "'";
}
if($id == 'assignedTo')
{
$class .= ' has-btn text-left';
if($bug->assignedTo == $account) $class .= ' red';
}
if($id == 'resolvedBy')
{
$class .= ' c-user';
$title = "title='" . zget($users, $bug->resolvedBy) . "'";
}
if($id == 'deadline' && isset($bug->delay) && $bug->status == 'active') $class .= ' delayed';
if(strpos(',type,execution,story,plan,task,openedBuild,', ",{$id},") !== false) $class .= ' text-ellipsis';
echo "<td class='" . $class . "' $title>";
if(isset($this->config->bizVersion)) $this->loadModel('flow')->printFlowCell('bug', $bug, $id);
switch($id)
{
case 'id':
if($canBatchAction)
{
echo html::checkbox('bugIDList', array($bug->id => '')) . html::a(helper::createLink('bug', 'view', "bugID=$bug->id"), sprintf('%03d', $bug->id));
}
else
{
printf('%03d', $bug->id);
}
break;
case 'severity':
$severityValue = zget($this->lang->bug->severityList, $bug->severity);
$hasCustomSeverity = !is_numeric($severityValue);
if($hasCustomSeverity)
{
echo "<span class='label-severity-custom' data-severity='{$bug->severity}' title='" . $severityValue . "'>" . $severityValue . "</span>";
}
else
{
echo "<span class='label-severity' data-severity='{$bug->severity}' title='" . $severityValue . "'></span>";
}
break;
case 'pri':
echo "<span class='label-pri label-pri-" . $bug->pri . "' title='" . zget($this->lang->bug->priList, $bug->pri, $bug->pri) . "'>";
echo zget($this->lang->bug->priList, $bug->pri, $bug->pri);
echo "</span>";
break;
case 'confirmed':
$class = 'confirm' . $bug->confirmed;
echo "<span class='$class'>" . zget($this->lang->bug->confirmedList, $bug->confirmed, $bug->confirmed) . "</span> ";
break;
case 'title':
if($bug->branch and isset($branches[$bug->branch])) echo "<span class='label label-outline label-badge'>{$branches[$bug->branch]}</span> ";
if($bug->module and isset($modulePairs[$bug->module])) echo "<span class='label label-gray label-badge'>{$modulePairs[$bug->module]}</span> ";
echo $canView ? html::a($bugLink, $bug->title, null, "style='color: $bug->color'") : "<span style='color: $bug->color'>{$bug->title}</span>";
break;
case 'branch':
echo zget($branches, $bug->branch, '');
break;
case 'execution':
echo zget($executions, $bug->execution, '');
break;
case 'plan':
echo zget($plans, $bug->plan, '');
break;
case 'story':
if(isset($stories[$bug->story]))
{
$story = $stories[$bug->story];
echo common::hasPriv('story', 'view') ? html::a(helper::createLink('story', 'view', "storyID=$story->id", 'html', true), $story->title, '', "class='iframe'") : $story->title;
}
break;
case 'task':
if(isset($tasks[$bug->task]))
{
$task = $tasks[$bug->task];
echo common::hasPriv('task', 'view') ? html::a(helper::createLink('task', 'view', "taskID=$task->id", 'html', true), $task->name, '', "class='iframe'") : $task->name;
}
break;
case 'toTask':
if(isset($tasks[$bug->toTask]))
{
$task = $tasks[$bug->toTask];
echo common::hasPriv('task', 'view') ? html::a(helper::createLink('task', 'view', "taskID=$task->id", 'html', true), $task->name, '', "class='iframe'") : $task->name;
}
break;
case 'type':
echo zget($this->lang->bug->typeList, $bug->type);
break;
case 'status':
echo "<span class='status-bug status-{$bug->status}'>";
echo $this->processStatus('bug', $bug);
echo '</span>';
break;
case 'activatedCount':
echo $bug->activatedCount;
break;
case 'activatedDate':
echo substr($bug->activatedDate, 5, 11);
break;
case 'keywords':
echo $bug->keywords;
break;
case 'os':
echo zget($this->lang->bug->osList, $bug->os);
break;
case 'browser':
echo zget($this->lang->bug->browserList, $bug->browser);
break;
case 'mailto':
$mailto = explode(',', $bug->mailto);
foreach($mailto as $account)
{
$account = trim($account);
if(empty($account)) continue;
echo zget($users, $account) . " ";
}
break;
case 'found':
echo zget($users, $bug->found);
break;
case 'openedBy':
echo zget($users, $bug->openedBy);
break;
case 'openedDate':
echo substr($bug->openedDate, 5, 11);
break;
case 'openedBuild':
$builds = array_flip($builds);
foreach(explode(',', $bug->openedBuild) as $build)
{
$buildID = zget($builds, $build, '');
if($buildID == 'trunk')
{
echo $build;
}
elseif($buildID and common::hasPriv('build', 'view'))
{
echo html::a(helper::createLink('build', 'view', "buildID=$buildID"), $build, '', "title='$bug->openedBuild'");
}
}
break;
case 'assignedTo':
$this->printAssignedHtml($bug, $users);
break;
case 'assignedDate':
echo substr($bug->assignedDate, 5, 11);
break;
case 'deadline':
echo $bug->deadline;
break;
case 'iscasefind':
echo $bug->iscasefind;
break;
case 'probability':
echo $bug->probability;
break;
case 'caseno':
echo $bug->caseno;
break;
case 'resolvedBy':
echo zget($users, $bug->resolvedBy, $bug->resolvedBy);
break;
case 'resolution':
echo zget($this->lang->bug->resolutionList, $bug->resolution);
break;
case 'resolvedDate':
echo substr($bug->resolvedDate, 5, 11);
break;
case 'resolvedBuild':
echo $bug->resolvedBuild;
break;
case 'closedBy':
echo zget($users, $bug->closedBy);
break;
case 'closedDate':
echo substr($bug->closedDate, 5, 11);
break;
case 'lastEditedBy':
echo zget($users, $bug->lastEditedBy);
break;
case 'lastEditedDate':
echo substr($bug->lastEditedDate, 5, 11);
break;
case 'actions':
$params = "bugID=$bug->id";
if($canBeChanged)
{
common::printIcon('bug', 'confirmBug', $params, $bug, 'list', 'ok', '', 'iframe', true);
common::printIcon('bug', 'resolve', $params, $bug, 'list', 'checked', '', 'iframe', true);
common::printIcon('bug', 'close', $params, $bug, 'list', '', '', 'iframe', true);
common::printIcon('bug', 'edit', $params, $bug, 'list');
common::printIcon('bug', 'create', "product=$bug->product&branch=$bug->branch&extra=$params", $bug, 'list', 'copy');
}
else
{
common::printIcon('bug', 'close', $params, $bug, 'list', '', '', 'iframe', true);
}
break;
}
echo '</td>';
}
}
?>
五、在BUG详情界面展示新增的字段
1.在/opt/zbox/app/zentao/module/bug/ext/view路径下创建view的扩展view.yyt.html.hook.php
<?php
$html = '<tr>';
$html .= '<th>';
$html .= $lang->bug->probability;
$html .= '</th>';
$html .= '<td>';
$html .= $bug->probability;
$html .= '</td>';
$html .= '</tr>';
$html .= '<tr>';
$html .= '<th>';
$html .= $lang->bug->iscasefind;
$html .= '</th>';
$html .= '<td>';
$html .= $bug->iscasefind;
$html .= '</td>';
$html .= '</tr>';
$html .= '<tr>';
$html .= '<th>';
$html .= $lang->bug->caseno;
$html .= '</th>';
$html .= '<td>';
$html .= $bug->caseno;
$html .= '</td>';
$html .= '</tr>';
?>
<script>
$('span.label-pri').closest('tr').after(<?php echo json_encode($html);?>);
</script>
六、BUG修改界面添加对应字段
1、在module\bug\ext\view目录下新增edit.html的扩展文件
<?php
$html = '<tr>';
$html .= '<th>';
$html .= $lang->bug->probability;
$html .= '</th>';
$html .= '<td>';
$html .= '<select id="probability" name="probability" class="form-control chosen chosen-controled" style="display: none;" >';
$html .= '<option id="probability1" value="必现">必现</option>';
$html .= '<option id="probability2" value="高概率">高概率</option>';
$html .= '<option id="probability3" value="低概率">低概率</option>';
$html .= '<option id="probability4" value="极低概率">极低概率</option>';
$html .= '</select>';
$html .= '</td>';
$html .= '</tr>';
$html .= '<tr>';
$html .= '<th>';
$html .= $lang->bug->iscasefind;
$html .= '</th>';
$html .= '<td>';
$html .= '<select id="iscasefind" name="iscasefind" class="form-control chosen chosen-controled" style="display: none;" >';
$html .= '<option id="iscasefind1" value="是">是</option>';
$html .= '<option id="iscasefind2" value="否">否</option>';
$html .= '</select>';
$html .= '</td>';
$html .= '</tr>';
$html .= '<tr>';
$html .= '<th>';
$html .= $lang->bug->caseno;
$html .= '</th>';
$html .= '<td>';
$html .= '<input type="text" id="caseno" name="caseno" value class="form-control" autocomplete="off">';
$html .= '</input>';
$html .= '</td>';
$html .= '</tr>';
$selectedProbability = $bug->probability;
$selectedIscasefind = $bug->iscasefind;
$defCaseno = $bug->caseno;
?>
<script>
$('#pri').closest('tr').after(<?php echo json_encode($html);?>);
</script>
<script>
str = <?php echo json_encode($selectedIscasefind);?>;
obj = document.getElementById("probability");
for(i=0;i<obj.length;i++){
if(obj[i].value==str)
obj[i].selected = true;
}
</script>
<script>
str = <?php echo json_encode($selectediscasefind);?>;
obj = document.getElementById("iscasefind");
for(i=0;i<obj.length;i++){
if(obj[i].value==str)
obj[i].selected = true;
}
</script>
<script>
document.getElementById("caseno").value=<?php echo json_encode($defCaseno);?>;
</script>