diff --git a/Dockerfile.test b/Dockerfile.test index 03cef88a60..fe9f782e05 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -1,4 +1,4 @@ -FROM hub.qucheng.com/ci/zentao-ztf:php8-2023050806 +FROM hub.qucheng.com/ci/zentao-ztf:php8-2023050810 # Install zentao ARG VERSION @@ -13,3 +13,5 @@ ENV MYSQL_PASSWORD=${MYSQL_PASSWORD} SHELL ["/bin/bash", "-c"] # Copy ZenTao COPY --chown=33:33 . /apps/zentao/ + +RUN INIT_PHPINI_ONLY=true /etc/s6/s6-init/run diff --git a/Jenkinsfile b/Jenkinsfile index 4a98a87a2f..c9d074c160 100755 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -96,7 +96,7 @@ pipeline { steps { container('zentao') { - sh 'cat /usr/bin/initdb.php; initdb.php ; /apps/zentao/test/ztest init' + sh '/etc/s6/s6-init/run ; php --ini ; cat /usr/bin/initdb.php; initdb.php ; /apps/zentao/test/ztest init' } } post { @@ -138,7 +138,7 @@ pipeline { stage('Run') { steps { container('zentao') { - sh 'initdb.php config' + sh '/etc/s6/s6-init/run ; php --ini ; initdb.php config' sh '/apps/zentao/test/ztest extract ; /apps/zentao/test/ztest ${SEQUENCE} | tee /apps/zentao/test/${SEQUENCE}.log' sh 'ls /apps/zentao/www ; cat /apps/zentao/www/coverage.php' sh 'pipeline-unittest.sh /apps/zentao/test/${SEQUENCE}.log' diff --git a/lib/zin/wg/history/css/v1.css b/lib/zin/wg/history/css/v1.css index 38a6ccf1fe..fd3640341f 100644 --- a/lib/zin/wg/history/css/v1.css +++ b/lib/zin/wg/history/css/v1.css @@ -6,6 +6,12 @@ font-size: 14px; font-weight: 700; line-height: 20px; + display: flex; + align-items: center; +} + +.histories { + background: #FCFDFE; } .histories .btn-mini { @@ -22,7 +28,8 @@ .histories .btn { background-color: #fff; - display: inline-block; + display: inline-flex; + align-items: center; margin-bottom: 0; font-weight: 400; text-align: center; @@ -69,6 +76,7 @@ background: 0 0; box-shadow: none; border-color: transparent; + text-decoration: none; } .detail-content { @@ -77,7 +85,6 @@ } .histories-list { - padding-left: 15px; margin-bottom: 0; margin-top: 0; list-style: decimal; @@ -85,6 +92,24 @@ flex-direction: column; } +.histories-list .timeline { + top: 13px; + bottom: 13px; + left: 10px; + background: #EEE; +} + +.histories-list .marker { + color: #5E626D; + border-color: #EEE; + border-width: 1px; + box-shadow: none; + background: #FCFDFE; + height: 1.25rem; + width: 1.25rem; + white-space: nowrap; +} + .histories-list.sort-reverse { flex-direction: column-reverse; } @@ -93,6 +118,7 @@ word-break: break-word; word-wrap: break-word; position: relative; + list-style: none; } .histories-list > li strong { diff --git a/lib/zin/wg/history/v1.php b/lib/zin/wg/history/v1.php index ac7c2c8a7e..5adebdd95f 100644 --- a/lib/zin/wg/history/v1.php +++ b/lib/zin/wg/history/v1.php @@ -14,10 +14,24 @@ class history extends wg return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css'); } + private function marker(int $num) + { + return span + ( + setClass('marker', 'text-sm', 'rounded-full', 'aspect-square', 'inline-flex', 'justify-center', 'items-center', 'mr-2'), + $num + ); + } + + private function timeline() + { + return div(setClass('timeline w-px absolute')); + } + private function checkEditCommentPriv($action) { global $app; - $methodName = $this->prop('methodName') ?? data('methodName'); + $methodName = $this->prop('methodName') === null ? $this->prop('methodName') : data('methodName'); return (!isset($canBeChanged) || !empty($canBeChanged)) && end($actions) == $action @@ -27,10 +41,9 @@ class history extends wg && common::hasPriv('action', 'editComment'); } - private function createExpandBtn($i) + private function expandBtn($i) { global $lang; - return button ( setClass('btn btn-mini switch-btn btn-icon btn-expand'), @@ -52,10 +65,9 @@ class history extends wg ); } - private function createEditCommentBtn() + private function editCommentBtn() { global $lang; - return button ( setClass('btn btn-link btn-icon btn-sm btn-edit-comment'), @@ -64,10 +76,9 @@ class history extends wg ); } - private function createHistoryChangesView($action, $i) + private function historyChanges($action, $i) { global $app; - return div ( setClass('history-changes'), @@ -76,18 +87,19 @@ class history extends wg ); } - private function createActionItemView($action, $i) + private function actionItem($action, $i) { global $app; - return li ( + setClass('my-3'), set::value($i), + $this->marker($i), html($app->loadTarget('action')->renderAction($action)) ); } - private function generateComment($action) + private function getComment($action) { if(str_contains($action->comment, '
'))
{
@@ -102,10 +114,9 @@ class history extends wg
: $action->comment;
}
- private function createCommentView($action)
+ private function comment($action)
{
- $comment = $this->generateComment($action);
-
+ $comment = $this->getComment($action);
return div
(
setClass('article-content comment'),
@@ -117,10 +128,9 @@ class history extends wg
);
}
- private function createCommentEditForm($action)
+ private function commentEditForm($action)
{
global $lang;
-
return form
(
setClass('comment-edit-form'),
@@ -156,51 +166,38 @@ class history extends wg
);
}
- private function buildHistoriesList()
+ private function historyList()
{
- $actions = $this->prop('actions') ?? data('actions');
- $users = $this->prop('users') ?? data('users');
- $historiesListView = h::ol(setClass('histories-list'));
+ $actions = $this->prop('actions') === null ? $this->prop('actions') : data('actions');
+ $users = $this->prop('users') === null ? $this->prop('users') : data('users');
+ $historiesListView = h::ol(setClass('histories-list relative'));
$i = 0;
+ $historiesListView->add($this->timeline());
foreach($actions as $action)
{
- if($action->action === 'assigned' || $action->action === 'toaudit')
- $action->extra = zget($users, $action->extra);
+ if($action->action === 'assigned' || $action->action === 'toaudit') $action->extra = zget($users, $action->extra);
$action->actor = zget($users, $action->actor);
- if(str_contains($action->actor, ':'))
- $action->actor = substr($action->actor, strpos($action->actor, ':') + 1);
+ if(str_contains($action->actor, ':')) $action->actor = substr($action->actor, strpos($action->actor, ':') + 1);
$i++;
- $actionItemView = $this->createActionItemView($action, $i);
+ $actionItemView = $this->actionItem($action, $i);
if(!empty($action->history))
{
- $allExpandBtn = $this->createExpandBtn($i);
- $actionItemView->add($allExpandBtn);
-
- $historyChangesView = $this->createHistoryChangesView($action, $i);
- $actionItemView->add($historyChangesView);
+ $actionItemView->add($this->expandBtn($i));
+ $actionItemView->add($this->historyChanges($action, $i));
}
if(strlen(trim(($action->comment))) !== 0)
{
$canEditComment = $this->checkEditCommentPriv($action);
- if($canEditComment)
- {
- $editCommentBtn = $this->createEditCommentBtn();
- $actionItemView->add($editCommentBtn);
- }
+ if($canEditComment) $actionItemView->add($this->editCommentBtn());
- $commentView = $this->createCommentView($action);
- $actionItemView->add($commentView);
+ $actionItemView->add($this->comment($action));
- if($canEditComment)
- {
- $commentEditForm = $this->createCommentEditForm($action);
- $actionItemView->add($commentEditForm);
- }
+ if($canEditComment) $actionItemView->add($this->commentEditForm($action));
}
$historiesListView->add($actionItemView);
}
@@ -208,6 +205,62 @@ class history extends wg
return $historiesListView;
}
+ private function reverseBtn()
+ {
+ global $lang;
+ return btn
+ (
+ setClass('btn-mini btn-icon btn-reverse mr-2'),
+ set::title($lang->reverse),
+ set::icon('arrow-up'),
+ on::click(<<switchDisplay),
+ set::icon('plus'),
+ on::click(<<action->create
+ );
+ }
+
protected function build()
{
global $lang;
@@ -221,51 +274,11 @@ class history extends wg
(
setClass('detail-title'),
span($lang->history),
- button
- (
- setClass('btn btn-mini btn-icon btn-reverse'),
- setStyle('margin-right', '4px'),
- set::type('button'),
- set::title($lang->reverse),
- h::i(setClass('icon icon-arrow-up icon-sm')),
- on::click(<<switchDisplay),
- h::i(setClass('icon icon-plus icon-sm')),
- on::click(<<action->create)
- ),
+ $this->reverseBtn(),
+ $this->expandAllBtn(),
+ $this->commentBtn(),
),
- div(setClass('detail-content'), $this->buildHistoriesList())
+ div(setClass('detail-content'), $this->historyList())
);
}
}
diff --git a/module/block/css/productstatisticblock.ui.css b/module/block/css/productstatisticblock.ui.css
new file mode 100644
index 0000000000..c753cbc820
--- /dev/null
+++ b/module/block/css/productstatisticblock.ui.css
@@ -0,0 +1,7 @@
+.productstatistic-block {background: #FCFDFE;}
+.productstatistic-block .tab-content {width: 100%;}
+.productstatistic-block .bg-secondary-pale {background: #F3F6FA;}
+.productstatistic-block .nav-tabs .nav-item:hover {border-left: 2px solid #2E7FFF; background-color: #FCFDFE;}
+.productstatistic-block .nav-tabs .nav-item.active {border-left: 2px solid #2E7FFF; background-color: #FCFDFE;}
+.productstatistic-block .nav-tabs .nav-item:hover > a.link {display: flex!important;}
+.productstatistic-block .nav-tabs .nav-item > a:before {background: transparent;}
diff --git a/module/block/model.php b/module/block/model.php
index 32764c870f..00fa2e5e46 100644
--- a/module/block/model.php
+++ b/module/block/model.php
@@ -370,49 +370,6 @@ class blockModel extends model
return true;
}
- /**
- * Save a block.
- *
- * @param int $blockID
- * @param string $type
- * @param string $module
- * @access public
- * @return int|false
- */
- public function save(int $blockID, string $type, string $module = 'my'): bool|int
- {
- $block = $blockID ? $this->getByID($blockID) : null;
- $data = fixer::input('post')
- ->setIF($blockID, 'id', $blockID)
- ->add('account', $this->app->user->account)
- ->add('module', $module)
- ->add('order', $block ? $block->order : ($this->getMaxOrderByModule($module) + 1))
- ->add('hidden', 0)
- ->setDefault('vision', $this->config->vision)
- ->setDefault('grid', '4')
- ->setDefault('params', array())
- ->stripTags('html', $this->config->allowedTags)
- ->remove('uid,actionLink,modules,moduleBlock')
- ->get();
-
- $data->source = $this->post->moduleBlock ? $this->post->modules : '';
- $data->block = $this->post->moduleBlock ? $this->post->moduleBlock : $this->post->modules;
-
- if($block) $data->height = $block->height;
- if($type == 'html')
- {
- $uid = $this->post->uid;
- $data = $this->loadModel('file')->processImgURL($data, 'html', $uid);
- $data->params['html'] = $data->html;
- unset($data->html);
- unset($_SESSION['album'][$uid]);
- }
-
- $data->params = helper::jsonEncode($data->params);
-
- $this->dao->replace(TABLE_BLOCK)->data($data)->exec();
- }
-
/**
* Init block when account use first.
* 用户首次加载时初始化区块数据.
@@ -459,7 +416,7 @@ class blockModel extends model
*/
public function isLongBlock(object $block): bool
{
- return (!empty($block) and $block->grid >= 6) ? true : false;
+ return (!empty($block->grid) and $block->grid >= 6) ? true : false;
}
/**
diff --git a/module/block/test/model/appendcountparams.php b/module/block/test/model/appendcountparams.php
deleted file mode 100755
index 090fd5968c..0000000000
--- a/module/block/test/model/appendcountparams.php
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env php
-appendCountParams();
-cid=1
-pid=1
-
-测试新增count param >> count:{name:数量,default:20,control:input};
-测试新增count param 和 param test >> test:test;count:{name:数量,default:20,control:input};
-测试新增count param 和 param par >> par:par;count:{name:数量,default:20,control:input};
-测试新增count param 和 param append >> append:append;count:{name:数量,default:20,control:input};
-测试新增count param 和 param 空 >> count:{name:数量,default:20,control:input};
-
-*/
-$param1 = new stdclass();
-$param1->test = 'test';
-
-$param2 = new stdclass();
-$param2->par = 'par';
-
-$param3 = new stdclass();
-$param3->append = 'append';
-
-$param4 = new stdclass();
-
-$block = new blockTest();
-
-r($block->appendCountParamsTest()) && p() && e('count:{name:数量,default:20,control:input};'); // 测试新增count param
-r($block->appendCountParamsTest($param1)) && p() && e('test:test;count:{name:数量,default:20,control:input};'); // 测试新增count param 和 param test
-r($block->appendCountParamsTest($param2)) && p() && e('par:par;count:{name:数量,default:20,control:input};'); // 测试新增count param 和 param par
-r($block->appendCountParamsTest($param3)) && p() && e('append:append;count:{name:数量,default:20,control:input};'); // 测试新增count param 和 param append
-r($block->appendCountParamsTest($param4)) && p() && e('count:{name:数量,default:20,control:input};'); // 测试新增count param 和 param 空
\ No newline at end of file
diff --git a/module/block/test/model/checkapi.php b/module/block/test/model/checkapi.php
index a04fa668ba..6997cd7526 100755
--- a/module/block/test/model/checkapi.php
+++ b/module/block/test/model/checkapi.php
@@ -19,14 +19,17 @@ function initData()
/**
title=测试 blockModel->checkAPI();
+timeout=0
cid=1
-pid=1
-测试空哈希值 >> 0
-测试正确的哈希值 >> 1
-测试错误的哈希值 >> 0
+sed: can't read /home/liuruogu/git/zentaopms/test/config/my.php: No such file or directory
+- 测试空哈希值 @0
- */
+- 测试正确的哈希值 @1
+
+- 测试错误的哈希值 @0
+
+*/
initData();
@@ -34,4 +37,4 @@ $block = new blockTest();
r($block->checkAPITest('')) && p('') && e('0'); // 测试空哈希值
r($block->checkAPITest('858640a724c2c981983935eb2bbc4ad8')) && p('') && e('1'); // 测试正确的哈希值
-r($block->checkAPITest('858640a724c2c98198')) && p('') && e('0'); // 测试错误的哈希值
+r($block->checkAPITest('858640a724c2c98198')) && p('') && e('0'); // 测试错误的哈希值
\ No newline at end of file
diff --git a/module/block/test/model/create.php b/module/block/test/model/create.php
index 9fbb185e38..a5aa0776a4 100755
--- a/module/block/test/model/create.php
+++ b/module/block/test/model/create.php
@@ -5,61 +5,66 @@ include dirname(__FILE__, 2) . '/block.class.php';
su('admin');
-function initData()
-{
- $block = zdTable('block');
- $block->id->range('2');
- $block->account->range('test');
- $block->vision->range('rnd');
- $block->module->range('test');
- $block->title->prefix('区块')->range('2');
- $block->order->range('5');
-
- $block->gen(1);
-}
-
/**
title=测试 block 模块 model下的 create 方法
timeout=0
cid=39
-- 执行block模块的getByID方法,参数是$newBlockID
+- 测试获取正常的block的内容
- 属性account @admin
- 属性vision @rnd
- 属性dashboard @my
- - 属性title @区块123
- - 属性source @my
- - 属性block @bug
- - 属性order @5
+ - 属性module @project
+ - 属性code @statistic
+ - 属性title @项目统计区块
+ - 属性order @1
-- 执行blockTest模块的create方法,参数是$accoutTooLangBlock,属性account @『所属用户』长度应当不超过『30』,且大于『0』。
+- 测试所属模块为空 @『所属模块』不能为空。
+- 测试所属区块为空 @『区块』不能为空。
+- 测试区块名称为空 @『区块名称』不能为空。
+
+- 测试account 字段字符超出长度 @『所属用户』长度应当不超过『30』,且大于『0』。
*/
global $tester;
$tester->loadModel('block');
-initData();
-
$block = new stdclass();
$block->account = 'admin';
$block->vision = 'rnd';
$block->dashboard = 'my';
-$block->title = '区块123';
-$block->order = '5';
+$block->module = 'project';
+$block->code = 'statistic';
+$block->title = '项目统计区块';
+$block->order = '1';
-$accoutTooLangBlock = new stdclass();
-$accoutTooLangBlock->account = 'adminadminadminadminadminadminadminadmin1';
-$accoutTooLangBlock->vision = 'rnd';
-$accoutTooLangBlock->dashboard = 'my';
-$accoutTooLangBlock->title = 'long account';
-$accoutTooLangBlock->order = '5';
+$accountTooLangBlock = new stdclass();
+$accountTooLangBlock->account = 'adminadminadminadminadminadminadminadmin1';
+$accountTooLangBlock->vision = 'rnd';
+$accountTooLangBlock->dashboard = 'my';
+$accountTooLangBlock->module = 'project';
+$accountTooLangBlock->code = 'statistic';
+$accountTooLangBlock->title = '项目统计区块2';
+$accountTooLangBlock->order = '2';
+
+$emptyModuleBlock = new stdclass();
+$emptyModuleBlock->module = '';
+
+$emptyCodeBlock = new stdclass();
+$emptyCodeBlock->code = '';
+
+$emptyTitleBlock = new stdclass();
+$emptyTitleBlock->title = '';
$blockTest = new blockTest();
$newBlockID = $blockTest->createTest($block);
-r($tester->block->getByID($newBlockID)) && p('account,vision,dashboard,title,order') && e('admin,rnd,my,区块123,5'); // 测试获取正常的block的内容
-r($blockTest->createTest($accoutTooLangBlock)) && p('account:0') && e('『所属用户』长度应当不超过『30』,且大于『0』。'); // 测试account 字段字符超出长度
+r($tester->block->getByID($newBlockID)) && p('account,vision,dashboard,module,code,title,order') && e('admin,rnd,my,project,statistic,项目统计区块,1'); // 测试获取正常的block的内容
+r($blockTest->createTest($emptyModuleBlock)) && p('module:0') && e('『所属模块』不能为空。'); // 测试所属模块为空
+r($blockTest->createTest($emptyCodeBlock)) && p('code:0') && e('『区块』不能为空。'); // 测试所属区块为空
+r($blockTest->createTest($emptyTitleBlock)) && p('title:0') && e('『区块名称』不能为空。'); // 测试区块名称为空
+r($blockTest->createTest($accountTooLangBlock)) && p('account:0') && e('『所属用户』长度应当不超过『30』,且大于『0』。'); // 测试account 字段字符超出长度
\ No newline at end of file
diff --git a/module/block/test/model/getassigntomeparams.php b/module/block/test/model/getassigntomeparams.php
deleted file mode 100755
index e82aeaf37a..0000000000
--- a/module/block/test/model/getassigntomeparams.php
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env php
-getAssignToMeParams();
-cid=1
-pid=1
-
-获取当前登陆用户待办的默认参数 >> 待办数,20,input
-获取当前登陆用户任务的默认参数 >> 任务数,20,input
-获取当前登陆用户Bug的默认参数 >> Bug数,20,input
-获取当前登陆用户需求的默认参数 >> 需求数,20,input
-
-*/
-
-$block = new blockTest();
-$data = $block->getAssignToMeParamsTest();
-
-r($data) && p('todoCount:name,default,control') && e('待办数,20,input'); // 获取当前登陆用户待办的默认参数
-r($data) && p('taskCount:name,default,control') && e('任务数,20,input'); // 获取当前登陆用户任务的默认参数
-r($data) && p('bugCount:name,default,control') && e('Bug数,20,input'); // 获取当前登陆用户Bug的默认参数
-r($data) && p('storyCount:name,default,control') && e('需求数,20,input'); // 获取当前登陆用户需求的默认参数
\ No newline at end of file
diff --git a/module/block/test/model/getavailableblocks.php b/module/block/test/model/getavailableblocks.php
index f2f24d5364..ae639c4363 100755
--- a/module/block/test/model/getavailableblocks.php
+++ b/module/block/test/model/getavailableblocks.php
@@ -9,9 +9,6 @@ title=测试 blockModel->getAvailableBlocks();
cid=1
pid=1
-通过获取项目的可用区块 >> 项目计划,最新动态
-通过获取测试的可用区块 >> 测试统计,Bug列表,用例列表,版本列表
-
*/
$block = new blockTest();
diff --git a/module/block/test/model/getblock.php b/module/block/test/model/getblock.php
deleted file mode 100755
index 68c8c45db3..0000000000
--- a/module/block/test/model/getblock.php
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env php
-getBlock();
-cid=1
-pid=1
-
-测试获取block的所属模块 >> my
-测试获取block的名称 >> 项目统计
-测试获取block的来源 >> project
-测试获取block的区块 >> statistic
-
-*/
-
-$block = new blockTest();
-$data = $block->getBlockTest(99);
-
-r($data) && p('module') && e('my'); // 测试获取block的所属模块
-r($data) && p('title') && e('项目统计'); // 测试获取block的名称
-r($data) && p('source') && e('project'); // 测试获取block的来源
-r($data) && p('block') && e('statistic'); // 测试获取block的区块
\ No newline at end of file
diff --git a/module/block/test/model/getblocklist.php b/module/block/test/model/getblocklist.php
deleted file mode 100755
index 64cc7240ef..0000000000
--- a/module/block/test/model/getblocklist.php
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env php
-getBlockList();
-cid=1
-pid=1
-
- >> 测试统计;指派给我的Bug;指派给我的用例;待测版本列表
- >> 项目计划;最新计划
-
-*/
-
-$block = new blockTest();
-
-r($block->getBlockListTest('qa')) && p('107:title;108:title;109:title;110:title') && e('测试统计;指派给我的Bug;指派给我的用例;待测版本列表');
-r($block->getBlockListTest('project', 'waterfall')) && p('105:title;106:title') && e('项目计划;最新计划');
\ No newline at end of file
diff --git a/module/block/test/model/getbugparams.php b/module/block/test/model/getbugparams.php
deleted file mode 100755
index 338a2c3bf8..0000000000
--- a/module/block/test/model/getbugparams.php
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env php
-getBugParams();
-cid=1
-pid=1
-
-测试通过模块获取Bug区块的参数 >> 数量;类型;排序
-测试通过模块获取Bug区块的参数 >> 数量;类型;排序
-
-*/
-
-$block = new blockTest();
-$data[0] = $block->getBugParamsTest('qa');
-$data[1] = $block->getBugParamsTest('my');
-
-r($data[0]) && p('count:name;type:name;orderBy:name') && e('数量;类型;排序'); //测试通过模块获取Bug区块的参数
-r($data[1]) && p('count:name;type:name;orderBy:name') && e('数量;类型;排序'); //测试通过模块获取Bug区块的参数
\ No newline at end of file
diff --git a/module/block/test/model/getbuildparams.php b/module/block/test/model/getbuildparams.php
deleted file mode 100755
index 39e03c683d..0000000000
--- a/module/block/test/model/getbuildparams.php
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env php
-getBuildParams();
-cid=1
-pid=1
-
-测试获取版本区块参数 >> 数量,20,input
-
-*/
-
-$block = new blockTest();
-$data = $block->getBuildParamsTest();
-
-r($data) && p('count:name,default,control') && e('数量,20,input'); //测试获取版本区块参数
\ No newline at end of file
diff --git a/module/block/test/model/getbyid.php b/module/block/test/model/getbyid.php
index c91889a9ad..b1bbbba46a 100755
--- a/module/block/test/model/getbyid.php
+++ b/module/block/test/model/getbyid.php
@@ -7,11 +7,13 @@ function initData()
{
$block = zdTable('block');
$block->id->range('2-5');
- $block->account->range('admin,test1,test2');
+ $block->account->range('admin');
$block->vision->range('rnd,lite');
- $block->module->range('my,qa,project');
- $block->title->prefix('区块')->range('2-5');
- $block->order->range('5-2');
+ $block->dashboard->range('my');
+ $block->module->range('project');
+ $block->code->range('list,statistic');
+ $block->title->prefix('区块名称')->range('2-5');
+ $block->order->range('1-4');
$block->gen(4);
}
@@ -22,18 +24,18 @@ title=测试 blockModel->getByID();
timeout=0
cid=1
-- 执行block模块的getByID方法,参数是2
+- 测试获取正常的block的内容
- 属性account @admin
- 属性vision @rnd
- - 属性module @my
- - 属性title @区块2
- - 属性source @my
- - 属性block @bug
- - 属性order @5
+ - 属性dashboard @my
+ - 属性module @project
+ - 属性code @list
+ - 属性title @区块名称2
+ - 属性order @1
-- 执行block模块的getByID方法,参数是4,属性order @3
-- 执行block模块的getByID方法,参数是6 @0
+- 测试获取正常的block的内容属性order @3
+- 测试获取不存在的block的内容 @0
*/
@@ -42,6 +44,6 @@ $tester->loadModel('block');
initData();
-r($tester->block->getByID(2)) && p('account,vision,module,title,order') && e('admin,rnd,my,区块2,5'); // 测试获取正常的block的内容
+r($tester->block->getByID(2)) && p('account,vision,dashboard,module,code,title,order') && e('admin,rnd,my,project,list,区块名称2,1'); // 测试获取正常的block的内容
r($tester->block->getByID(4)) && p('order') && e('3'); // 测试获取正常的block的内容
-r($tester->block->getByID(6)) && p('') && e('0'); // 测试获取不存在的block的内容
+r($tester->block->getByID(6)) && p('') && e('0'); // 测试获取不存在的block的内容
\ No newline at end of file
diff --git a/module/block/test/model/getcaseparams.php b/module/block/test/model/getcaseparams.php
deleted file mode 100755
index 334fe013cc..0000000000
--- a/module/block/test/model/getcaseparams.php
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env php
-getCaseParams();
-cid=1
-pid=1
-
-测试通过模块获取用例区块的参数 >> 数量;类型;排序
-测试通过模块获取用例区块的参数 >> 数量;类型;排序
-
-*/
-
-$block = new blockTest();
-$data[0] = $block->getCaseParamsTest('qa');
-$data[1] = $block->getCaseParamsTest('my');
-
-r($data[0]) && p('count:name;type:name;orderBy:name') && e('数量;类型;排序'); //测试通过模块获取用例区块的参数
-r($data[1]) && p('count:name;type:name;orderBy:name') && e('数量;类型;排序'); //测试通过模块获取用例区块的参数
\ No newline at end of file
diff --git a/module/block/test/model/getexecutionparams.php b/module/block/test/model/getexecutionparams.php
deleted file mode 100755
index 5c80eab9ae..0000000000
--- a/module/block/test/model/getexecutionparams.php
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env php
-getExecutionParams();
-cid=1
-pid=1
-
-测试获取执行区块的参数 >> 数量;类型
-
-*/
-
-$block = new blockTest();
-$data = $block->getExecutionParamsTest();
-
-r($data) && p('count:name;type:name') && e('数量;类型'); //测试获取执行区块的参数
\ No newline at end of file
diff --git a/module/block/test/model/getexecutionstatisticparams.php b/module/block/test/model/getexecutionstatisticparams.php
deleted file mode 100755
index 183de9b9ea..0000000000
--- a/module/block/test/model/getexecutionstatisticparams.php
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env php
-getExecutionStatisticParams();
-cid=1
-pid=1
-
-测试获取执行区块的参数 >> 数量;类型
-
-*/
-
-$block = new blockTest();
-$data = $block->getExecutionStatisticParamsTest();
-
-r($data) && p('count:name;type:name') && e('数量;类型'); //测试获取执行区块的参数
\ No newline at end of file
diff --git a/module/block/test/model/gethiddenblocks.php b/module/block/test/model/gethiddenblocks.php
deleted file mode 100755
index e8a222fc1c..0000000000
--- a/module/block/test/model/gethiddenblocks.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getHiddenBlocks();
-cid=1
-pid=1
-
-测试获取隐藏的区块 >> 未获取到隐藏的区块
-
-*/
-
-$block = new blockTest();
-
-r($block->getHiddenBlocksTest('my')) && p('message') && e('未获取到隐藏的区块'); //测试获取隐藏的区块
\ No newline at end of file
diff --git a/module/block/test/model/getlastkey.php b/module/block/test/model/getlastkey.php
deleted file mode 100755
index 4593256e0e..0000000000
--- a/module/block/test/model/getlastkey.php
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env php
-getLastKey();
-cid=1
-pid=1
-
-测试通过qa模块获取区块的key >> 4
-测试通过my模块获取区块的key >> 10
-
-*/
-
-$block = new blockTest();
-$data[0] = $block->getLastKeyTest('qa');
-$data[1] = $block->getLastKeyTest('my');
-
-r($data[0]) && p('qa') && e('4'); //测试通过qa模块获取区块的key
-r($data[1]) && p('my') && e('10'); //测试通过my模块获取区块的key
\ No newline at end of file
diff --git a/module/block/test/model/getlistparams.php b/module/block/test/model/getlistparams.php
deleted file mode 100755
index 48799a7461..0000000000
--- a/module/block/test/model/getlistparams.php
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env php
-getListParams();
-cid=1
-pid=1
-
-测试通过模块获取区块的参数 >> 数量
-测试通过模块获取区块的参数 >> 数量
-测试通过模块获取区块的参数 >> 数量;类型;排序
-
-*/
-
-$block = new blockTest();
-$data[0] = $block->getListParamsTest('my');
-$data[1] = $block->getListParamsTest('qa');
-$data[2] = $block->getListParamsTest('project');
-
-r($data[0]) && p('count:name') && e('数量'); //测试通过模块获取区块的参数
-r($data[1]) && p('count:name') && e('数量'); //测试通过模块获取区块的参数
-r($data[2]) && p('count:name;type:name;orderBy:name') && e('数量;类型;排序'); //测试通过模块获取区块的参数
\ No newline at end of file
diff --git a/module/block/test/model/getmaxorderbydashboard.php b/module/block/test/model/getmaxorderbydashboard.php
index 0c47617e4b..47478b0327 100644
--- a/module/block/test/model/getmaxorderbydashboard.php
+++ b/module/block/test/model/getmaxorderbydashboard.php
@@ -2,20 +2,19 @@
identify('admin', 'Asd123456');
-$userModel->login($user);
+su('admin');
function initData()
{
$block = zdTable('block');
$block->id->range('2-5');
- $block->account->range('admin,test1,test2');
+ $block->account->range('admin');
$block->vision->range('rnd,lite');
- $block->module->range('my,qa,project');
- $block->title->prefix('区块')->range('2-5');
- $block->dashboard->range('my,qa');
- $block->order->range('5-2');
+ $block->dashboard->range('my');
+ $block->module->range('project');
+ $block->code->range('list,statistic');
+ $block->title->prefix('区块名称')->range('2-5');
+ $block->order->range('1-4');
$block->gen(4);
}
@@ -26,16 +25,6 @@ title=测试 blockModel->getMaxOrderByDashboard();
timeout=0
cid=1
-- 执行block模块的getByID方法,参数是2
- - 属性account @admin
- - 属性vision @rnd
- - 属性module @my
- - 属性title @区块2
- - 属性source @my
- - 属性block @bug
- - 属性order @5
-
-
*/
global $tester;
@@ -43,6 +32,6 @@ $tester->loadModel('block');
initData();
-r($tester->block->getMaxOrderByDashboard('my')) && p('') && e('5'); // 测试 my 模块下最大order 为 5
-r($tester->block->getMaxOrderByDashboard('my')) && p('') && e('5'); // 测试 my 模块下最大order 为 5
+r($tester->block->getMaxOrderByDashboard('my')) && p('') && e('4'); // 测试 my 模块下最大order 为 4
+r($tester->block->getMaxOrderByDashboard('my')) && p('') && e('4'); // 测试 my 模块下最大order 为 4
r($tester->block->getMaxOrderByDashboard('bug')) && p('') && e('0'); // 测试数据库中不存在 模块的最大排序 为 0
diff --git a/module/block/test/model/getmydashboard.php b/module/block/test/model/getmydashboard.php
index eea65dad87..6934c8ca41 100644
--- a/module/block/test/model/getmydashboard.php
+++ b/module/block/test/model/getmydashboard.php
@@ -3,25 +3,19 @@
include dirname(__FILE__, 5) . "/test/lib/init.php";
include dirname(__FILE__, 2) . '/block.class.php';
-#su('admin');
-
-$userModel = new userModel();
-$user = $userModel->identify('admin', 'Asd123456');
-$userModel->login($user);
+su('admin');
function initData()
{
$block = zdTable('block');
- $block->id->range('2-3');
+ $block->id->range('2-5');
$block->account->range('admin');
- $block->vision->range('rnd');
- $block->module->range('test,my');
- $block->title->prefix('区块')->range('3,2');
- $block->hidden->range('0-1');
- $block->order->range('3-2');
- $block->dashboard->range('test,my');
+ $block->vision->range('rnd,lite');
+ $block->dashboard->range('my,qa,project');
+ $block->title->prefix('区块')->range('2-5');
+ $block->order->range('5-2');
- $block->gen(2);
+ $block->gen(4);
}
/**
@@ -36,7 +30,8 @@ $tester->loadModel('block');
initData();
-r($tester->block->getMyDashboard('test')) && p('2:account,title') && e('admin,区块3'); // 测试我的 test 模块的面板
-r($tester->block->getMyHiddenBlocks('my')) && p('3:account,title') && e('admin,区块2');// 测试我的 my 模块隐藏的面板
-r($tester->block->getMyDashboard('noneModule')) && p('') && e('0');// 测试我的 不存在的 模块的面板
-r($tester->block->getMyDashboard('')) && p('') && e('0');// 测试我的 空 模块的面板
+r(count($tester->block->getMyDashboard('my'))) && p('') && e('1'); // 查询admin用户在我的地盘仪表盘的区块列表数量
+r($tester->block->getMyDashboard('my')) && p('2:title') && e('区块2'); // 查询admin用户在我的地盘仪表盘的区块标题第2条的title属性
+r(count($tester->block->getMyDashboard('my', 1))) && p('') && e('0'); // 查询admin用户在我的地盘仪表盘的隐藏区块列表数量
+r(count($tester->block->getMyDashboard('asdas?'))) && p('') && e('0'); // 查询admin用户在不存在仪表盘的区块列表数量
+r($tester->block->getMyDashboard('my')) && p('2:vision') && e('rnd'); // 查询admin用户在我的地盘仪表盘区块的vision第2条的vision属性
diff --git a/module/block/test/model/getplanparams.php b/module/block/test/model/getplanparams.php
deleted file mode 100755
index d4f4ebd7a4..0000000000
--- a/module/block/test/model/getplanparams.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getPlanParams();
-cid=1
-pid=1
-
-获取计划参数 >> {"count":{"name":"\u6570\u91cf","default":20,"control":"input"}}
-
-*/
-
-$block = new blockTest();
-
-r($block->getPlanParamsTest()) && p() && e('{"count":{"name":"\u6570\u91cf","default":20,"control":"input"}}'); // 获取计划参数
\ No newline at end of file
diff --git a/module/block/test/model/getproductparams.php b/module/block/test/model/getproductparams.php
deleted file mode 100755
index 92455e2fbb..0000000000
--- a/module/block/test/model/getproductparams.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getProductParams();
-cid=1
-pid=1
-
-获取产品区块的参数 >> type:{name:类型,noclosed=>未关闭,closed=>已关闭,all=>全部,involved=>我参与,control:select};count:{name:数量,default:20,control:input};
-
-*/
-
-$block = new blockTest();
-
-r($block->getProductParamsTest()) && p() && e('type:{name:类型,noclosed=>未关闭,closed=>已关闭,all=>全部,involved=>我参与,control:select};count:{name:数量,default:20,control:input};'); // 获取产品区块的参数
diff --git a/module/block/test/model/getproductstatisticparams.php b/module/block/test/model/getproductstatisticparams.php
deleted file mode 100755
index 9d1057dfd9..0000000000
--- a/module/block/test/model/getproductstatisticparams.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getProductStatisticParams();
-cid=1
-pid=1
-
-获取产品统计区块的参数 >> count:{name:数量,default:20,control:input};type:{name:类型,noclosed=>未关闭,closed=>已关闭,all=>全部,involved=>我参与,control:select};
-
-*/
-
-$block = new blockTest();
-
-r($block->getProductStatisticParamsTest()) && p() && e('count:{name:数量,default:20,control:input};type:{name:类型,noclosed=>未关闭,closed=>已关闭,all=>全部,involved=>我参与,control:select};'); // 获取产品统计区块的参数
diff --git a/module/block/test/model/getprojectdynamicparams.php b/module/block/test/model/getprojectdynamicparams.php
deleted file mode 100755
index cc326b7f07..0000000000
--- a/module/block/test/model/getprojectdynamicparams.php
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env php
-getProjectDynamicParams();
-cid=1
-pid=1
-
-获取项目动态区块参数 >> count:{name:数量,default:20,control:input};
-*/
-
-$block = new blockTest();
-
-r($block->getProjectDynamicParamsTest()) && p() && e('count:{name:数量,default:20,control:input};'); // 获取项目动态区块参数
diff --git a/module/block/test/model/getprojectparams.php b/module/block/test/model/getprojectparams.php
deleted file mode 100755
index 016f529b9c..0000000000
--- a/module/block/test/model/getprojectparams.php
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env php
-getProjectParams();
-cid=1
-pid=1
-
-获取计划参数 >> {"type":{"name":"\u7c7b\u578b","options":{"all":"\u6240\u6709","undone":"\u672a\u5b8c\u6210","wait":"\u672a\u5f00\u59cb","doing":"\u8fdb\u884c\u4e2d","suspended":"\u5df2\u6302\u8d77","closed":"\u5df2\u5173\u95ed"},"control":"select"},"orderBy":{"name":"\u6392\u5e8f","options":{"id_asc":"ID \u9012\u589e","id_desc":"ID \u9012\u51cf","status_asc":"\u72b6\u6001\u6b63\u5e8f","status_desc":"\u72b6\u6001\u5012\u5e8f"},"control":"select"},"count":{"name":"\u6570\u91cf","default":20,"control":"input"}}
-*/
-
-$block = new blockTest();
-
-r($block->getProjectParamsTest()) && p() && e('{"type":{"name":"\u7c7b\u578b","options":{"all":"\u6240\u6709","undone":"\u672a\u5b8c\u6210","wait":"\u672a\u5f00\u59cb","doing":"\u8fdb\u884c\u4e2d","suspended":"\u5df2\u6302\u8d77","closed":"\u5df2\u5173\u95ed"},"control":"select"},"orderBy":{"name":"\u6392\u5e8f","options":{"id_asc":"ID \u9012\u589e","id_desc":"ID \u9012\u51cf","status_asc":"\u72b6\u6001\u6b63\u5e8f","status_desc":"\u72b6\u6001\u5012\u5e8f"},"control":"select"},"count":{"name":"\u6570\u91cf","default":20,"control":"input"}}'); //获取计划参数
diff --git a/module/block/test/model/getprojectstatisticparams.php b/module/block/test/model/getprojectstatisticparams.php
deleted file mode 100755
index 55ec0f0e0f..0000000000
--- a/module/block/test/model/getprojectstatisticparams.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getProjectStatisticParams();
-cid=1
-pid=1
-
-获取project静态param >> {"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":{"undone":"未完成","doing":"进行中","all":"全部","involved":"我参与的"},"control":"select"}}
-
-*/
-
-$block = new blockTest();
-
-r($block->getProjectStatisticParamsTest()) && p() && e('{"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":{"undone":"未完成","doing":"进行中","all":"全部","involved":"我参与的"},"control":"select"}}'); // 获取project静态param
\ No newline at end of file
diff --git a/module/block/test/model/getprojectteamparams.php b/module/block/test/model/getprojectteamparams.php
deleted file mode 100755
index 777d55fd01..0000000000
--- a/module/block/test/model/getprojectteamparams.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getProjectTeamParams();
-cid=1
-pid=1
-
-测试获取项目团队 >> type:{name:类型,all=>所有,undone=>未完成,wait=>未开始,doing=>进行中,suspended=>已挂起,closed=>已关闭,control:select};orderBy:{name:排序,id_asc=>ID 递增,id_desc=>ID 递减,status_asc=>状态正序,status_desc=>状态倒序,control:select};count:{name:数量,default:20,control:input};
-
-*/
-
-$block = new blockTest();
-
-r($block->getProjectTeamParamsTest()) && p() && e('type:{name:类型,all=>所有,undone=>未完成,wait=>未开始,doing=>进行中,suspended=>已挂起,closed=>已关闭,control:select};orderBy:{name:排序,id_asc=>ID 递增,id_desc=>ID 递减,status_asc=>状态正序,status_desc=>状态倒序,control:select};count:{name:数量,default:20,control:input};'); // 测试获取项目团队
diff --git a/module/block/test/model/getqastatisticparams.php b/module/block/test/model/getqastatisticparams.php
deleted file mode 100755
index 72fb78ce21..0000000000
--- a/module/block/test/model/getqastatisticparams.php
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env php
-getQaStatisticParams();
-cid=1
-pid=1
-
-测试name >> 类型
-测试control >> select
-
-*/
-
-$block = new blockTest();
-
-r($block->getQaStatisticParamsTest()) && p('type:name') && e('类型'); //测试name
-r($block->getQaStatisticParamsTest()) && p('type:control') && e('select');//测试control
\ No newline at end of file
diff --git a/module/block/test/model/getreleaseparams.php b/module/block/test/model/getreleaseparams.php
deleted file mode 100755
index 385d928357..0000000000
--- a/module/block/test/model/getreleaseparams.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getReleaseParams();
-cid=1
-pid=1
-
-测试name >> 数量,20,input
-
-*/
-
-$block = new blockTest();
-
-r($block->getReleaseParamsTest()) && p('name,default,control') && e('数量,20,input'); //测试name
\ No newline at end of file
diff --git a/module/block/test/model/getscrumlistparams.php b/module/block/test/model/getscrumlistparams.php
deleted file mode 100755
index 09bf516922..0000000000
--- a/module/block/test/model/getscrumlistparams.php
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env php
-getScrumListParams();
-cid=1
-pid=1
-
-测试name和select >> 类型,select
-测试options >> 未完成
-测试options >> 进行中
-测试options >> 全部
-测试options >> 我参与
-
-*/
-
-$block = new blockTest();
-
-r($block->getScrumListParamsTest()) && p('name,control') && e('类型,select'); //测试name和select
-r($block->getScrumListParamsTest()) && p('options:undone') && e('未完成'); //测试options
-r($block->getScrumListParamsTest()) && p('options:doing') && e('进行中'); //测试options
-r($block->getScrumListParamsTest()) && p('options:all') && e('全部'); //测试options
-r($block->getScrumListParamsTest()) && p('options:involved') && e('我参与'); //测试options
\ No newline at end of file
diff --git a/module/block/test/model/getscrumproductparams.php b/module/block/test/model/getscrumproductparams.php
deleted file mode 100755
index fff6bf6faf..0000000000
--- a/module/block/test/model/getscrumproductparams.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getScrumProductParams();
-cid=1
-pid=1
-
-测试获取产品区块的参数 >> 数量;20;input
-
-*/
-
-$block = new blockTest();
-
-r($block->getScrumProductParamsTest()) && p('count:name;count:default;count:control') && e('数量;20;input'); // 测试获取产品区块的参数
\ No newline at end of file
diff --git a/module/block/test/model/getscrumroadmapparams.php b/module/block/test/model/getscrumroadmapparams.php
deleted file mode 100755
index a35c36473e..0000000000
--- a/module/block/test/model/getscrumroadmapparams.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getScrumRoadMapParams();
-cid=1
-pid=1
-
-测试获取产品路线图区块的参数 >> 0
-
-*/
-
-$block = new blockTest();
-
-r($block->getScrumRoadMapParamsTest()) && p() && e('0'); // 测试获取产品路线图区块的参数
\ No newline at end of file
diff --git a/module/block/test/model/getscrumtestparams.php b/module/block/test/model/getscrumtestparams.php
deleted file mode 100755
index cdcc4d675b..0000000000
--- a/module/block/test/model/getscrumtestparams.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getScrumTestParams();
-cid=1
-pid=1
-
-测试获取测试单区块的参数 >> 数量;类型
-
-*/
-
-$block = new blockTest();
-
-r($block->getScrumTestParamsTest()) && p('count:name;type:name') && e('数量;类型'); // 测试获取测试单区块的参数
\ No newline at end of file
diff --git a/module/block/test/model/getstatisticparams.php b/module/block/test/model/getstatisticparams.php
deleted file mode 100755
index 7d3e20ee94..0000000000
--- a/module/block/test/model/getstatisticparams.php
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env php
-getStatisticParams();
-cid=1
-pid=1
-
-获取空区块的参数 >> {"count":{"name":"数量","default":20,"control":"input"}}
-获取产品区块的参数 >> {"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":{"noclosed":"未关闭","closed":"已关闭","all":"全部","involved":"我参与"},"control":"select"}}
-获取项目区块的参数 >> {"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":{"undone":"未完成","doing":"进行中","all":"全部","involved":"我参与的"},"control":"select"}}
-获取执行区块的参数 >> {"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":{"undone":"未完成","doing":"进行中","all":"所有","involved":"我参与"},"control":"select"}}
-获取测试区块的参数 >> {"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":{"noclosed":"未关闭","closed":"已关闭","all":"全部","involved":"我参与"},"control":"select"}}
-
-*/
-
-$block = new blockTest();
-
-$data = array();
-$data[0] = $block->getStatisticParamsTest('');
-$data[1] = $block->getStatisticParamsTest('product');
-$data[2] = $block->getStatisticParamsTest('project');
-$data[3] = $block->getStatisticParamsTest('execution');
-$data[4] = $block->getStatisticParamsTest('qa');
-
-r($data[0]) && p() && e('{"count":{"name":"数量","default":20,"control":"input"}}'); // 获取空区块的参数
-r($data[1]) && p() && e('{"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":{"noclosed":"未关闭","closed":"已关闭","all":"全部","involved":"我参与"},"control":"select"}}'); // 获取产品区块的参数
-r($data[2]) && p() && e('{"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":{"undone":"未完成","doing":"进行中","all":"全部","involved":"我参与的"},"control":"select"}}'); // 获取项目区块的参数
-r($data[3]) && p() && e('{"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":{"undone":"未完成","doing":"进行中","all":"所有","involved":"我参与"},"control":"select"}}'); // 获取执行区块的参数
-r($data[4]) && p() && e('{"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":{"noclosed":"未关闭","closed":"已关闭","all":"全部","involved":"我参与"},"control":"select"}}'); // 获取测试区块的参数
\ No newline at end of file
diff --git a/module/block/test/model/getstoryparams.php b/module/block/test/model/getstoryparams.php
deleted file mode 100755
index 05e4c1c985..0000000000
--- a/module/block/test/model/getstoryparams.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getStoryParams();
-cid=1
-pid=1
-
-获取需求的参数 >> {"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":{"assignedTo":"指派给我","openedBy":"由我创建","reviewedBy":"由我评审","closedBy":"由我关闭"},"control":"select"},"orderBy":{"name":"排序","default":"id_desc","options":{"id_asc":"ID 递增","id_desc":"ID 递减","pri_asc":"优先级递增","pri_desc":"优先级递减","status_asc":"状态正序","status_desc":"状态倒序","stage_asc":"阶段正序","stage_desc":"阶段倒序"},"control":"select"}}
-
-*/
-
-$block = new blockTest();
-
-r($block->getStoryParamsTest()) && p() && e('{"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":{"assignedTo":"指派给我","openedBy":"由我创建","reviewedBy":"由我评审","closedBy":"由我关闭"},"control":"select"},"orderBy":{"name":"排序","default":"id_desc","options":{"id_asc":"ID 递增","id_desc":"ID 递减","pri_asc":"优先级递增","pri_desc":"优先级递减","status_asc":"状态正序","status_desc":"状态倒序","stage_asc":"阶段正序","stage_desc":"阶段倒序"},"control":"select"}}'); // 获取需求的参数
\ No newline at end of file
diff --git a/module/block/test/model/getstorysestimatehours.php b/module/block/test/model/getstorysestimatehours.php
deleted file mode 100755
index affb340cfa..0000000000
--- a/module/block/test/model/getstorysestimatehours.php
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env php
-getStorysEstimateHours();
-cid=1
-pid=1
-
-获取需求 1 的预计工时 >> 1
-获取需求 2 的预计工时 >> 1
-获取需求 3 的预计工时 >> 1
-获取需求 4 的预计工时 >> 1
-获取需求 5 的预计工时 >> 1
-
-*/
-
-$storyID = array(1, 2, 3, 4, 5);
-
-$block = new blockTest();
-
-r($block->getStorysEstimateHoursTest($storyID[0])) && p('estimate') && e('1'); // 获取需求 1 的预计工时
-r($block->getStorysEstimateHoursTest($storyID[1])) && p('estimate') && e('1'); // 获取需求 2 的预计工时
-r($block->getStorysEstimateHoursTest($storyID[2])) && p('estimate') && e('1'); // 获取需求 3 的预计工时
-r($block->getStorysEstimateHoursTest($storyID[3])) && p('estimate') && e('1'); // 获取需求 4 的预计工时
-r($block->getStorysEstimateHoursTest($storyID[4])) && p('estimate') && e('1'); // 获取需求 5 的预计工时
\ No newline at end of file
diff --git a/module/block/test/model/gettaskparams.php b/module/block/test/model/gettaskparams.php
deleted file mode 100755
index 5cdbe3e02f..0000000000
--- a/module/block/test/model/gettaskparams.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getTaskParams();
-cid=1
-pid=1
-
-获取task的参数 >> {"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":{"assignedTo":"指派给我","openedBy":"由我创建","finishedBy":"由我完成","closedBy":"由我关闭","canceledBy":"由我取消"},"control":"select"},"orderBy":{"name":"排序","default":"id_desc","options":{"id_asc":"ID 递增","id_desc":"ID 递减","pri_asc":"优先级递增","pri_desc":"优先级递减","estimate_asc":"预计时间递增","estimate_desc":"预计时间递减","status_asc":"状态正序","status_desc":"状态倒序","deadline_asc":"截止日期递增","deadline_desc":"截止日期递减"},"control":"select"}}
-
-*/
-
-$block = new blockTest();
-
-r($block->getTaskParamsTest()) && p() && e('{"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":{"assignedTo":"指派给我","openedBy":"由我创建","finishedBy":"由我完成","closedBy":"由我关闭","canceledBy":"由我取消"},"control":"select"},"orderBy":{"name":"排序","default":"id_desc","options":{"id_asc":"ID 递增","id_desc":"ID 递减","pri_asc":"优先级递增","pri_desc":"优先级递减","estimate_asc":"预计时间递增","estimate_desc":"预计时间递减","status_asc":"状态正序","status_desc":"状态倒序","deadline_asc":"截止日期递增","deadline_desc":"截止日期递减"},"control":"select"}}'); // 获取task的参数
\ No newline at end of file
diff --git a/module/block/test/model/gettesttaskparams.php b/module/block/test/model/gettesttaskparams.php
deleted file mode 100755
index 4e48a6d40f..0000000000
--- a/module/block/test/model/gettesttaskparams.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getTesttaskParams();
-cid=1
-pid=1
-
-获取testtask参数 >> {"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":{"wait":"待测版本","doing":"测试中版本","blocked":"阻塞版本","done":"已测版本","all":"全部"},"control":"select"}}
-
-*/
-
-$block = new blockTest();
-
-r($block->getTesttaskParamsTest()) && p() && e('{"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":{"wait":"待测版本","doing":"测试中版本","blocked":"阻塞版本","done":"已测版本","all":"全部"},"control":"select"}}'); // 获取testtask参数
\ No newline at end of file
diff --git a/module/block/test/model/gettodoparams.php b/module/block/test/model/gettodoparams.php
deleted file mode 100755
index 7ca72385eb..0000000000
--- a/module/block/test/model/gettodoparams.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getTodoParams();
-cid=1
-pid=1
-
-获取todo参数 >> {"count":{"name":"数量","default":20,"control":"input"}}
-
-*/
-
-$block = new blockTest();
-
-r($block->getTodoParamsTest()) && p() && e('{"count":{"name":"数量","default":20,"control":"input"}}'); // 获取todo参数
\ No newline at end of file
diff --git a/module/block/test/model/getwaterfallissueparams.php b/module/block/test/model/getwaterfallissueparams.php
deleted file mode 100755
index d026af32e5..0000000000
--- a/module/block/test/model/getwaterfallissueparams.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getWaterfallIssueParams();
-cid=1
-pid=1
-
-获取waterfall issue的参数 >> {"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":null,"control":"select"},"orderBy":{"name":"排序","options":{"id_asc":"ID 递增","id_desc":"ID 递减","status_asc":"状态正序","status_desc":"状态倒序"},"control":"select"}}
-
-*/
-
-$block = new blockTest();
-
-r($block->getWaterfallIssueParamsTest()) && p() && e('{"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":null,"control":"select"},"orderBy":{"name":"排序","options":{"id_asc":"ID 递增","id_desc":"ID 递减","status_asc":"状态正序","status_desc":"状态倒序"},"control":"select"}}'); // 获取waterfall issue的参数
\ No newline at end of file
diff --git a/module/block/test/model/getwaterfallriskparams.php b/module/block/test/model/getwaterfallriskparams.php
deleted file mode 100755
index 9139370692..0000000000
--- a/module/block/test/model/getwaterfallriskparams.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getWaterfallRiskParams();
-cid=1
-pid=1
-
-获取waterfall risk 参数 >> {"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":null,"control":"select"},"orderBy":{"name":"排序","options":{"id_asc":"ID 递增","id_desc":"ID 递减","status_asc":"状态正序","status_desc":"状态倒序"},"control":"select"}}
-
-*/
-
-$block = new blockTest();
-
-r($block->getWaterfallRiskParamsTest()) && p() && e('{"count":{"name":"数量","default":20,"control":"input"},"type":{"name":"类型","options":null,"control":"select"},"orderBy":{"name":"排序","options":{"id_asc":"ID 递增","id_desc":"ID 递减","status_asc":"状态正序","status_desc":"状态倒序"},"control":"select"}}'); // 获取waterfall risk 参数
\ No newline at end of file
diff --git a/module/block/test/model/getwelcomeblockdata.php b/module/block/test/model/getwelcomeblockdata.php
deleted file mode 100755
index 8e182242ae..0000000000
--- a/module/block/test/model/getwelcomeblockdata.php
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env php
-getWelcomeBlockData();
-cid=1
-pid=1
-
-获取欢迎区块的数据 >> {"tasks":"0","doneTasks":"0","bugs":85,"stories":0,"executions":739,"products":80,"delayTask":0,"delayBug":74,"delayProject":0}
-
-*/
-
-$block = new blockTest();
-
-r($block->getWelcomeBlockDataTest()) && p() && e('{"tasks":"0","doneTasks":"0","bugs":85,"stories":0,"executions":739,"products":80,"delayTask":0,"delayBug":74,"delayProject":0}'); // 获取欢迎区块的数据
diff --git a/module/block/test/model/initblock.php b/module/block/test/model/initblock.php
index f2438b194a..ad213dee25 100755
--- a/module/block/test/model/initblock.php
+++ b/module/block/test/model/initblock.php
@@ -7,54 +7,31 @@ su('admin');
/**
title=测试 blockModel->initBlock();
+timeout=0
cid=1
-pid=1
-获取敏捷项目的区块版本 >> 1;2
-获取敏捷项目的区块数据 >> project;scrum
-获取瀑布项目的区块版本 >> 1;2
-获取瀑布项目的区块数据 >> project;waterfall
-获取看板项目的区块版本 >> 1;2
-获取看板项目的区块数据 >> project;kanban
-获取产品的区块版本 >> 1;2
-获取产品的区块数据 >> product;
-获取执行的区块版本 >> 1;2
-获取执行的区块数据 >> execution;
-获取地盘的区块版本 >> 1;2
-获取地盘的区块数据 >> my;
-获取测试的区块版本 >> 1;2
-获取测试的区块数据 >> qa;
-获取空区块版本 >> 1;2
-获取空区块数据 >> 0
+- 测试获取正常的block的内容
+ - 属性account @admin
+ - 属性dashboard @my
+ - 属性module @welcome
+ - 属性code @welcome
+ - 属性title @欢迎
+
+- 测试获取正常的block的内容
+ - 属性account @admin
+ - 属性dashboard @my
+ - 属性module @project
+ - 属性code @project
+ - 属性title @项目列表
*/
-$block = new blockTest();
+global $tester, $app;
+$tester->loadModel('block');
+$tester->block->reset('my');
-$dataList = array();
-$dataList[0] = $block->initBlockTest('project', 'scrum');
-$dataList[1] = $block->initBlockTest('project', 'waterfall');
-$dataList[2] = $block->initBlockTest('project', 'kanban');
-$dataList[3] = $block->initBlockTest('product');
-$dataList[4] = $block->initBlockTest('execution');
-$dataList[5] = $block->initBlockTest('my');
-$dataList[6] = $block->initBlockTest('qa');
-$dataList[7] = $block->initBlockTest('');
-
-r($dataList[0]) && p("blockInited;blockversion") && e('1;2'); // 获取敏捷项目的区块版本
-r($dataList[0]) && p("blockData:module;blockData:type") && e('project;scrum'); // 获取敏捷项目的区块数据
-r($dataList[1]) && p("blockInited;blockversion") && e('1;2'); // 获取瀑布项目的区块版本
-r($dataList[1]) && p("blockData:module;blockData:type") && e('project;waterfall'); // 获取瀑布项目的区块数据
-r($dataList[2]) && p("blockInited;blockversion") && e('1;2'); // 获取看板项目的区块版本
-r($dataList[2]) && p("blockData:module;blockData:type") && e('project;kanban'); // 获取看板项目的区块数据
-r($dataList[3]) && p("blockInited;blockversion") && e('1;2'); // 获取产品的区块版本
-r($dataList[3]) && p("blockData:module;blockData:type") && e('product;'); // 获取产品的区块数据
-r($dataList[4]) && p("blockInited;blockversion") && e('1;2'); // 获取执行的区块版本
-r($dataList[4]) && p("blockData:module;blockData:type") && e('execution;'); // 获取执行的区块数据
-r($dataList[5]) && p("blockInited;blockversion") && e('1;2'); // 获取地盘的区块版本
-r($dataList[5]) && p("blockData:module;blockData:type") && e('my;'); // 获取地盘的区块数据
-r($dataList[6]) && p("blockInited;blockversion") && e('1;2'); // 获取测试的区块版本
-r($dataList[6]) && p("blockData:module;blockData:type") && e('qa;'); // 获取测试的区块数据
-r($dataList[7]) && p("blockInited;blockversion") && e('1;2'); // 获取空区块版本
-r($dataList[7]) && p("blockData") && e('0'); // 获取空区块数据
+$tester->block->initBlock('my');
+$newBlcoks = $tester->block->getMyDashboard('my');
+r(reset($newBlcoks)) && p('account,dashboard,module,code,title') && e('admin,my,welcome,welcome,欢迎'); // 测试获取正常的block的内容
+r(end($newBlcoks)) && p('account,dashboard,module,code,title') && e('admin,my,project,project,项目列表'); // 测试获取正常的block的内容
diff --git a/module/block/test/model/islongblock.php b/module/block/test/model/islongblock.php
index 713a79b38c..7f6c32e76c 100755
--- a/module/block/test/model/islongblock.php
+++ b/module/block/test/model/islongblock.php
@@ -2,35 +2,46 @@
id->range('2-5');
+ $block->account->range('admin');
+ $block->vision->range('rnd,lite');
+ $block->dashboard->range('my');
+ $block->module->range('project');
+ $block->code->range('list,statistic');
+ $block->title->prefix('区块名称')->range('2-5');
+ $block->grid->range('4,8');
+ $block->order->range('1-4');
+
+ $block->gen(4);
+}
+
/**
title=测试 blockModel->isLongBlock();
+timeout=0
cid=1
-pid=1
-测试 空 对象 检查是否为长区块 >> 2
-测试 对象grid为 5 的时候 检查是否为长区块 >> 2
-测试 对象grid为 6 的时候 检查是否为长区块 >> 1
-测试 对象grid为 7 的时候 检查是否为长区块 >> 1
+- 测试 空 对象 检查是否为长区块 @0
+
+- 测试 空 对象 检查是否为长区块 @0
+
+- 测试 空 对象 检查是否为长区块 @1
*/
-$block1 = new stdclass();
+global $tester;
+$tester->loadModel('block');
-$block2 = new stdclass();
-$block2->grid = 5;
+initData();
-$block3 = new stdclass();
-$block3->grid = 6;
+$emptyObject = new stdclass();
-$block4 = new stdclass();
-$block4->grid = 7;
-
-$block = new blockTest();
-
-r($block->isLongBlockTest($block1)) && p() && e('2'); // 测试 空 对象 检查是否为长区块
-r($block->isLongBlockTest($block2)) && p() && e('2'); // 测试 对象grid为 5 的时候 检查是否为长区块
-r($block->isLongBlockTest($block3)) && p() && e('1'); // 测试 对象grid为 6 的时候 检查是否为长区块
-r($block->isLongBlockTest($block4)) && p() && e('1'); // 测试 对象grid为 7 的时候 检查是否为长区块
\ No newline at end of file
+r($tester->block->isLongBlock($emptyObject)) && p() && e('0'); // 测试 空 对象 检查是否为长区块
+r($tester->block->isLongBlock($tester->block->getByID(2))) && p() && e('0'); // 测试 空 对象 检查是否为长区块
+r($tester->block->isLongBlock($tester->block->getByID(3))) && p() && e('1'); // 测试 空 对象 检查是否为长区块
\ No newline at end of file
diff --git a/module/block/test/model/save.php b/module/block/test/model/save.php
deleted file mode 100755
index 7857008401..0000000000
--- a/module/block/test/model/save.php
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env php
-save();
-cid=1
-pid=1
-
-测试修改block 名称 >> 欢迎test,my,8,welcome
-测试修改block 模块 >> 我的贡献,my,8,dynamic
-测试修改block 区块 >> 项目统计,projectteam,8,projectteam
-测试修改block 变量 >> 未关闭的产品,statistic,8,statistic
-
-*/
-
-$blockID = array('95', '99', '113');
-$source = 'product';
-
-$changeTitle = new stdclass();
-$changeTitle->modules = 'welcome';
-$changeTitle->title = '欢迎test';
-$changeTitle->grid = 8;
-$changeTitle->actionLink = '/block-set-95-welcome-.html';
-
-$changeModules = new stdclass();
-$changeModules->modules = 'dynamic';
-$changeModules->title = '我的贡献';
-$changeModules->grid = 8;
-$changeModules->actionLink = '/block-set-95-welcome-.html';
-
-$changeBlock = new stdclass();
-$changeBlock->modules = 'project';
-$changeBlock->title = '项目统计';
-$changeBlock->moduleBlock = 'projectteam';
-$changeBlock->grid = 8;
-$changeBlock->params = array('type' => 'all', 'orderBy' => 'id_asc', 'count' => 20);
-$changeBlock->actionLink = '/block-set-95-welcome-.html';
-
-$changeParams = new stdclass();
-$changeParams->modules = 'product';
-$changeParams->title = '未关闭的产品';
-$changeParams->moduleBlock = 'statistic';
-$changeParams->grid = 8;
-$changeParams->params = array('type' => 'noclosed', 'count' => 30);
-$changeParams->actionLink = '/block-set-95-welcome-.html';
-
-$block = new blockTest();
-
-r($block->saveTest($changeTitle, $blockID[0], $source, $changeTitle->modules)) && p('title,module,grid,block') && e('欢迎test,my,8,welcome'); // 测试修改block 名称
-r($block->saveTest($changeModules, $blockID[0], $source, $changeModules->modules)) && p('title,module,grid,block') && e('我的贡献,my,8,dynamic'); // 测试修改block 模块
-r($block->saveTest($changeBlock, $blockID[1], $source, $changeBlock->modules, $changeBlock->moduleBlock)) && p('title,module,grid,block') && e('项目统计,projectteam,8,projectteam'); // 测试修改block 区块
-r($block->saveTest($changeParams, $blockID[2], $source, $changeParams->modules, $changeParams->moduleBlock)) && p('title,module,grid,block') && e('未关闭的产品,statistic,8,statistic'); // 测试修改block 变量
diff --git a/module/block/test/model/update.php b/module/block/test/model/update.php
index a45e8a26f8..abfbd75d78 100644
--- a/module/block/test/model/update.php
+++ b/module/block/test/model/update.php
@@ -8,14 +8,16 @@ su('admin');
function initData()
{
$block = zdTable('block');
- $block->id->range('2');
- $block->account->range('test');
- $block->vision->range('rnd');
- $block->module->range('test');
- $block->title->prefix('区块')->range('2');
- $block->order->range('5');
+ $block->id->range('2-5');
+ $block->account->range('admin');
+ $block->vision->range('rnd,lite');
+ $block->dashboard->range('my');
+ $block->module->range('project');
+ $block->code->range('list,statistic');
+ $block->title->prefix('区块名称')->range('2-5');
+ $block->order->range('1-4');
- $block->gen(1);
+ $block->gen(4);
}
/**
@@ -24,18 +26,22 @@ title=测试 block 模块的update 方法
timeout=0
cid=39
-- 执行block模块的getByID方法,参数是$newBlockID
- - 属性account @admin
- - 属性vision @rnd
- - 属性module @my
- - 属性title @区块123
- - 属性source @my
- - 属性block @bug
- - 属性order @5
+- 测试获取正常的block的内容
+ - 属性account @admin2
+ - 属性vision @lite
+ - 属性dashboard @scrumproject
+ - 属性module @project
+ - 属性code @statistic
+ - 属性title @项目统计区块
+ - 属性order @1
-- 执行blockTest模块的create方法,参数是$accoutTooLangBlock,属性account @『所属用户』长度应当不超过『30』,且大于『0』。
+- 测试所属模块为空 @『所属模块』不能为空。
+- 测试所属区块为空 @『区块』不能为空。
+- 测试区块名称为空 @『区块名称』不能为空。
+
+- 测试account 字段字符超出长度 @『所属用户』长度应当不超过『30』,且大于『0』。
*/
@@ -44,25 +50,43 @@ $tester->loadModel('block');
initData();
-$newBlock = new stdclass();
-$newBlock->id = '2';
-$newBlock->account = 'newadmin';
-$newBlock->vision = 'lite';
-$newBlock->module = 'newmy';
-$newBlock->title = 'new区块';
-$newBlock->params = '';
-$newBlock->order = '5';
+$block = new stdclass();
+$block->id = '2';
+$block->account = 'admin2';
+$block->vision = 'lite';
+$block->dashboard = 'scrumproject';
+$block->module = 'project';
+$block->code = 'statistic';
+$block->title = '项目统计区块';
+$block->order = '1';
-$accoutTooLangBlock = new stdclass();
-$accoutTooLangBlock->id = '2';
-$accoutTooLangBlock->account = 'adminadminadminadminadminadminadminadmin1';
-$accoutTooLangBlock->vision = 'rnd';
-$accoutTooLangBlock->module = 'my';
-$accoutTooLangBlock->title = 'long account';
-$accoutTooLangBlock->order = '5';
+$accountTooLangBlock = new stdclass();
+$accountTooLangBlock->id = '3';
+$accountTooLangBlock->account = 'adminadminadminadminadminadminadminadmin1';
+$accountTooLangBlock->vision = 'rnd';
+$accountTooLangBlock->dashboard = 'my';
+$accountTooLangBlock->module = 'project';
+$accountTooLangBlock->code = 'statistic';
+$accountTooLangBlock->title = '项目统计区块2';
+$accountTooLangBlock->order = '2';
+
+$emptyModuleBlock = new stdclass();
+$emptyModuleBlock->id = '4';
+$emptyModuleBlock->module = '';
+
+$emptyCodeBlock = new stdclass();
+$emptyCodeBlock->id = '4';
+$emptyCodeBlock->code = '';
+
+$emptyTitleBlock = new stdclass();
+$emptyTitleBlock->id = '4';
+$emptyTitleBlock->title = '';
$blockTest = new blockTest();
-$newBlockID = $blockTest->updateTest($newBlock);
+$newBlockID = $blockTest->updateTest($block);
-r($tester->block->getByID($newBlockID)) && p('account,vision,module,title,order') && e("newadmin,lite,newmy,new区块,5"); // 测试获取正常的block的内容
-r($blockTest->updateTest($accoutTooLangBlock)) && p('account:0') && e('『所属用户』长度应当不超过『30』,且大于『0』。'); // 测试account 字段字符超出长度
+r($tester->block->getByID($newBlockID)) && p('account,vision,dashboard,module,code,title,order') && e("admin2,lite,scrumproject,project,statistic,项目统计区块,1"); // 测试获取正常的block的内容
+r($blockTest->updateTest($emptyModuleBlock)) && p('module:0') && e('『所属模块』不能为空。'); // 测试所属模块为空
+r($blockTest->updateTest($emptyCodeBlock)) && p('code:0') && e('『区块』不能为空。'); // 测试所属区块为空
+r($blockTest->updateTest($emptyTitleBlock)) && p('title:0') && e('『区块名称』不能为空。'); // 测试区块名称为空
+r($blockTest->updateTest($accountTooLangBlock)) && p('account:0') && e('『所属用户』长度应当不超过『30』,且大于『0』。'); // 测试account 字段字符超出长度
\ No newline at end of file
diff --git a/module/block/test/tao/fetchmyblocks.php b/module/block/test/tao/fetchmyblocks.php
new file mode 100644
index 0000000000..15b3eff80f
--- /dev/null
+++ b/module/block/test/tao/fetchmyblocks.php
@@ -0,0 +1,34 @@
+#!/usr/bin/env php
+id->range('2-5');
+ $block->account->range('admin');
+ $block->vision->range('rnd,lite');
+ $block->dashboard->range('my,qa,project');
+ $block->title->prefix('区块')->range('2-5');
+ $block->order->range('5-2');
+
+ $block->gen(4);
+}
+
+/**
+
+title=blockTao->fetchMyBlocks();
+timeout=0
+cid=2
+
+*/
+$tester->loadModel('block');
+
+initData();
+
+r(count($tester->block->fetchMyBlocks('my'))) && p('') && e('1'); // 查询admin用户在我的地盘仪表盘的区块列表数量
+r($tester->block->fetchMyBlocks('my')) && p('2:title') && e('区块2'); // 查询admin用户在我的地盘仪表盘的区块标题第2条的title属性
+r(count($tester->block->fetchMyBlocks('my', 1))) && p('') && e('0'); // 查询admin用户在我的地盘仪表盘的隐藏区块列表数量
+r(count($tester->block->fetchMyBlocks('asdas?'))) && p('') && e('0'); // 查询admin用户在不存在仪表盘的区块列表数量
+r($tester->block->fetchMyBlocks('my')) && p('2:vision') && e('rnd'); // 查询admin用户在我的地盘仪表盘区块的vision第2条的vision属性
diff --git a/module/block/ui/productstatisticblock.html.php b/module/block/ui/productstatisticblock.html.php
new file mode 100644
index 0000000000..8cdcdc66f1
--- /dev/null
+++ b/module/block/ui/productstatisticblock.html.php
@@ -0,0 +1,289 @@
+
+* @package block
+* @link https://www.zentao.net
+*/
+
+namespace zin;
+
+/**
+ * 获取区块左侧的产品列表.
+ * Get product tabs on the left side.
+ *
+ * @param array $products
+ * @param string $blockNavCode
+ * @access public
+ * @return array
+ */
+function getProductTabs($products, $blockNavCode): array
+{
+ $navTabs = array();
+ $selected = key($products);
+ foreach($products as $product)
+ {
+ $navTabs[] = li
+ (
+ set('class', 'nav-item' . ($product->id == $selected ? ' active' : '')),
+ a
+ (
+ set('class', 'ellipsis'),
+ set('data-toggle', 'tab'),
+ set('href', "#tab3{$blockNavCode}Content{$product->id}"),
+ $product->name
+
+ ),
+ a
+ (
+ set('class', 'link flex-1 text-right hidden'),
+ set('href', helper::createLink('product', 'browse', "productID=$product->id")),
+ icon
+ (
+ set('class', 'rotate-90 text-primary'),
+ 'export'
+ )
+ )
+ );
+ }
+ return $navTabs;
+}
+
+/**
+ * 获取区块右侧显示的项目信息.
+ * Get product statistical information.
+ *
+ * @param object $products
+ * @param string $blockNavID
+ * @access public
+ * @return array
+ */
+function getProductInfo($products, $blockNavID): array
+{
+ global $lang;
+
+ $selected = key($products);
+ $tabItems = array();
+ foreach($products as $product)
+ {
+ $tabItems[] = div
+ (
+ set('class', 'tab-pane' . ($product->id == $selected ? ' active' : '')),
+ set('id', "tab3{$blockNavID}Content{$product->id}"),
+ div
+ (
+ set('class', 'flex'),
+ cell
+ (
+ set('width', '68%'),
+ div
+ (
+ set('class', 'flex'),
+ cell
+ (
+ set('width', '45%'),
+ set('class', 'px-3 py-2'),
+ div
+ (
+ set('class', 'mx-6 my-4 bg-primary aspect-square text-center align-middle'),
+ span('需求交付率')
+ ),
+ div
+ (
+ set('class', 'flex'),
+ cell
+ (
+ set('class', 'flex-1 text-center'),
+ div(span('8073')),
+ div(span('BUG总数'))
+ ),
+ cell
+ (
+ set('class', 'flex-1 text-center'),
+ div(span('6549')),
+ div(span('已关闭'))
+ ),
+ cell
+ (
+ set('class', 'flex-1 text-center'),
+ div(span('1542')),
+ div(span('未关闭'))
+ )
+ )
+ ),
+ cell
+ (
+ set('width', '55%'),
+ set('class', 'py-2'),
+ div
+ (
+ set('class', 'py-2'),
+ span('BUG统计')
+ ),
+ div
+ (
+ set('class', 'flex border-r py-1'),
+ cell
+ (
+ div(set('class', 'py-1'), span('昨日新增'), span(set('class', 'ml-1'), '12')),
+ div(set('class', 'py-1'), span('今日新增'), span(set('class', 'ml-1'), '6')),
+ ),
+ cell
+ (
+ set('class', 'flex-1 px-3'),
+ div
+ (
+ set('class', 'py-1'),
+ div
+ (
+ set('class', 'progress'),
+ div
+ (
+ set('class', 'progress-bar'),
+ set('role', 'progressbar'),
+ setStyle(['width' => '36%']),
+ )
+ )
+ ),
+ div
+ (
+ set('class', 'py-1'),
+ div
+ (
+ set('class', 'progress'),
+ div
+ (
+ set('class', 'progress-bar'),
+ set('role', 'progressbar'),
+ setStyle(['width' => '18%']),
+ )
+ )
+ )
+ )
+ ),
+ div
+ (
+ set('class', 'flex border-r py-1'),
+ cell
+ (
+ div(set('class', 'py-1'), span('昨日解决'), span(set('class', 'ml-1'), '36')),
+ div(set('class', 'py-1'), span('今日解决'), span(set('class', 'ml-1'), '12')),
+ ),
+ cell
+ (
+ set('class', 'flex-1 px-3'),
+ div
+ (
+ set('class', 'py-1'),
+ div
+ (
+ set('class', 'progress'),
+ div
+ (
+ set('class', 'progress-bar'),
+ set('role', 'progressbar'),
+ setStyle(['width' => '84%']),
+ )
+ )
+ ),
+ div
+ (
+ set('class', 'py-1'),
+ div
+ (
+ set('class', 'progress'),
+ div
+ (
+ set('class', 'progress-bar'),
+ set('role', 'progressbar'),
+ setStyle(['width' => '28%']),
+ )
+ )
+ )
+ )
+ ),
+ div
+ (
+ set('class', 'flex border-r py-1'),
+ cell
+ (
+ div(set('class', 'py-1'), span('昨日关闭'), span(set('class', 'ml-1'), '24')),
+ div(set('class', 'py-1'), span('今日关闭'), span(set('class', 'ml-1'), '12')),
+ ),
+ cell
+ (
+ set('class', 'flex-1 px-3'),
+ div
+ (
+ set('class', 'py-1'),
+ div
+ (
+ set('class', 'progress'),
+ div
+ (
+ set('class', 'progress-bar'),
+ set('role', 'progressbar'),
+ setStyle(['width' => '60%']),
+ )
+ )
+ ),
+ div
+ (
+ set('class', 'py-1'),
+ div
+ (
+ set('class', 'progress'),
+ div
+ (
+ set('class', 'progress-bar'),
+ set('role', 'progressbar'),
+ setStyle(['width' => '30%']),
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ ),
+ cell
+ (
+ set('width', '32%'),
+ 123
+ )
+ )
+ );
+ }
+ return $tabItems;
+}
+
+$blockNavCode = 'nav-' . uniqid();
+div
+(
+ set('class', 'productstatistic-block'),
+ div
+ (
+ set('class', 'flex'),
+ cell
+ (
+ set('width', '25%'),
+ set('class', 'of-hidden bg-secondary-pale'),
+ ul
+ (
+ set('class', 'nav nav-tabs nav-stacked'),
+ getProductTabs($products, $blockNavCode)
+ ),
+ ),
+ cell
+ (
+ set('class', 'tab-content'),
+ set('width', '75%'),
+ getProductInfo($products, $blockNavCode)
+ )
+ )
+);
+
+render();
diff --git a/module/block/ui/projectstatisticblock.html.php b/module/block/ui/projectstatisticblock.html.php
index 96a93ba55e..01e7b99a49 100644
--- a/module/block/ui/projectstatisticblock.html.php
+++ b/module/block/ui/projectstatisticblock.html.php
@@ -1,7 +1,7 @@
@@ -14,9 +14,9 @@ namespace zin;
/**
* 获取区块左侧的项目列表.
* Get project tabs on the left side.
- *
- * @param array $projects
- * @param string $blockNavCode
+ *
+ * @param array $projects
+ * @param string $blockNavCode
* @access public
* @return array
*/
@@ -54,10 +54,10 @@ function getProjectTabs($projects, $blockNavCode): array
/**
* 获取区块右侧显示的项目信息.
- * Get project statistical information.
- *
- * @param object $projects
- * @param string $blockNavID
+ * Get project statistical information.
+ *
+ * @param object $projects
+ * @param string $blockNavID
* @access public
* @return array
*/
@@ -80,8 +80,8 @@ function getProjectInfo($projects, $blockNavID): array
/**
* 获取敏捷类项目的统计信息.
* Get scrum project info.
- *
- * @param object $project
+ *
+ * @param object $project
* @access public
* @return void
*/
@@ -89,7 +89,7 @@ function getScrumProjectInfo($project)
{
global $lang;
- $scrumProjectInfo = div
+ return div
(
/* 区块右侧顶部的项目概况。 */
div
@@ -158,14 +158,13 @@ function getScrumProjectInfo($project)
getProjectStatisticItems($project)
)
);
- return $scrumProjectInfo;
}
/**
* 获取项目的统计项.
* get project statistic items.
- *
- * @param object $project
+ *
+ * @param object $project
* @access public
* @return array
*/
@@ -233,7 +232,7 @@ function getWaterfallProjectInfo($project)
{
global $app, $lang;
$isChineseLang = in_array($app->getClientLang(), array('zh-cn','zh-tw'));
- $waterfallProjectInfo = div
+ return div
(
/* 瀑布项目展示概况。 */
set('class', 'weekly-row'),
@@ -343,7 +342,6 @@ function getWaterfallProjectInfo($project)
)
)
);
- return $waterfallProjectInfo;
}
$blockNavCode = 'nav-' . uniqid();
diff --git a/module/block/ui/recentprojectblock.html.php b/module/block/ui/recentprojectblock.html.php
index 2e6d548b57..1e32c9fe2f 100644
--- a/module/block/ui/recentprojectblock.html.php
+++ b/module/block/ui/recentprojectblock.html.php
@@ -18,7 +18,7 @@ foreach($projects as $projectID => $project)
$cards[] = cell
(
set('width', '33%'),
- set('class', 'border m-2 p-4'),
+ set('class', 'border m-2 p-4'),
div
(
set('class', 'pb-2'),
diff --git a/module/block/zen.php b/module/block/zen.php
index 40cc9bcf61..fd370c665a 100644
--- a/module/block/zen.php
+++ b/module/block/zen.php
@@ -1118,9 +1118,7 @@ class blockZen extends block
$this->loadModel('weekly');
$this->app->loadLang('execution');
- $projectID = $this->session->project;
- $project = $this->loadModel('project')->getByID($projectID);
-
+ $projectID = $this->session->project;
$projectWeekly = $this->dao->select('*')->from(TABLE_WEEKLYREPORT)->where('project')->eq($projectID)->orderBy('weekStart_asc')->fetchAll('weekStart');
$charts['PV'] = '[';
diff --git a/module/bug/tao.php b/module/bug/tao.php
index 4cccf81dc0..b9248ff9b2 100644
--- a/module/bug/tao.php
+++ b/module/bug/tao.php
@@ -225,14 +225,11 @@ class bugTao extends bugModel
* @param int $bugID
* @param string $linkBug
* @param string $oldLinkBug
- * @access private
+ * @access protected
* @return bool
*/
- private function updateLinkBug(int $bugID, string $linkBug, string $oldLinkBug): bool
+ protected function updateLinkBug(int $bugID, string $linkBug, string $oldLinkBug): bool
{
-
- return false;
-
$linkBugs = explode(',', $linkBug);
$oldLinkBugs = explode(',', $oldLinkBug);
$addedLinkBugs = array_diff($linkBugs, $oldLinkBugs);
@@ -242,19 +239,21 @@ class bugTao extends bugModel
foreach($changedLinkBugs as $changedBugID => $linkBugs)
{
- if(in_array($changeBugID, $addedLinkBugs))
+ if(in_array($changedBugID, $addedLinkBugs))
{
$currentLinkBug = $bugID;
- if(!empty($linkBugs)) $currentLinkBug = trim($linkBugs, ',') . ',' . $bugID;
+ $linkBugs = explode(',', $linkBugs);
+ if(!empty($linkBugs) && !in_array($bugID, $linkBugs)) $linkBugs[] = $bugID;
}
else
{
$linkBugs = explode(',', $linkBugs);
unset($linkBugs[array_search($bugID, $linkBugs)]);
- $currentLinkBug = implode(',', $linkBugs);
}
- $this->dao->update(TABLE_BUG)->set('linkBug')->eq($linkBug)->where('id')->eq($changeBugID)->exec();
+ $currentLinkBug = implode(',', array_filter($linkBugs));
+
+ $this->dao->update(TABLE_BUG)->set('linkBug')->eq($currentLinkBug)->where('id')->eq($changedBugID)->exec();
}
return !dao::isError();
diff --git a/module/bug/test/bug.class.php b/module/bug/test/bug.class.php
index 084419b479..d494431892 100644
--- a/module/bug/test/bug.class.php
+++ b/module/bug/test/bug.class.php
@@ -2135,4 +2135,30 @@ class bugTest
return $ids;
}
}
+
+ /**
+ * The test for updatelinkbug function.
+ *
+ * @param string $bugID
+ * @param string $linkBug
+ * @param string $oldLinkBug
+ * @access public
+ * @return array
+ */
+ public function updateLinkBugTest($bugID, $linkBug, $oldLinkBug)
+ {
+ $this->objectModel->updateLinkBug($bugID, $linkBug, $oldLinkBug);
+
+ $linkBugs = explode(',', $linkBug);
+ $oldLinkBugs = explode(',', $oldLinkBug);
+ $addedLinkBugs = array_diff($linkBugs, $oldLinkBugs);
+ $removedLinkBugs = array_diff($oldLinkBugs, $linkBugs);
+ $allRelatedLinkBugs = array_merge($addedLinkBugs, $removedLinkBugs, array($bugID));
+
+ global $tester;
+ $linkBugPairs = $tester->dao->select('id,linkBug')->from(TABLE_BUG)->where('id')->in(array_filter($allRelatedLinkBugs))->andWhere('deleted')->eq('0')->fetchPairs();
+
+ if(dao::isError()) return dao::getError();
+ return $linkBugPairs;
+ }
}
diff --git a/module/bug/test/model/update.php b/module/bug/test/model/update.php
index a2601b1843..2c977226b4 100755
--- a/module/bug/test/model/update.php
+++ b/module/bug/test/model/update.php
@@ -42,6 +42,18 @@ cid=1
- 测试不更改bug类型 @没有数据更新
+- 测试不输入Bug标题 @『Bug标题』不能为空。
+
+- 测试通知邮件不合法 @『通知邮箱』应当为合法的EMAIL。
+
+- 测试解决者不为空时,不输入解决方案 @『解决方案』不能为空。
+
+- 测试由谁关闭不为空时,不输入解决方案 @『解决方案』不能为空。
+
+- 测试解决方案为重复Bug时,不输入重复Bug值 @『重复Bug』不能为空。
+
+- 测试解决方案为已修复时,不输入解决版本 @『解决版本』不能为空。
+
*/
@@ -50,13 +62,25 @@ initData();
$bugIdList = array('1', '2');
-$t_uptitle = array('title' => 'john');
-$t_uptype = array('type' => 'config');
-$t_untitle = array('title' => 'john');
-$t_untype = array('type' => 'config');
+$t_uptitle = array('title' => 'john');
+$t_uptype = array('type' => 'config');
+$t_untitle = array('title' => 'john');
+$t_untype = array('type' => 'config');
+$t_titleRequire = array('title' => '');
+$t_unnotifyEmail = array('notifyEmail' => '123');
+$t_resolution1 = array('resolvedBy' => 'john', 'resolution' => '');
+$t_resolution2 = array('closedBy' => 'john', 'resolution' => '');
+$t_unduplicateBug = array('resolution' => 'duplicate', 'duplicateBug' => '');
+$t_unresolvedBuild = array('resolution' => 'fixed', 'resolvedBuild' => '');
$bug = new bugTest();
-r($bug->updateObject($bugIdList[0], $t_uptitle)) && p('0:field,old,new') && e('title,BUG1,john'); // 测试更新bug名称
-r($bug->updateObject($bugIdList[0], $t_uptype)) && p('0:field,old,new') && e('type,codeerror,config'); // 测试更新bug类型
-r($bug->updateObject($bugIdList[0], $t_untitle)) && p() && e('没有数据更新'); // 测试不更改bug名称
-r($bug->updateObject($bugIdList[0], $t_untype)) && p() && e('没有数据更新'); // 测试不更改bug类型
\ No newline at end of file
+r($bug->updateObject($bugIdList[0], $t_uptitle)) && p('0:field,old,new') && e('title,BUG1,john'); // 测试更新bug名称
+r($bug->updateObject($bugIdList[0], $t_uptype)) && p('0:field,old,new') && e('type,codeerror,config'); // 测试更新bug类型
+r($bug->updateObject($bugIdList[0], $t_untitle)) && p() && e('没有数据更新'); // 测试不更改bug名称
+r($bug->updateObject($bugIdList[0], $t_untype)) && p() && e('没有数据更新'); // 测试不更改bug类型
+r($bug->updateObject($bugIdList[0], $t_titleRequire)) && p('title:0') && e('『Bug标题』不能为空。'); // 测试不输入Bug标题
+r($bug->updateObject($bugIdList[0], $t_unnotifyEmail)) && p('notifyEmail:0') && e('『通知邮箱』应当为合法的EMAIL。'); // 测试通知邮件不合法
+r($bug->updateObject($bugIdList[0], $t_resolution1)) && p('resolution:0') && e('『解决方案』不能为空。'); // 测试解决者不为空时,不输入解决方案
+r($bug->updateObject($bugIdList[0], $t_resolution2)) && p('resolution:0') && e('『解决方案』不能为空。'); // 测试由谁关闭不为空时,不输入解决方案
+r($bug->updateObject($bugIdList[0], $t_unduplicateBug)) && p('duplicateBug:0') && e('『重复Bug』不能为空。'); // 测试解决方案为重复Bug时,不输入重复Bug值
+r($bug->updateObject($bugIdList[0], $t_unresolvedBuild)) && p('resolvedBuild:0') && e('『解决版本』不能为空。'); // 测试解决方案为已修复时,不输入解决版本
\ No newline at end of file
diff --git a/module/bug/test/tao/data/bug_updatelinkbug.yaml b/module/bug/test/tao/data/bug_updatelinkbug.yaml
new file mode 100644
index 0000000000..ce1e65fe58
--- /dev/null
+++ b/module/bug/test/tao/data/bug_updatelinkbug.yaml
@@ -0,0 +1,128 @@
+---
+fields:
+- field: id
+ range: 1-5
+- field: project
+ range: 0-5
+- field: product
+ range: 1-5
+- field: branch
+ range: 0-1
+- field: module
+ range: 1821-1823,1825-1827,1831-1833,0{1000000}
+- field: execution
+ range: 0-5
+- field: plan
+ range: 1{3},4{3},7{3},0{1111111}
+- field: story
+ range: 2-400:4
+- field: storyVersion
+ range: 1
+- field: task
+ range: 0
+- field: toTask
+ range: 0
+- field: toStory
+ range: 0
+- field: title
+ range: 1-5
+ prefix: BUG
+- field: keywords
+ range: '[]'
+- field: severity
+ range: '[3]'
+- field: pri
+ range: '[3]'
+- field: type
+ range: '[codeerror]'
+- field: os
+ range: '[]{2},[win10,windows,android,ios]'
+- field: browser
+ range: '[]'
+- field: hardware
+ range: '[]'
+- field: found
+ range: '[]'
+- field: steps
+ range: '[【步骤】
【结果】
【期望】
,【步骤】进入成果展示
【结果】乱码
【期望】正常显示
]'
+- field: status
+ range: '[active]'
+- field: subStatus
+ range: '[]'
+- field: color
+ range: '[#3da7f5,#75c941,#2dbdb2,#797ec9,#ffaf38,#ff4e3e]'
+- field: confirmed
+ range: 0,1
+- field: activatedCount
+ range: 0
+- field: mailto
+ range: admin{100},[]{200}
+- field: openedBy
+ range: admin
+- field: openedDate
+ range: (-1M)-(+1w):-1D
+ type: timestamp
+ format: YYYY-MM-DD hh:mm:ss
+- field: openedBuild
+ range: 1-5
+- field: assignedTo
+ range: '[admin,dev1,test1]{30},[]{20},[admin,dev1,test1]{20},[]{10},closed{20}'
+- field: assignedDate
+ range: (-1M)-(+1w):-1D
+ type: timestamp
+ format: YYYY-MM-DD
+- field: deadline
+ range: (-1M)-(+1w):-1D
+ type: timestamp
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: YYYY-MM-DD
+- field: resolvedBy
+ range: '[]{50},$assignedTo{30},admin{20}'
+- field: resolution
+ range: '[]{50},bydesign{5},duplicate{5},external{5},fixed{5},notrepro{2},postponed{3},willnotfix{5},fixed{10},bydesign,external,notrepro,postponed,willnotfix,duplicate{5}'
+- field: resolvedBuild
+ range: '[]{55},trunk{15},[]{25},trunk{5}'
+- field: resolvedDate
+ range: (+1w)-(-2w):-1D
+ type: timestamp
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: YYYY-MM-DD
+- field: closedBy
+ range: '[]{50},admin{30}'
+- field: closedDate
+ range: ~
+- field: duplicateBug
+ range: 0{55},1-5,0{40},10-15
+- field: linkBug
+ range: ~
+- field: case
+ range: 0
+- field: caseVersion
+ range: 0
+- field: result
+ range: 0
+- field: repo
+ range: 0
+- field: entry
+ range: ~
+- field: lines
+ range: ~
+- field: v1
+ range: ~
+- field: v2
+ range: ~
+- field: repoType
+ range: ~
+- field: testtask
+ range: 0
+- field: lastEditedBy
+ range: ~
+- field: lastEditedDate
+ range: ~
+- field: deleted
+ range: 0{40},1{10},0{50}
+...
diff --git a/module/bug/test/tao/data/sql/bug.sql b/module/bug/test/tao/data/sql/bug.sql
new file mode 100644
index 0000000000..be592d58e5
--- /dev/null
+++ b/module/bug/test/tao/data/sql/bug.sql
@@ -0,0 +1,120 @@
+-- MySQL dump 10.13 Distrib 8.0.32, for Linux (x86_64)
+--
+-- Host: 127.0.0.1 Database: zentaopms184
+-- ------------------------------------------------------
+-- Server version 8.0.32-0ubuntu0.22.04.2
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!50503 SET NAMES utf8mb4 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `zt_bug`
+--
+
+DROP TABLE IF EXISTS `zt_bug`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `zt_bug` (
+ `id` mediumint NOT NULL AUTO_INCREMENT,
+ `project` mediumint unsigned NOT NULL DEFAULT '0',
+ `product` mediumint unsigned NOT NULL DEFAULT '0',
+ `injection` mediumint unsigned NOT NULL DEFAULT '0',
+ `identify` mediumint unsigned NOT NULL DEFAULT '0',
+ `branch` mediumint unsigned NOT NULL DEFAULT '0',
+ `module` mediumint unsigned NOT NULL DEFAULT '0',
+ `execution` mediumint unsigned NOT NULL DEFAULT '0',
+ `plan` mediumint unsigned NOT NULL DEFAULT '0',
+ `story` mediumint unsigned NOT NULL DEFAULT '0',
+ `storyVersion` smallint NOT NULL DEFAULT '1',
+ `task` mediumint unsigned NOT NULL DEFAULT '0',
+ `toTask` mediumint unsigned NOT NULL DEFAULT '0',
+ `toStory` mediumint NOT NULL DEFAULT '0',
+ `title` varchar(255) NOT NULL DEFAULT '',
+ `keywords` varchar(255) NOT NULL DEFAULT '',
+ `severity` tinyint NOT NULL DEFAULT '0',
+ `pri` tinyint unsigned NOT NULL DEFAULT '0',
+ `type` varchar(30) NOT NULL DEFAULT '',
+ `os` varchar(255) NOT NULL DEFAULT '',
+ `browser` varchar(255) NOT NULL DEFAULT '',
+ `hardware` varchar(30) NOT NULL DEFAULT '',
+ `found` varchar(30) NOT NULL DEFAULT '',
+ `steps` mediumtext,
+ `status` enum('active','resolved','closed') NOT NULL DEFAULT 'active',
+ `subStatus` varchar(30) NOT NULL DEFAULT '',
+ `color` char(7) NOT NULL DEFAULT '',
+ `confirmed` tinyint(1) NOT NULL DEFAULT '0',
+ `activatedCount` smallint NOT NULL DEFAULT '0',
+ `activatedDate` datetime DEFAULT NULL,
+ `feedbackBy` varchar(100) NOT NULL DEFAULT '',
+ `notifyEmail` varchar(100) NOT NULL DEFAULT '',
+ `mailto` text,
+ `openedBy` varchar(30) NOT NULL DEFAULT '',
+ `openedDate` datetime DEFAULT NULL,
+ `openedBuild` varchar(255) NOT NULL DEFAULT '',
+ `assignedTo` varchar(30) NOT NULL DEFAULT '',
+ `assignedDate` datetime DEFAULT NULL,
+ `deadline` date DEFAULT NULL,
+ `resolvedBy` varchar(30) NOT NULL DEFAULT '',
+ `resolution` varchar(30) NOT NULL DEFAULT '',
+ `resolvedBuild` varchar(30) NOT NULL DEFAULT '',
+ `resolvedDate` datetime DEFAULT NULL,
+ `closedBy` varchar(30) NOT NULL DEFAULT '',
+ `closedDate` datetime DEFAULT NULL,
+ `duplicateBug` mediumint unsigned NOT NULL DEFAULT '0',
+ `linkBug` varchar(255) NOT NULL DEFAULT '',
+ `case` mediumint unsigned NOT NULL DEFAULT '0',
+ `caseVersion` smallint NOT NULL DEFAULT '1',
+ `feedback` mediumint unsigned NOT NULL DEFAULT '0',
+ `result` mediumint unsigned NOT NULL DEFAULT '0',
+ `repo` mediumint unsigned NOT NULL DEFAULT '0',
+ `mr` mediumint unsigned NOT NULL DEFAULT '0',
+ `entry` text,
+ `lines` varchar(10) NOT NULL DEFAULT '',
+ `v1` varchar(40) NOT NULL DEFAULT '',
+ `v2` varchar(40) NOT NULL DEFAULT '',
+ `repoType` varchar(30) NOT NULL DEFAULT '',
+ `issueKey` varchar(50) NOT NULL DEFAULT '',
+ `testtask` mediumint unsigned NOT NULL DEFAULT '0',
+ `lastEditedBy` varchar(30) NOT NULL DEFAULT '',
+ `lastEditedDate` datetime DEFAULT NULL,
+ `deleted` enum('0','1') NOT NULL DEFAULT '0',
+ PRIMARY KEY (`id`),
+ KEY `product` (`product`),
+ KEY `execution` (`execution`),
+ KEY `status` (`status`),
+ KEY `plan` (`plan`),
+ KEY `story` (`story`),
+ KEY `case` (`case`),
+ KEY `toStory` (`toStory`),
+ KEY `result` (`result`),
+ KEY `assignedTo` (`assignedTo`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `zt_bug`
+--
+
+LOCK TABLES `zt_bug` WRITE;
+/*!40000 ALTER TABLE `zt_bug` DISABLE KEYS */;
+/*!40000 ALTER TABLE `zt_bug` ENABLE KEYS */;
+UNLOCK TABLES;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2023-05-08 10:24:51
diff --git a/module/bug/test/tao/data/sql/zt_bug_zd.sql b/module/bug/test/tao/data/sql/zt_bug_zd.sql
new file mode 100755
index 0000000000..0d06c4e5ee
--- /dev/null
+++ b/module/bug/test/tao/data/sql/zt_bug_zd.sql
@@ -0,0 +1,6 @@
+INSERT INTO zt_bug(`id`, `project`, `product`, `branch`, `module`, `execution`, `plan`, `story`, `storyVersion`, `task`, `toTask`, `toStory`, `title`, `keywords`, `severity`, `pri`, `type`, `os`, `browser`, `hardware`, `found`, `steps`, `status`, `subStatus`, `color`, `confirmed`, `activatedCount`, `mailto`, `openedBy`, `openedDate`, `openedBuild`, `assignedTo`, `assignedDate`, `deadline`, `resolvedBy`, `resolution`, `resolvedBuild`, `resolvedDate`, `closedBy`, `closedDate`, `duplicateBug`, `linkBug`, `case`, `caseVersion`, `result`, `repo`, `entry`, `lines`, `v1`, `v2`, `repoType`, `testtask`, `lastEditedBy`, `lastEditedDate`, `deleted`)
+ VALUES ('1', '0', '1', '0', '1821', '0', '1', '2', '1', '0', '0', '0', 'BUG1', '', '3', '3', 'codeerror', '', '', '', '', '【步骤】
【结果】
【期望】
', 'active', '', '#3da7f5', '0', '0', 'admin', 'admin', '2023-04-08 10:24:51', '1', 'admin', '2023-04-08', '2023-04-08', '', '', '', '2023-05-15', '', '', '0', '', '0', '0', '0', '0', '', '', '', '', '', '0', '', '', '0'),
+ ('2', '1', '2', '1', '1822', '1', '1', '6', '1', '0', '0', '0', 'BUG2', '', '3', '3', 'codeerror', '', '', '', '', '【步骤】进入成果展示
【结果】乱码
【期望】正常显示
', 'active', '', '#75c941', '1', '0', 'admin', 'admin', '2023-04-09 10:24:51', '2', 'admin', '2023-04-09', '2023-04-09', '', '', '', '2023-05-14', '', '', '0', '', '0', '0', '0', '0', '', '', '', '', '', '0', '', '', '0'),
+ ('3', '2', '3', '0', '1823', '2', '1', '10', '1', '0', '0', '0', 'BUG3', '', '3', '3', 'codeerror', 'win10', '', '', '', '【步骤】
【结果】
【期望】
', 'active', '', '#2dbdb2', '0', '0', 'admin', 'admin', '2023-04-10 10:24:51', '3', 'admin', '2023-04-10', '2023-04-10', '', '', '', '2023-05-13', '', '', '0', '', '0', '0', '0', '0', '', '', '', '', '', '0', '', '', '0'),
+ ('4', '3', '4', '1', '1825', '3', '4', '14', '1', '0', '0', '0', 'BUG4', '', '3', '3', 'codeerror', 'windows', '', '', '', '【步骤】进入成果展示
【结果】乱码
【期望】正常显示
', 'active', '', '#797ec9', '1', '0', 'admin', 'admin', '2023-04-11 10:24:51', '4', 'admin', '2023-04-11', '2023-04-11', '', '', '', '2023-05-12', '', '', '0', '', '0', '0', '0', '0', '', '', '', '', '', '0', '', '', '0'),
+ ('5', '4', '5', '0', '1826', '4', '4', '18', '1', '0', '0', '0', 'BUG5', '', '3', '3', 'codeerror', 'android', '', '', '', '【步骤】
【结果】
【期望】
', 'active', '', '#ffaf38', '0', '0', 'admin', 'admin', '2023-04-12 10:24:51', '5', 'admin', '2023-04-12', '2023-04-12', '', '', '', '2023-05-11', '', '', '0', '', '0', '0', '0', '0', '', '', '', '', '', '0', '', '', '0');
diff --git a/module/bug/test/tao/updatelinkbug.php b/module/bug/test/tao/updatelinkbug.php
new file mode 100755
index 0000000000..08ceaa8daa
--- /dev/null
+++ b/module/bug/test/tao/updatelinkbug.php
@@ -0,0 +1,53 @@
+#!/usr/bin/env php
+id->range('1-5');
+ $data->product->range('1-5');
+ $data->branch->range('0-1');
+ $data->project->range('0-5');
+ $data->execution->range('0-5');
+ $data->title->prefix("BUG")->range('1-5');
+ $data->openedBuild->range('1-5');
+ $data->type->range("[codeerror]");
+ $data->status->range("[active]");
+ $data->pri->range("[3]");
+ $data->severity->range("[3]");
+
+ $data->gen(5);
+}
+
+/**
+
+title=bugModel->updateLinkBug();
+timeout=0
+cid=1
+
+- 测试关联bug2的关联bug同步更新为1属性2 @1
+
+- 测试关联bug2的关联bug同步更新为空,bug3的关联bug为1
+ - 属性2 @~~
+ - 属性3 @1
+
+- 测试关联bug2的关联bug同步更新为1属性2 @1
+
+- 测试关联bug3的关联bug同步更新为1,2属性3 @1,2
+
+
+
+*/
+
+initData();
+
+$bugIDList = array(1, 2, 3);
+
+$bug = new bugTest();
+r($bug->updateLinkBugTest($bugIDList[0], '2', '')) && p('2', ';') && e('1'); //测试关联bug2的关联bug同步更新为1
+r($bug->updateLinkBugTest($bugIDList[0], '3', '2')) && p('2;3', ';') && e('~~;1'); //测试关联bug2的关联bug同步更新为空,bug3的关联bug为1
+r($bug->updateLinkBugTest($bugIDList[0], '2,3', '3')) && p('2') && e('1'); //测试关联bug2的关联bug同步更新为1
+r($bug->updateLinkBugTest($bugIDList[1], '1,3', '1')) && p('3', ';') && e('1,2'); //测试关联bug3的关联bug同步更新为1,2
\ No newline at end of file
diff --git a/module/bug/zen.php b/module/bug/zen.php
index 4a7af9d80a..2f3f1fc993 100644
--- a/module/bug/zen.php
+++ b/module/bug/zen.php
@@ -829,9 +829,11 @@ class bugZen extends bug
/* 获取影响版本列表和解决版本列表。*/
/* Get the openedBuilds and resolvedBuilds. */
+ $objectType = '';
+ if($bug->project) $objectType = 'project';
+ if($bug->execution) $objectType = 'execution';
+
$objectID = $bug->execution ? $bug->execution : $bug->project;
- $objectType = $bug->project ? 'project' : '';
- $objectType = $bug->execution ? 'execution' : $objectType;
$allBuilds = $this->loadModel('build')->getBuildPairs($bug->product, 'all', 'noempty');
$openedBuilds = $this->build->getBuildPairs($bug->product, $bug->branch, $params = 'noempty,noterminate,nodone,withbranch,noreleased', $objectID, $objectType, $bug->openedBuild);
$resolvedBuilds = $openedBuilds;
diff --git a/module/doc/control.php b/module/doc/control.php
index 78b9c1a7f8..ec3b3eb75d 100755
--- a/module/doc/control.php
+++ b/module/doc/control.php
@@ -380,7 +380,7 @@ class doc extends control
$libID = $this->post->lib;
$moduleID = $this->post->module;
if(empty($libID) and strpos($this->post->module, '_') !== false) list($libID, $moduleID) = explode('_', $this->post->module);
- setcookie('lastDocModule', $moduleID, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, false);
+ setcookie('lastDocModule', $moduleID, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
$docResult = $this->doc->create();
if(!$docResult or dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
@@ -1043,7 +1043,7 @@ class doc extends control
{
$this->loadModel('file');
if(empty($viewType)) $viewType = !empty($_COOKIE['docFilesViewType']) ? $this->cookie->docFilesViewType : 'list';
- setcookie('docFilesViewType', $viewType, $this->config->cookieLife, $this->config->webRoot, '', false, true);
+ setcookie('docFilesViewType', $viewType, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
$objects = $this->doc->getOrderedObjects($type, 'nomerge', $objectID);
list($libs, $libID, $object, $objectID, $objectDropdown) = $this->doc->setMenuByType($type, $objectID, 0);
@@ -1271,7 +1271,7 @@ class doc extends control
$docSpaceParam->moduleID = $moduleID;
$docSpaceParam->browseType = $browseType;
$docSpaceParam->param = $param;
- setCookie("docSpaceParam", json_encode($docSpaceParam), $this->config->cookieLife, $this->config->webRoot, '', false, true);
+ setCookie("docSpaceParam", json_encode($docSpaceParam), $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
if($moduleID) $libID = $this->tree->getById($moduleID)->root;
$isFirstLoad = $libID == 0 ? true : false;
diff --git a/module/doc/model.php b/module/doc/model.php
index 70a4125ddb..e627fc8987 100644
--- a/module/doc/model.php
+++ b/module/doc/model.php
@@ -255,7 +255,7 @@ class docModel extends model
->remove('uid,contactListMenu,libType')
->get();
- if(defined('IN_UPGRADE') and (($this->config->edition == 'open' and version_compare($this->config->version, '18.4.alpha1', '<')) or ($this->config->edition == 'biz' and version_compare($this->config->version, 'biz8.4.alpha1', '<')) or ($this->config->edition == 'max' and version_compare($this->config->version, 'max4.4.alpha1', '<')))) unset($lib->addedBy, $lib->addedDate);
+ if(defined('IN_UPGRADE') and (($this->config->edition == 'open' and version_compare($this->config->version, '18.4.alpha1', '<')) or ($this->config->edition == 'biz' and version_compare($this->config->version, 'biz8.4.alpha1', '<')) or ($this->config->edition == 'max' and version_compare($this->config->version, 'max4.4.alpha1', '<')))) unset($data->addedBy, $data->addedDate);
$this->app->loadLang('api');
diff --git a/module/product/config.php b/module/product/config.php
index 5d397e6828..9740d97fb5 100644
--- a/module/product/config.php
+++ b/module/product/config.php
@@ -13,7 +13,7 @@ if($config->systemMode == 'ALM') $config->product->custom->batchEditFields .= ',
$config->product->list = new stdclass();
$config->product->list->exportFields = 'id,program,line,name,manager,draftStories,activeStories,changedStories,reviewingStories,closedStories,storyCompleteRate,bugs,unResolvedBugs,assignToNullBugs,bugFixedRate,plans,releases';
-$config->product->showBranchMethod = 'browse,project';
+$config->product->showBranchMethod = ',browse,project,track,';
global $lang, $app;
$app->loadLang('story');
diff --git a/module/product/control.php b/module/product/control.php
index 57ac7e293a..f1b07d3c7d 100755
--- a/module/product/control.php
+++ b/module/product/control.php
@@ -43,29 +43,28 @@ class product extends control
/**
* Index page, to browse.
*
- * @param string $locate locate to browse page or not. If not, display all products.
- * @param int $productID
- * @param string $orderBy
- * @param int $recTotal
- * @param int $recPerPage
- * @param int $pageID
+ * @param string $locate auto|yes locate to browse page or not. If not, display all products.
+ * @param string $productID
* @access public
* @return void
*/
- public function index($locate = 'auto', $productID = 0, $status = 'noclosed', $orderBy = 'order_desc', $recTotal = 0, $recPerPage = 10, $pageID = 1)
+ public function index(string $locate = 'auto', string $productID = '0')
{
if($locate == 'yes') $this->locate($this->createLink($this->moduleName, 'browse'));
- if($this->app->getViewType() != 'mhtml') unset($this->lang->product->menu->index);
+ /* Check product id and get product branch. */
+ $productID = (int)$productID;
$productID = $this->product->saveVisitState($productID, $this->products);
$branch = (int)$this->cookie->preBranch;
+ /* Set Menu. */
+ if($this->app->getViewType() != 'mhtml') unset($this->lang->product->menu->index);
if($this->app->viewType == 'mhtml') $this->product->setMenu($productID, $branch);
+ /* Add create product button for view. */
if(common::hasPriv('product', 'create')) $this->lang->TRActions = html::a($this->createLink('product', 'create'), " " . $this->lang->product->create, '', "class='btn btn-primary'");
- $this->view->title = $this->lang->product->index;
- $this->view->position[] = $this->lang->product->index;
+ $this->view->title = $this->lang->product->index;
$this->display();
}
@@ -296,6 +295,7 @@ class product extends control
if($this->post->name)
{
+ /* 从POST中获取数据,并预处理数据。 */
$formConfig = $this->productZen->appendFlowFields($this->config->product->form->batchEdit, 'batch');
$data = form::data($formConfig);
$products = $this->productZen->prepareBatchEditExtras($data);
@@ -647,7 +647,7 @@ class product extends control
$programID = (int)$programID;
/* Set env data. */
- $this->productZen->setEnvAll();
+ $this->productZen->setMenu4All();
/* Generate statistics of products and program. */
$this->app->loadClass('pager', true);
diff --git a/module/product/model.php b/module/product/model.php
index d50484f001..6f5e348fc5 100755
--- a/module/product/model.php
+++ b/module/product/model.php
@@ -26,150 +26,28 @@ class productModel extends model
const STORY_TYPE_REQ = 'requirement';
/**
- * Get product module menu.
+ * 获取移动端1.5级导航。
+ * Get product drop menu in mobile.
*
- * @param array $products
- * @param int $productID
- * @param string $extra
- * @param string $branch
- * @param string $module
- * @param string $moduleType
+ * @param array $products
+ * @param int $productID
+ * @param string $extra
+ * @param string|int $branch
*
* @access public
* @return string
*/
- public function getModuleNav($products, $productID, $extra, $branch, $module = 0, $moduleType = '')
+ public function getMobileDropMenu(array $products, int $productID, string $extra = '', string|int $branch = ''): string
{
- $currentModule = $this->app->getModuleName();
- $currentMethod = $this->app->getMethodName();
+ list($locateModule, $locateMethod) = $this->productTao->computeLocate4DropMenu();
- /* init currentModule and currentMethod for report and story. */
- if($currentModule == 'story')
- {
- $storyMethods = ",track,create,batchcreate,batchclose,";
- if(strpos($storyMethods, "," . $currentMethod . ",") === false) $currentModule = 'product';
- if($currentMethod == 'view' || $currentMethod == 'change' || $currentMethod == 'review') $currentMethod = 'browse';
- }
- if($currentMethod == 'report') $currentMethod = 'browse';
-
- $selectHtml = $this->select($products, $productID, $currentModule, $currentMethod, $extra, $branch, $module, $moduleType);
-
- $pageNav = '';
- $isMobile = $this->app->viewType == 'mhtml';
- if($isMobile)
- {
- $pageNav = html::a(helper::createLink('product', 'index'), $this->lang->product->index) . $this->lang->colon;
- $pageNav .= $selectHtml;
- }
- else
- {
- $pageNav = $selectHtml;
- }
+ $selectHtml = $this->productTao->buildSelect4Mobile($products, $productID, $locateModule, $locateMethod, $extra, $branch);
+ $pageNav = html::a(helper::createLink('product', 'index'), $this->lang->product->index) . $this->lang->colon;
+ $pageNav .= $selectHtml;
return $pageNav;
}
- /**
- * Create the select code of products.
- *
- * @param array $products
- * @param int $productID
- * @param string $currentModule
- * @param string $currentMethod
- * @param string $extra
- * @param int|string $branch
- * @param int $module
- * @param string $moduleType
- * @param bool $withBranch true|false
- *
- * @access public
- * @return string
- */
- public function select($products, $productID, $currentModule, $currentMethod, $extra = '', $branch = '', $module = 0, $moduleType = '', $withBranch = true)
- {
- $isQaModule = (strpos(',project,execution,', ",{$this->app->tab},") !== false and strpos(',bug,testcase,testtask,ajaxselectstory,', ",{$this->app->rawMethod},") !== false and isset($products[0])) ? true : false;
- $isFeedbackModel = strpos(',feedback,', ",{$this->app->tab},") !== false ? true : false;
- if(count($products) <= 2 and isset($products[0]))
- {
- unset($products[0]);
- $productID = key($products);
- }
-
- if(empty($products)) return;
-
- if($this->app->tab == 'project' and strpos(',zeroCase,browseUnits,groupCase,', ",$currentMethod,") !== false) $isQaModule = true;
-
- $this->app->loadLang('product');
- if(!$isQaModule and !$productID and !$isFeedbackModel)
- {
- unset($this->lang->product->menu->settings['subMenu']->branch);
- return;
- }
- $isMobile = $this->app->viewType == 'mhtml';
-
- $productID = $productID == 'all' ? 0 : $productID;
- setcookie("lastProduct", $productID, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
- if($productID) $currentProduct = $this->getById($productID);
-
- if($isQaModule and $this->app->tab == 'project')
- {
- if($this->app->tab == 'project') $extra = strpos(',testcase,groupCase,zeroCase,', ",$currentMethod,") !== false ? $extra : $this->session->project;
- if($this->app->tab == 'execution') $extra = $this->session->execution;
- }
-
- if($isQaModule and !$productID)
- {
- $currentProduct = new stdclass();
- $currentProduct->name = $products[$productID];
- $currentProduct->type = 'normal';
- }
- if($isFeedbackModel and !$productID)
- {
- $currentProduct = new stdclass();
- $currentProduct->name = isset($products[$productID]) ? $products[$productID] : current($products);
- $currentProduct->type = 'normal';
- }
- $this->session->set('currentProductType', $currentProduct->type);
-
- $output = '';
- if(!empty($products))
- {
- $moduleName = 'product';
- if($isQaModule) $moduleName = 'bug';
- if($isFeedbackModel) $moduleName = 'feedback';
- $dropMenuLink = helper::createLink($moduleName, 'ajaxGetDropMenu', "objectID=$productID&module=$currentModule&method=$currentMethod&extra=$extra");
- $output = "";
- if($isMobile) $output = "{$currentProduct->name} ";
-
- if($currentProduct->type == 'normal' || !$withBranch) unset($this->lang->product->menu->settings['subMenu']->branch);
- if($currentProduct->type != 'normal' && $currentModule != 'programplan' && $withBranch)
- {
- $this->lang->product->branch = sprintf($this->lang->product->branch, $this->lang->product->branchName[$currentProduct->type]);
- $this->lang->product->menu->settings['subMenu']->branch = str_replace('@branch@', $this->lang->product->branch, $this->lang->product->menu->settings['subMenu']->branch);
-
- $branches = $this->loadModel('branch')->getPairs($productID, 'all');
- $branchName = $branches[$branch];
- if(!$isMobile)
- {
- $dropMenuLink = helper::createLink('branch', 'ajaxGetDropMenu', "objectID=$productID&branch=$branch&module=$currentModule&method=$currentMethod&extra=$extra");
- $output .= "";
- }
- else
- {
- $output .= "{$branchName} ";
- }
- }
-
- if(!$isMobile) $output .= '';
- }
-
- return $output;
- }
-
/**
* Check privilege.
*
@@ -177,7 +55,7 @@ class productModel extends model
* @access public
* @return bool
*/
- public function checkPriv($productID)
+ public function checkPriv(int $productID): bool
{
if(empty($productID)) return false;
@@ -525,30 +403,19 @@ class productModel extends model
}
/*
+ * 获取1.5级导航数据。
* Get product switcher.
*
* @param int $productID
* @param string $extra
- * @param int|string $branch
+ * @param string|int $branch
* @access public
- * @return void
+ * @return string
*/
- public function getSwitcher($productID = 0, $extra = '', $branch = '')
+ public function getSwitcher(int $productID = 0, string $extra = '', string|int $branch = ''): string
{
- $currentModule = $this->app->moduleName;
- $currentMethod = $this->app->methodName;
-
- /* Init currentModule and currentMethod for report and story. */
- if($currentModule == 'story')
- {
- $storyMethods = ",create,batchcreate,batchclose,";
- if(strpos($storyMethods, "," . $currentMethod . ",") === false) $currentModule = 'product';
- if($currentMethod == 'view' or $currentMethod == 'change' or $currentMethod == 'review') $currentMethod = 'browse';
- }
- if($currentModule == 'testcase' and strpos(',view,edit,', ",$currentMethod,") !== false) $currentMethod = 'browse';
- if($currentModule == 'bug' and $currentMethod == 'edit') $currentMethod = 'browse';
- if($currentMethod == 'report') $currentMethod = 'browse';
-
+ /* 获取产品名称,产品类型。 */
+ $currentProduct = new stdclass();
$currentProductName = $this->lang->productCommon;
if($productID)
{
@@ -557,38 +424,21 @@ class productModel extends model
$this->session->set('currentProductType', $currentProduct->type);
}
- $fromModule = $this->app->tab == 'qa' ? 'qa' : '';
- $dropMenuLink = helper::createLink($this->app->tab == 'qa' ? 'product' : $this->app->tab, 'ajaxGetDropMenu', "objectID=$productID&module=$currentModule&method=$currentMethod&extra=$extra&from=$fromModule");
+ if($this->app->viewType == 'mhtml') return $this->getMobileDropMenu(array($productID => $currentProductName), $productID, $extra, $branch);
- if($this->app->viewType == 'mhtml' and $productID) return $this->getModuleNav(array($productID => $currentProductName), $productID, $extra, $branch);
+ /* Init locateModule and locateMethod for report and story. */
+ list($locateModule, $locateMethod) = $this->productTao->computeLocate4DropMenu();
+ /* 生成异步获取产品下拉菜单的链接。*/
+ $fromModule = $this->app->tab == 'qa' ? 'qa' : '';
+ $dropMenuModule = $this->app->tab == 'qa' ? 'product' : $this->app->tab;
+ $dropMenuLink = helper::createLink($dropMenuModule, 'ajaxGetDropMenu', "objectID=$productID&module=$locateModule&method=$locateMethod&extra=$extra&from=$fromModule");
+
+ /* 构建产品1.5级导航数据。 */
$output = "";
-
- $notNormalProduct = (isset($currentProduct->type) and $currentProduct->type != 'normal');
- if($notNormalProduct)
- {
- $isShowBranch = false;
- if($currentModule == 'product' and $currentMethod == 'track') $isShowBranch = true;
- if($currentModule == 'tree' and $currentMethod == 'browse') $isShowBranch = true;
- if($currentModule == 'product' and strpos($this->config->product->showBranchMethod, $currentMethod) !== false) $isShowBranch = true;
- if($this->app->tab == 'qa' and strpos(',testsuite,testreport,testtask,', ",$currentModule,") === false) $isShowBranch = true;
- if($this->app->tab == 'qa' and $currentModule == 'testtask' and strpos(',create,edit,browseunits,importunitresult,unitcases,', ",$currentMethod,") === false) $isShowBranch = true;
- if($currentModule == 'testcase' and $currentMethod == 'showimport') $isShowBranch = false;
- if($currentModule == 'release' and strpos(',browse,create,', $currentMethod) !== false) $isShowBranch = true;
- if($isShowBranch)
- {
- $this->lang->product->branch = sprintf($this->lang->product->branch, $this->lang->product->branchName[$currentProduct->type]);
- $branches = $this->loadModel('branch')->getPairs($productID, 'all');
- $branchName = isset($branches[$branch]) ? $branches[$branch] : $branches[0];
- $dropMenuLink = helper::createLink('branch', 'ajaxGetDropMenu', "objectID=$productID&branch=$branch&module=$currentModule&method=$currentMethod&extra=$extra");
-
- $output .= "";
- }
- }
+ $output .= $this->productTao->getBranchSelect4PC($currentProduct, $branch, $locateModule, $locateMethod, $extra);
return $output;
}
@@ -1272,7 +1122,7 @@ class productModel extends model
/**
* 获取产品路线图数据。
- * Get roadmap of a proejct.
+ * Get roadmap of product.
*
* @param int $productID
* @param string $branch all|0|1
@@ -1282,85 +1132,8 @@ class productModel extends model
*/
public function getRoadmap(int $productID, string $branch = '0', int $count = 0): array
{
- $plans = $this->loadModel('productplan')->getList($productID, $branch);
- $releases = $this->loadModel('release')->getList($productID, $branch);
- $roadmap = array();
- $total = 0;
-
- $parents = array();
- $orderedPlans = array();
- foreach($plans as $planID => $plan)
- {
- if($plan->parent == '-1')
- {
- $parents[$planID] = $plan->title;
- unset($plans[$planID]);
- continue;
- }
- if((!helper::isZeroDate($plan->end) and $plan->end < date('Y-m-d')) or $plan->end == '2030-01-01') continue;
- $orderedPlans[$plan->end][] = $plan;
- }
-
- krsort($orderedPlans);
- foreach($orderedPlans as $plans)
- {
- krsort($plans);
- foreach($plans as $plan)
- {
- if($plan->parent > 0 and isset($parents[$plan->parent])) $plan->title = $parents[$plan->parent] . ' / ' . $plan->title;
-
- $year = substr($plan->end, 0, 4);
- $branchIdList = explode(',', trim($plan->branch, ','));
- $branchIdList = array_unique($branchIdList);
- foreach($branchIdList as $branchID)
- {
- if($branchID === '') continue;
- $roadmap[$year][$branchID][] = $plan;
- }
- $total++;
-
- if($count > 0 and $total >= $count) return $this->processRoadmap($roadmap, $branch);
- }
- }
-
- $orderedReleases = array();
- foreach($releases as $release) $orderedReleases[$release->date][] = $release;
-
- krsort($orderedReleases);
- foreach($orderedReleases as $releases)
- {
- krsort($releases);
- foreach($releases as $release)
- {
- $year = substr($release->date, 0, 4);
- $branchIdList = explode(',', trim($release->branch, ','));
- $branchIdList = array_unique($branchIdList);
- foreach($branchIdList as $branchID)
- {
- if($branchID === '') continue;
- $roadmap[$year][$branchID][] = $release;
- }
- $total++;
-
- if($count > 0 and $total >= $count) return $this->processRoadmap($roadmap, $branch);
- }
- }
-
- if($count > 0) return $this->processRoadmap($roadmap, $branch);
-
- $groupRoadmap = array();
- foreach($roadmap as $year => $branchRoadmaps)
- {
- foreach($branchRoadmaps as $branch => $roadmaps)
- {
- $totalData = count($roadmaps);
- $rows = ceil($totalData / 8);
- $maxPerRow = ceil($totalData / $rows);
-
- $groupRoadmap[$year][$branch] = array_chunk($roadmaps, $maxPerRow);
- foreach($groupRoadmap[$year][$branch] as $row => $rowRoadmaps) krsort($groupRoadmap[$year][$branch][$row]);
- }
- }
+ /* Get group roadmap data. */
+ $groupRoadmap = $this->productTao->getGroupRoadmapData($productID, $branch, $count);
/* Get last 5 roadmap. */
$lastKeys = array_slice(array_keys($groupRoadmap), 0, 5);
@@ -1391,7 +1164,7 @@ class productModel extends model
* @access public
* @return array
*/
- public function processRoadmap($roadmapGroups, $branch)
+ public function processRoadmap($roadmapGroups, $branch): array
{
$newRoadmap = array();
foreach($roadmapGroups as $year => $branchRoadmaps)
@@ -2243,19 +2016,18 @@ class productModel extends model
if(empty($this->session->product)) $productID = (int)key($products);
}
+ if(isset($products[$productID])) return $productID;
+
/* 产品ID已经被删除,不存在于产品列表中。*/
/* Product ID does not exsit in products list, it may be deleted. */
- if(!isset($products[$productID]))
+ /* Confirm if product exist. */
+ $product = $this->product->getById($productID);
+ if(empty($product) or $product->deleted == 1) $productID = (int)key($products);
+ /* If product is invisable for curren user, then response access denied message. */
+ if($productID && !$this->checkPriv($productID))
{
- /* Confirm if product exist. */
- $product = $this->product->getById($productID);
- if(empty($product) or $product->deleted == 1) $productID = (int)key($products);
- /* If product is invisable for curren user, then response access denied message. */
- if($productID && strpos(",{$this->app->user->view->products},", ",{$productID},") === false)
- {
- $productID = (int)key($products);
- $this->accessDenied($this->lang->product->accessDenied);
- }
+ $productID = (int)key($products);
+ $this->accessDenied($this->lang->product->accessDenied);
}
return $productID;
@@ -2269,7 +2041,7 @@ class productModel extends model
* @access private
* @return void
*/
- public function accessDenied($tips)
+ public function accessDenied(string $tips)
{
if(defined('TUTORIAL')) return true;
@@ -2288,40 +2060,37 @@ class productModel extends model
* Set menu.
*
* @param int $productID
- * @param int|string $branch
- * @param int $module
- * @param string $moduleType
+ * @param string|int $branch all|''|int
* @param string $extra
* @access public
* @return void
*/
- public function setMenu($productID = 0, $branch = '', $module = 0, $moduleType = '', $extra = ''): void
+ public function setMenu(int $productID = 0, string|int $branch = '', string $extra = '')
{
- if(!$this->app->user->admin and strpos(",{$this->app->user->view->products},", ",$productID,") === false and $productID != 0 and !defined('TUTORIAL'))
- {
- $this->accessDenied($this->lang->product->accessDenied);
- return;
- }
-
- $product = $this->getByID($productID);
+ if(!defined('TUTORIAL') and $productID != 0 and !$this->checkPriv($productID)) return $this->accessDenied($this->lang->product->accessDenied);
+ /* 用真实数据替换导航配置的占位符,并删除无用配置项。 */
$params = array('branch' => $branch);
common::setMenuVars('product', $productID, $params);
+ if(strpos($extra, 'requirement') !== false) unset($this->lang->product->moreSelects['willclose']);
+
+ $product = $this->getByID($productID);
if(!$product) return;
+ /* 设置1.5级导航数据。*/
$this->lang->switcherMenu = $this->getSwitcher($productID, $extra, $branch);
+ /* 设置导航中分支的显示数据。*/
+ /* 如果产品类型是正常的,隐藏导航中分支的显示。*/
if($product->type == 'normal')
{
unset($this->lang->product->menu->settings['subMenu']->branch);
- }
- else
- {
- $branchLink = $this->lang->product->menu->settings['subMenu']->branch['link'];
- $this->lang->product->menu->settings['subMenu']->branch['link'] = str_replace('@branch@', $this->lang->product->branchName[$product->type], $branchLink);
- $this->lang->product->branch = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]);
+ return;
}
- if(strpos($extra, 'requirement') !== false) unset($this->lang->product->moreSelects['willclose']);
+ /* 如果产品类型是多分支、多平台的,将真实数据替换@branch@匹配符。*/
+ $branchLink = $this->lang->product->menu->settings['subMenu']->branch['link'];
+ $this->lang->product->menu->settings['subMenu']->branch['link'] = str_replace('@branch@', $this->lang->product->branchName[$product->type], $branchLink);
+ $this->lang->product->branch = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]);
}
}
diff --git a/module/product/tao.php b/module/product/tao.php
index 76d4c5ba05..d6cfcc22aa 100644
--- a/module/product/tao.php
+++ b/module/product/tao.php
@@ -431,27 +431,6 @@ class productTao extends productModel
return $products;
}
- /**
- * 格式化append参数,保证输出用逗号间隔的id列表。
- * Format append param.
- *
- * @param string|array append
- * @access protected
- * @return string
- */
- protected function formatAppendParam(string|array $append = ''): string
- {
- if(empty($append)) return '';
-
- if(is_string($append)) $append = explode(',', $append);
-
- $append = array_map(function($item){return (int)$item;}, $append);
- $append = array_unique(array_filter($append));
- sort($append);
-
- return implode(',', $append);
- }
-
/**
* 获取用于数据统计的研发需求和用户需求列表。
* Get dev stories and user requirements for statistics.
@@ -491,7 +470,121 @@ class productTao extends productModel
/* Story type is 'requirement'. */
if($storyType == static::STORY_TYPE_REQ) $stories = $requirements;
- return [$stories, $requirements];
+ return array($stories, $requirements);
+ }
+
+ /**
+ * 获取PC端分支下拉的HTML
+ * Get branch select for mobile
+ *
+ * @param object $product
+ * @param string|int $branch
+ * @param string $currentModule
+ * @param string $currentMethod
+ * @param string $extra
+ * @access private
+ * @return string
+ */
+ protected function getBranchSelect4PC(object $product, string|int $branch, string $currentModule, string $currentMethod, string $extra = ''): string
+ {
+ if(!isset($product->type) or $product->type == 'normal') return '';
+
+ /* 检测是否要显示分支。 */
+ $showBranch = false;
+ if($currentModule == 'testcase' and $currentMethod == 'showimport') $showBranch = false;
+ if($currentModule == 'tree' and $currentMethod == 'browse') $showBranch = true;
+ if($currentModule == 'product' and strpos($this->config->product->showBranchMethod, ",{$currentMethod},") !== false) $showBranch = true;
+ if($currentModule == 'release' and strpos(',browse,create,', ",{$currentMethod},") !== false) $showBranch = true;
+ if($this->app->tab == 'qa' and strpos(',testsuite,testreport,testtask,', ",$currentModule,") === false) $showBranch = true;
+ if($this->app->tab == 'qa' and $currentModule == 'testtask' and strpos(',create,edit,browseunits,importunitresult,unitcases,', ",$currentMethod,") === false) $showBranch = true;
+
+ if(!$showBranch) return '';
+
+ /* 生成异步请求地址。 */
+ $branches = $this->loadModel('branch')->getPairs($product->id, 'all');
+ $branchName = zget($branches, $branch, reset($branches));
+ $dropMenuLink = helper::createLink('branch', 'ajaxGetDropMenu', "objectID={$product->id}&branch=$branch&module=$currentModule&method=$currentMethod&extra=$extra");
+
+ /* 生成分支HTML代码。*/
+ $this->lang->product->branch = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]);
+ $output = "";
+ return $output;
+ }
+
+ /**
+ * 获取客户端分支下拉的HTML
+ * Get branch select for mobile
+ *
+ * @param object $product
+ * @param string $currentModule
+ * @param string $currentMethod
+ * @param string $extra
+ * @access private
+ * @return string
+ */
+ protected function getBranchSelect4Mobile(object $product, string|int $branch, string $currentModule, string $currentMethod, string $extra = ''): string
+ {
+ if(!isset($product->type) or $product->type == 'normal') return '';
+
+ /* 修正分支显示语言项。 */
+ $this->lang->product->branch = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]);
+ $this->lang->product->menu->settings['subMenu']->branch['link'] = str_replace('@branch@', $this->lang->product->branch, $this->lang->product->menu->settings['subMenu']->branch['link']);
+
+ /* 生成分支HTML代码。*/
+ $output = '';
+ $branches = $this->loadModel('branch')->getPairs($product->id, 'all');
+ $branchName = zget($branches, $branch, reset($branches));
+ if($branchName) $output .= "id}', '$currentModule', '$currentMethod', '$extra')\">{$branchName} ";
+
+ return $output;
+ }
+
+ /**
+ * 计算在点击1.5级导航下拉选项后,跳转的模块名和方法名。
+ * Compute locate for drop menu in PC.
+ *
+ * @access protected
+ * @return array
+ */
+ protected function computeLocate4DropMenu(): array
+ {
+ $currentModule = (string)$this->app->moduleName;
+ $currentMethod = (string)$this->app->methodName;
+
+ /* Init currentModule and currentMethod for report and story. */
+ if($currentModule == 'story')
+ {
+ if(strpos(",track,create,batchcreate,batchclose,", ",{$currentMethod},") === false) $currentModule = 'product';
+ if($currentMethod == 'view' or $currentMethod == 'change' or $currentMethod == 'review') $currentMethod = 'browse';
+ }
+ if($currentModule == 'testcase' and strpos(',view,edit,', ",$currentMethod,") !== false) $currentMethod = 'browse';
+ if($currentModule == 'bug' and $currentMethod == 'edit') $currentMethod = 'browse';
+ if($currentMethod == 'report') $currentMethod = 'browse';
+
+ return array($currentModule, $currentMethod);
+ }
+
+ /**
+ * 格式化append参数,保证输出用逗号间隔的id列表。
+ * Format append param.
+ *
+ * @param string|array append
+ * @access protected
+ * @return string
+ */
+ protected function formatAppendParam(string|array $append = ''): string
+ {
+ if(empty($append)) return '';
+
+ if(is_string($append)) $append = explode(',', $append);
+
+ $append = array_map(function($item){return (int)$item;}, $append);
+ $append = array_unique(array_filter($append));
+ sort($append);
+
+ return implode(',', $append);
}
/**
@@ -629,4 +722,237 @@ class productTao extends productModel
->orderBy($orderBy . 't2.order asc')
->fetchAll();
}
+
+ /**
+ * 构建移动端的下拉HTML。
+ * Create the select code of products.
+ *
+ * @param array $products
+ * @param int $productID
+ * @param string $currentModule
+ * @param string $currentMethod
+ * @param string $extra
+ * @param int|string $branch
+ * @param bool $withBranch true|false
+ * @access protected
+ * @return string
+ */
+ protected function buildSelect4Mobile(array $products, int $productID, string $currentModule, string $currentMethod, string $extra = '', string|int $branch = '', bool $withBranch = true): string
+ {
+ /* 处理数据。*/
+ if(isset($products[0])) unset($products[0]);
+ if(empty($products)) return '';
+ if(!isset($products[$productID])) $productID = (int)key($products);
+
+ /* 检测当前页面是否在项目或执行的测试二级导航中。*/
+ $isQaModule = (strpos(',project,execution,', ",{$this->app->tab},") !== false and stripos(',bug,testcase,testtask,ajaxselectstory,', ",{$this->app->rawMethod},") !== false) ? true : false;
+ if($this->app->tab == 'project' and stripos(',zeroCase,browseUnits,groupCase,', ",$currentMethod,") !== false) $isQaModule = true;
+ if($isQaModule)
+ {
+ if($this->app->tab == 'project') $extra = strpos(',testcase,groupCase,zeroCase,', ",$currentMethod,") !== false ? $extra : $this->session->project;
+ if($this->app->tab == 'execution') $extra = $this->session->execution;
+ }
+
+ /* 查询产品数据。*/
+ $currentProduct = $this->getById($productID);
+ $this->session->set('currentProductType', $currentProduct->type);
+
+ /* 生成异步获取下拉菜单的链接。*/
+ $moduleName = $isQaModule ? 'bug' : 'product';
+ if($this->app->tab == 'feedback') $moduleName = 'feedback';
+ $dropMenuLink = helper::createLink($moduleName, 'ajaxGetDropMenu', "objectID=$productID&module=$currentModule&method=$currentMethod&extra=$extra");
+
+ /* 构建产品1.5级导航代码。 */
+ $output = "{$currentProduct->name} ";
+
+ /* 处理分支。根据条件,判断是否追加分支1.5级导航代码。*/
+ if($currentProduct->type == 'normal' || !$withBranch) unset($this->lang->product->menu->settings['subMenu']->branch);
+ if($currentProduct->type != 'normal' && $withBranch && $currentModule != 'programplan') $output .= $this->getBranchSelect4Mobile($currentProduct, $branch, $currentModule, $currentMethod, $extra);
+ return $output;
+ }
+
+ /**
+ * 获取产品路线图的分组数据。
+ * Get group roadmap data of product.
+ *
+ * @param int $productID
+ * @param string $branch all|0|1
+ * @param int $count
+ * @access public
+ * @return array
+ */
+ protected function getGroupRoadmapData(int $productID, string $branch, int $count): array
+ {
+ $roadmap = array();
+ $total = 0;
+
+ /* Get product plans. */
+ $plans = $this->loadModel('productplan')->getList($productID, $branch);
+
+ /* Get valid product plans and parent plans. */
+ list($orderedPlans, $parents) = $this->filterValidProductPlans($plans);
+
+ /* Get roadmaps of product plans. */
+ list($roadmap, $total, $return) = $this->getRoadmapsOfPlans($orderedPlans, $parents, $branch, $count);
+ if($return) return $roadmap;
+
+ /* Get roadmpas of product releases. */
+ $releases = $this->loadModel('release')->getList($productID, $branch);
+ list($roadmap, $subTotal, $return) = $this->getRoadmapsOfReleases($roadmap, $releases, $branch, $count);
+ if($return) return $roadmap;
+ $total += $subTotal;
+
+ $groupRoadmap = array();
+ foreach($roadmap as $year => $branchRoadmaps)
+ {
+ foreach($branchRoadmaps as $branch => $roadmaps)
+ {
+ $totalData = count($roadmaps);
+ $rows = ceil($totalData / 8);
+ $maxPerRow = ceil($totalData / $rows);
+
+ $groupRoadmap[$year][$branch] = array_chunk($roadmaps, (int)$maxPerRow);
+ foreach($groupRoadmap[$year][$branch] as $row => $rowRoadmaps) krsort($groupRoadmap[$year][$branch][$row]);
+ }
+ }
+
+ return $groupRoadmap;
+ }
+
+ /**
+ * 过滤有效的产品计划, 并返回所有父级计划。
+ * Filter valid product plans.
+ *
+ * @param array $plans
+ * @access private
+ * @return [array, array]
+ */
+ private function filterValidProductPlans(array $plans): array
+ {
+ $parents = array();
+ $orderedPlans = array();
+
+ foreach($plans as $planID => $plan)
+ {
+ /* Remove parent plan. */
+ if($plan->parent == '-1')
+ {
+ $parents[$planID] = $plan->title;
+ unset($plans[$planID]);
+ continue;
+ }
+
+ /* Remove exceeded plan and long-time plan. */
+ if((!helper::isZeroDate($plan->end) and $plan->end < date('Y-m-d')) or $plan->end == '2030-01-01') continue;
+
+ $orderedPlans[$plan->end][] = $plan;
+ }
+
+ krsort($orderedPlans);
+
+ return array($orderedPlans, $parents);
+ }
+
+ /**
+ * 获取计划的路线图数据。
+ * Get roadmaps of plans.
+ *
+ * @param array $orderedPlans
+ * @param array $parents
+ * @param string $branch
+ * @param int $count
+ * @access private
+ * @return [array, int, bool]
+ */
+ private function getRoadmapsOfPlans(array $orderedPlans, array $parents, string $branch, int $count): array
+ {
+ $return = false;
+ $total = 0;
+ $roadmap = array();
+
+ foreach($orderedPlans as $plans)
+ {
+ krsort($plans);
+ foreach($plans as $plan)
+ {
+ /* Attach parent plan. */
+ if($plan->parent > 0 and isset($parents[$plan->parent])) $plan->title = $parents[$plan->parent] . ' / ' . $plan->title;
+
+ $year = substr($plan->end, 0, 4);
+ $branchIdList = explode(',', trim($plan->branch, ','));
+ $branchIdList = array_unique($branchIdList);
+ foreach($branchIdList as $branchID)
+ {
+ if($branchID === '') continue;
+ $roadmap[$year][$branchID][] = $plan;
+ }
+ $total++;
+
+ /* Exceed requested count. */
+ if($count > 0 and $total >= $count)
+ {
+ $roadmap = $this->processRoadmap($roadmap, $branch);
+ $return = true;
+ break;
+ };
+ }
+ }
+
+ return array($roadmap, $total, $return);
+ }
+
+ /**
+ * 获取计划的路线图数据。
+ * Get roadmaps of plans.
+ *
+ * @param array $roadmaps
+ * @param array $parents
+ * @param string $branch
+ * @param int $count
+ * @access private
+ * @return [array, int, bool]
+ */
+ private function getRoadmapsOfReleases(array $roadmaps, array $releases, string $branch, int $count): array
+ {
+ $total = 0;
+ $return = false;
+ $orderedReleases = array();
+
+ /* Collect releases. */
+ foreach($releases as $release) $orderedReleases[$release->date][] = $release;
+
+ krsort($orderedReleases);
+ foreach($orderedReleases as $releases)
+ {
+ krsort($releases);
+ foreach($releases as $release)
+ {
+ $year = substr($release->date, 0, 4);
+ $branchIdList = explode(',', trim($release->branch, ','));
+ $branchIdList = array_unique($branchIdList);
+ foreach($branchIdList as $branchID)
+ {
+ if($branchID === '') continue;
+ $roadmaps[$year][$branchID][] = $release;
+ }
+ $total++;
+
+ /* Exceed required count .*/
+ if($count > 0 and $total >= $count)
+ {
+ $roadmaps = $this->processRoadmap($roadmaps, $branch);
+ $return = true;
+ return array($roadmaps, $total, $return);
+ }
+ }
+ }
+
+ if($count > 0)
+ {
+ $roadmaps = $this->processRoadmap($roadmaps, $branch);
+ $return = true;
+ }
+
+ return array($roadmaps, $total, $return);
+ }
}
diff --git a/module/product/test/model/checkpriv.php b/module/product/test/model/checkpriv.php
index f0457e9869..de52781c13 100755
--- a/module/product/test/model/checkpriv.php
+++ b/module/product/test/model/checkpriv.php
@@ -3,8 +3,6 @@
include dirname(__FILE__, 5) . "/test/lib/init.php";
include dirname(__FILE__, 2) . '/product.class.php';
-#su('admin');
-
/**
title=测试productModel->checkPriv();
@@ -26,21 +24,22 @@ pid=1
*/
-$productIDList = array('1', '2', '3', '4', '5', '1000001');
+$productIdList = array(1, 2, 3, 4, 5, 1000001);
$productTest = new productTest('admin');
-r($productTest->checkPrivTest($productIDList[0])) && p() && e('1'); // 测试admin能否看到产品1
-r($productTest->checkPrivTest($productIDList[1])) && p() && e('1'); // 测试admin能否看到产品2
-r($productTest->checkPrivTest($productIDList[2])) && p() && e('1'); // 测试admin能否看到产品3
-r($productTest->checkPrivTest($productIDList[3])) && p() && e('1'); // 测试admin能否看到产品4
-r($productTest->checkPrivTest($productIDList[4])) && p() && e('1'); // 测试admin能否看到产品5
-r($productTest->checkPrivTest($productIDList[5])) && p() && e('1'); // 测试admin能否看到不存在的产品
-
-$productTest = new productTest('po1');
-r($productTest->checkPrivTest($productIDList[0])) && p() && e('1'); // 测试po1能否看到产品1
-r($productTest->checkPrivTest($productIDList[1])) && p() && e('1'); // 测试po1能否看到产品2
-r($productTest->checkPrivTest($productIDList[2])) && p() && e('1'); // 测试po1能否看到产品3
-r($productTest->checkPrivTest($productIDList[3])) && p() && e('1'); // 测试po1能否看到产品4
-r($productTest->checkPrivTest($productIDList[4])) && p() && e('1'); // 测试po1能否看到产品5
-r($productTest->checkPrivTest($productIDList[5])) && p() && e('2'); // 测试po1能否看到不存在的产品
+$productTest->objectModel->app->user->admin = true;
+r($productTest->checkPrivTest($productIdList[0])) && p() && e('1'); // 测试admin能否看到产品1
+r($productTest->checkPrivTest($productIdList[1])) && p() && e('1'); // 测试admin能否看到产品2
+r($productTest->checkPrivTest($productIdList[2])) && p() && e('1'); // 测试admin能否看到产品3
+r($productTest->checkPrivTest($productIdList[3])) && p() && e('1'); // 测试admin能否看到产品4
+r($productTest->checkPrivTest($productIdList[4])) && p() && e('1'); // 测试admin能否看到产品5
+r($productTest->checkPrivTest($productIdList[5])) && p() && e('1'); // 测试admin能否看到不存在的产品
+$productTest->objectModel->app->user->admin = false;
+$productTest->objectModel->app->user->view->products = '1,2,3,4,5,6,7,8,9,20,21,48,49,50';
+r($productTest->checkPrivTest($productIdList[0])) && p() && e('1'); // 测试po1能否看到产品1
+r($productTest->checkPrivTest($productIdList[1])) && p() && e('1'); // 测试po1能否看到产品2
+r($productTest->checkPrivTest($productIdList[2])) && p() && e('1'); // 测试po1能否看到产品3
+r($productTest->checkPrivTest($productIdList[3])) && p() && e('1'); // 测试po1能否看到产品4
+r($productTest->checkPrivTest($productIdList[4])) && p() && e('1'); // 测试po1能否看到产品5
+r($productTest->checkPrivTest($productIdList[5])) && p() && e('0'); // 测试po1能否看到不存在的产品
diff --git a/module/product/test/model/getmobiledropmenu.php b/module/product/test/model/getmobiledropmenu.php
new file mode 100755
index 0000000000..0f01bcb62d
--- /dev/null
+++ b/module/product/test/model/getmobiledropmenu.php
@@ -0,0 +1,38 @@
+#!/usr/bin/env php
+gen(10);
+
+/**
+
+title=测试productModel->getMobileDropMenu();
+cid=1
+pid=1
+
+测试admin能否看到产品1 >> 1
+测试admin能否看到产品2 >> 1
+测试admin能否看到产品3 >> 1
+测试admin能否看到产品4 >> 1
+测试admin能否看到产品5 >> 1
+测试admin能否看到不存在的产品 >> 1
+测试po1能否看到产品1 >> 1
+测试po1能否看到产品2 >> 1
+测试po1能否看到产品3 >> 1
+测试po1能否看到产品4 >> 1
+测试po1能否看到产品5 >> 1
+测试po1能否看到不存在的产品 >> 2
+
+*/
+
+global $tester;
+$productTest = $tester->loadModel('product');
+$products = $productTest->dao->select('*')->from(TABLE_PRODUCT)->where('deleted')->eq(0)->fetchPairs('id', 'name');
+
+r(strpos($productTest->getMobileDropMenu($products, -1), 'showSearchMenu') !== false) && p() && e('1');
+r(strpos($productTest->getMobileDropMenu($products, 0), 'showSearchMenu') !== false) && p() && e('1');
+r(strpos($productTest->getMobileDropMenu($products, 1), 'showSearchMenu') !== false) && p() && e('1');
+r(strpos($productTest->getMobileDropMenu(array(), -1), 'showSearchMenu') !== false) && p() && e('0');
+r(strpos($productTest->getMobileDropMenu(array(), 0), 'showSearchMenu') !== false) && p() && e('0');
+r(strpos($productTest->getMobileDropMenu(array(), 1), 'showSearchMenu') !== false) && p() && e('0');
diff --git a/module/product/test/model/getroadmap.php b/module/product/test/model/getroadmap.php
index c94dc12fb9..0c688908c9 100755
--- a/module/product/test/model/getroadmap.php
+++ b/module/product/test/model/getroadmap.php
@@ -9,11 +9,11 @@ title=productModel->getRoadmap();
cid=1
pid=1
-测试获取产品1的roadmap数量 >> 5
-测试获取产品2的roadmap数量 >> 2
-测试获取产品3的roadmap数量 >> 0
-测试获取产品4的roadmap数量 >> 0
-测试获取产品5的roadmap数量 >> 0
+测试获取产品1的roadmap数量 >> 1
+测试获取产品2的roadmap数量 >> 1
+测试获取产品3的roadmap数量 >> 1
+测试获取产品4的roadmap数量 >> 1
+测试获取产品5的roadmap数量 >> 1
测试获取不存在产品的roadmap数量 >> 0
*/
@@ -22,9 +22,9 @@ $productIDList = array('1', '2', '3', '4', '5', '1000001');
$product = new productTest('admin');
-r($product->getRoadmapTest($productIDList[0])) && p('total') && e('5'); // 测试获取产品1的roadmap数量
-r($product->getRoadmapTest($productIDList[1])) && p('total') && e('2'); // 测试获取产品2的roadmap数量
-r($product->getRoadmapTest($productIDList[2])) && p('total') && e('0'); // 测试获取产品3的roadmap数量
-r($product->getRoadmapTest($productIDList[3])) && p('total') && e('0'); // 测试获取产品4的roadmap数量
-r($product->getRoadmapTest($productIDList[4])) && p('total') && e('0'); // 测试获取产品5的roadmap数量
+r($product->getRoadmapTest($productIDList[0])) && p('total') && e('1'); // 测试获取产品1的roadmap数量
+r($product->getRoadmapTest($productIDList[1])) && p('total') && e('1'); // 测试获取产品2的roadmap数量
+r($product->getRoadmapTest($productIDList[2])) && p('total') && e('1'); // 测试获取产品3的roadmap数量
+r($product->getRoadmapTest($productIDList[3])) && p('total') && e('1'); // 测试获取产品4的roadmap数量
+r($product->getRoadmapTest($productIDList[4])) && p('total') && e('1'); // 测试获取产品5的roadmap数量
r($product->getRoadmapTest($productIDList[5])) && p('total') && e('0'); // 测试获取不存在产品的roadmap数量
diff --git a/module/product/test/model/getswitcher.php b/module/product/test/model/getswitcher.php
new file mode 100755
index 0000000000..2a0ef6a0be
--- /dev/null
+++ b/module/product/test/model/getswitcher.php
@@ -0,0 +1,34 @@
+#!/usr/bin/env php
+gen(50);
+
+/**
+
+title=测试productModel->setMenu();
+timeout=0
+cid=1
+
+*/
+
+$product = new productTest('admin');
+$product->objectModel->app->moduleName = 'product';
+$product->objectModel->app->methodName = 'browse';
+
+r($product->getSwitcherTest(0)) && p('hasProduct,hasBranch') && e('1,0');
+r($product->getSwitcherTest(1)) && p('hasProduct,hasBranch') && e('1,0');
+r($product->getSwitcherTest(0, '', 'all')) && p('hasProduct,hasBranch') && e('1,0');
+r($product->getSwitcherTest(41,'', 'all')) && p('hasProduct,hasBranch') && e('1,1');
+r($product->getSwitcherTest(0, '', 0)) && p('hasProduct,hasBranch') && e('1,0');
+r($product->getSwitcherTest(41,'', 0)) && p('hasProduct,hasBranch') && e('1,1');
+
+$product->objectModel->app->viewType = 'mhtml';
+r($product->getSwitcherTest(0)) && p('hasProduct,hasBranch') && e('1,0');
+r($product->getSwitcherTest(1)) && p('hasProduct,hasBranch') && e('1,0');
+r($product->getSwitcherTest(0, '', 'all')) && p('hasProduct,hasBranch') && e('1,0');
+r($product->getSwitcherTest(41,'', 'all')) && p('hasProduct,hasBranch') && e('1,1');
+r($product->getSwitcherTest(0, '', 0)) && p('hasProduct,hasBranch') && e('1,0');
+r($product->getSwitcherTest(41,'', 0)) && p('hasProduct,hasBranch') && e('1,1');
+
diff --git a/module/product/test/model/setmenu.php b/module/product/test/model/setmenu.php
new file mode 100755
index 0000000000..f3ff3b1e53
--- /dev/null
+++ b/module/product/test/model/setmenu.php
@@ -0,0 +1,25 @@
+#!/usr/bin/env php
+gen(50);
+
+/**
+
+title=测试productModel->setMenu();
+timeout=0
+cid=1
+
+*/
+
+$product = new productTest('admin');
+
+r($product->setMenuTest(0)) && p('idReplaced,branchReplaced,hasBranch,requirement,hasSwitch') && e('1,0,1,0,0');
+r($product->setMenuTest(1)) && p('idReplaced,branchReplaced,hasBranch,requirement,hasSwitch') && e('1,0,0,0,1');
+r($product->setMenuTest(0, '', 'requirement')) && p('idReplaced,branchReplaced,hasBranch,requirement,hasSwitch') && e('1,0,1,1,0');
+r($product->setMenuTest(1, '', 'requirement')) && p('idReplaced,branchReplaced,hasBranch,requirement,hasSwitch') && e('1,0,0,1,1');
+r($product->setMenuTest(0, 'all')) && p('idReplaced,branchReplaced,hasBranch,requirement,hasSwitch') && e('1,0,1,0,0');
+r($product->setMenuTest(41, 'all')) && p('idReplaced,branchReplaced,hasBranch,requirement,hasSwitch') && e('1,1,1,0,1');
+r($product->setMenuTest(0, 0, 'requirement')) && p('idReplaced,branchReplaced,hasBranch,requirement,hasSwitch') && e('1,0,1,1,0');
+r($product->setMenuTest(41, 0, 'requirement')) && p('idReplaced,branchReplaced,hasBranch,requirement,hasSwitch') && e('1,1,1,1,1');
diff --git a/module/product/test/product.class.php b/module/product/test/product.class.php
index 085c6364cc..98875227fd 100644
--- a/module/product/test/product.class.php
+++ b/module/product/test/product.class.php
@@ -5,7 +5,7 @@ class productTest
* @var productModel
* @access private
*/
- private productModel $objectModel;
+ public productModel $objectModel;
/**
* __construct
@@ -372,20 +372,11 @@ class productTest
*
* @param int $productID
* @access public
- * @return int
+ * @return bool
*/
- public function checkPrivTest($productID)
+ public function checkPrivTest(int $productID): bool
{
- $object = $this->objectModel->checkPriv($productID);
-
- if(dao::isError())
- {
- return dao::getError();
- }
- else
- {
- return $object ? 1 : 2;
- }
+ return $this->objectModel->checkPriv($productID);
}
/**
@@ -777,14 +768,9 @@ class productTest
{
$objects = $this->objectModel->getRoadmap($productID);
- if(dao::isError())
- {
- return dao::getError();
- }
- else
- {
- return $objects;
- }
+ if(dao::isError()) return dao::getError();
+
+ return $objects;
}
/**
@@ -803,14 +789,9 @@ class productTest
$objects = $this->objectModel->processRoadmap($roadmapGroups);
- if(dao::isError())
- {
- return dao::getError();
- }
- else
- {
- return $objects;
- }
+ if(dao::isError()) return dao::getError();
+
+ return $objects;
}
/**
@@ -1106,4 +1087,86 @@ class productTest
return $object;
}
}
+
+ /**
+ * 测试setMenu方法。
+ * Test setMenu
+ *
+ * @param int $productID
+ * @param string|int $branch
+ * @param string $extra
+ * @access public
+ * @return array
+ */
+ public function setMenuTest(int $productID, string|int $branch = '', string $extra = ''): array
+ {
+ /* Reset data. */
+ unset($this->objectModel->lang->switcherMenu);
+ $this->objectModel->lang->product->moreSelects['willclose'] = 'willcose';
+ $this->objectModel->lang->product->menu->settings['link'] = "Settings|product|view|productID=%s";
+ $this->objectModel->lang->product->menu->settings['subMenu']->branch = array('link' => "@branch@|branch|manage|product=%s", 'subModule' => 'branch');
+
+ $this->objectModel->setMenu($productID, $branch, $extra);
+
+ $hasBranch = (int) isset($this->objectModel->lang->product->menu->settings['subMenu']->branch);
+ $requirement = (int)!isset($this->objectModel->lang->product->moreSelects['willclose']);
+ $hasSwitch = (int)!empty($this->objectModel->lang->switcherMenu);
+ $idReplaced = (int)(strpos($this->objectModel->lang->product->menu->settings['link'], '%s') === false);
+ $branchReplaced = (int)($hasBranch and strpos($this->objectModel->lang->product->menu->settings['subMenu']->branch['link'], '@branch@') === false);
+
+ return array('idReplaced' => $idReplaced, 'branchReplaced' => $branchReplaced, 'hasBranch' => $hasBranch, 'requirement' => $requirement, 'hasSwitch' => $hasSwitch);
+ }
+
+ /**
+ * 测试 getSwitcher 方法。
+ * Test getSwitcher.
+ *
+ * @param int $productID
+ * @param string $extra
+ * @param string|int $branch
+ * @access public
+ * @return array
+ */
+ public function getSwitcherTest(int $productID, string $extra = '', string|int $branch = ''): array
+ {
+ $this->objectModel->lang->product->menu->settings['subMenu']->branch = array('link' => "@branch@|branch|manage|product=%s", 'subModule' => 'branch');
+
+ $switcher = $this->objectModel->getSwitcher($productID, $extra, $branch);
+
+ $product = $this->objectModel->dao->select('*')->from(TABLE_PRODUCT)->where('id')->eq($productID)->fetch();
+ $hasProduct = $product ? (int)(strpos($switcher, $product->name) !== false) : (int)(strpos($switcher, '产品') !== false);
+ $hasBranch = (int)(strpos($switcher, 'currentBranch') !== false);
+
+ return array('hasProduct' => $hasProduct, 'hasBranch' => $hasBranch);
+ }
+
+ /**
+ * 测试 buildSelect4Mobile 方法。
+ * Test buildSelect4Mobile
+ *
+ * @param array $products
+ * @param int $productID
+ * @param string $currentModule
+ * @param string $currentMethod
+ * @param string $extra
+ * @param string|int $branch
+ * @param bool $withBranch
+ * @access public
+ * @return array
+ */
+ public function buildSelect4MobileTest(array $products, int $productID, string $currentModule, string $currentMethod, string $extra = '', string|int $branch = '', bool $withBranch = true): array
+ {
+ $this->objectModel->lang->product->menu->settings['subMenu']->branch = array('link' => "@branch@|branch|manage|product=%s", 'subModule' => 'branch');
+
+ $select = $this->objectModel->buildSelect4Mobile($products, $productID, $currentModule, $currentMethod, $extra, $branch, $withBranch);
+
+ $productName = zget($products, $productID, reset($products));
+ $branchName = '所有';
+ if(is_numeric($branch)) $branchName = $this->objectModel->dao->select('*')->from(TABLE_BRANCH)->where('id')->eq($branch)->fetch('name');
+
+ $hasProduct = (int)(strpos($select, 'currentItem') !== false and strpos($select, $productName) !== false);
+ $hasBranch = (int)(strpos($select, 'currentBranch') !== false and strpos($select, $branchName) !== false);
+
+ return array('hasProduct' => $hasProduct, 'hasBranch' => $hasBranch);
+ }
}
diff --git a/module/product/test/tao/buildselect4mobile.php b/module/product/test/tao/buildselect4mobile.php
new file mode 100755
index 0000000000..d8bdc27fac
--- /dev/null
+++ b/module/product/test/tao/buildselect4mobile.php
@@ -0,0 +1,52 @@
+#!/usr/bin/env php
+gen(50);
+$branch = zdTable('branch');
+$branch->product->range('41');
+$branch->gen(5);
+
+/**
+
+title=测试productModel->buildSelect4Mobile();
+timeout=0
+cid=1
+
+*/
+
+$productTest = new productTest('admin');
+$productTest->objectModel->dao->update(TABLE_PRODUCT)->set('deleted')->eq(1)->where('id')->eq(49)->exec();
+$products = $productTest->objectModel->dao->select('*')->from(TABLE_PRODUCT)->where('deleted')->eq(0)->fetchPairs('id', 'name');
+
+$moduleName = 'product';
+$methodName = 'browse';
+r($productTest->buildSelect4MobileTest(array(), 0, $moduleName, $methodName)) && p('hasProduct,hasBranch') && e('0,0');
+r($productTest->buildSelect4MobileTest($products, 0, $moduleName, $methodName)) && p('hasProduct,hasBranch') && e('1,0');
+r($productTest->buildSelect4MobileTest($products, 1, $moduleName, $methodName)) && p('hasProduct,hasBranch') && e('1,0');
+r($productTest->buildSelect4MobileTest($products, 49, $moduleName, $methodName)) && p('hasProduct,hasBranch') && e('1,0');
+r($productTest->buildSelect4MobileTest($products, 41, $moduleName, $methodName)) && p('hasProduct,hasBranch') && e('1,1');
+r($productTest->buildSelect4MobileTest($products, 41, $moduleName, $methodName, '', 1)) && p('hasProduct,hasBranch') && e('1,1');
+r($productTest->buildSelect4MobileTest($products, 41, $moduleName, $methodName, '', '', false)) && p('hasProduct,hasBranch') && e('1,0');
+r($productTest->buildSelect4MobileTest($products, 70, $moduleName, $methodName)) && p('hasProduct,hasBranch') && e('1,0');
+
+$productTest->objectModel->app->tab = 'project';
+$moduleName = 'project';
+$methodName = 'testcase';
+r($productTest->buildSelect4MobileTest($products, 41, $moduleName, $methodName)) && p('hasProduct,hasBranch') && e('1,1');
+$moduleName = 'testcase';
+$methodName = 'groupCase';
+r($productTest->buildSelect4MobileTest($products, 41, $moduleName, $methodName)) && p('hasProduct,hasBranch') && e('1,1');
+
+$productTest->objectModel->app->tab = 'execution';
+$moduleName = 'execution';
+$methodName = 'bug';
+r($productTest->buildSelect4MobileTest($products, 41, $moduleName, $methodName)) && p('hasProduct,hasBranch') && e('1,1');
+$methodName = 'task';
+r($productTest->buildSelect4MobileTest($products, 41, $moduleName, $methodName)) && p('hasProduct,hasBranch') && e('1,1');
+
+$productTest->objectModel->app->tab = 'feedback';
+$moduleName = 'bug';
+$methodName = 'view';
+r($productTest->buildSelect4MobileTest($products, 41, $moduleName, $methodName)) && p('hasProduct,hasBranch') && e('1,1');
diff --git a/module/product/test/tao/computelocate4dropmenu.php b/module/product/test/tao/computelocate4dropmenu.php
new file mode 100755
index 0000000000..d62e716ab5
--- /dev/null
+++ b/module/product/test/tao/computelocate4dropmenu.php
@@ -0,0 +1,54 @@
+#!/usr/bin/env php
+computeLocate4DropMenu();
+timeout=0
+cid=1
+
+*/
+
+global $tester;
+$product = $tester->loadModel('product');
+
+$product->app->moduleName = 'product';
+$product->app->methodName = 'browse';
+r($product->computeLocate4DropMenu()) && p('0,1') && e('product,browse');
+
+$product->app->moduleName = 'story';
+$product->app->methodName = 'view';
+r($product->computeLocate4DropMenu()) && p('0,1') && e('product,browse');
+
+$product->app->moduleName = 'story';
+$product->app->methodName = 'create';
+r($product->computeLocate4DropMenu()) && p('0,1') && e('story,create');
+
+$product->app->moduleName = 'story';
+$product->app->methodName = 'report';
+r($product->computeLocate4DropMenu()) && p('0,1') && e('product,browse');
+
+$product->app->moduleName = 'product';
+$product->app->methodName = 'report';
+r($product->computeLocate4DropMenu()) && p('0,1') && e('product,browse');
+
+$product->app->moduleName = 'bug';
+$product->app->methodName = 'edit';
+r($product->computeLocate4DropMenu()) && p('0,1') && e('bug,browse');
+
+$product->app->moduleName = 'bug';
+$product->app->methodName = 'view';
+r($product->computeLocate4DropMenu()) && p('0,1') && e('bug,view');
+
+$product->app->moduleName = 'bug';
+$product->app->methodName = 'report';
+r($product->computeLocate4DropMenu()) && p('0,1') && e('bug,browse');
+
+$product->app->moduleName = 'testcase';
+$product->app->methodName = 'edit';
+r($product->computeLocate4DropMenu()) && p('0,1') && e('testcase,browse');
+
+$product->app->moduleName = 'testcase';
+$product->app->methodName = 'view';
+r($product->computeLocate4DropMenu()) && p('0,1') && e('testcase,browse');
diff --git a/module/product/test/tao/getbranchselect4mobile.php b/module/product/test/tao/getbranchselect4mobile.php
new file mode 100755
index 0000000000..ca283b12f1
--- /dev/null
+++ b/module/product/test/tao/getbranchselect4mobile.php
@@ -0,0 +1,32 @@
+#!/usr/bin/env php
+gen(50);
+$branch = zdTable('branch');
+$branch->product->range('41');
+$branch->gen(5);
+
+/**
+
+title=测试productModel->getBranchSelect4Mobile();
+timeout=0
+cid=1
+
+*/
+
+global $tester;
+$productTest = $tester->loadModel('product');
+$product = $productTest->dao->select('*')->from(TABLE_PRODUCT)->where('id')->eq(1)->fetch();
+
+$moduleName = 'product';
+$methodName = 'browse';
+r($productTest->getBranchSelect4Mobile(new stdclass(), '', $moduleName, $methodName)) && p() && e('0');
+r($productTest->getBranchSelect4Mobile($product, '', $moduleName, $methodName)) && p() && e('0');
+
+$product = $productTest->dao->select('*')->from(TABLE_PRODUCT)->where('id')->eq(41)->fetch();
+$result = $productTest->getBranchSelect4Mobile($product, 'all', $moduleName, $methodName);
+r((strpos($result, 'currentBranch') !== false and strpos($result, '所有') !== false)) && p() && e('1');
+
+$result = $productTest->getBranchSelect4Mobile($product, 1, $moduleName, $methodName);
+r((strpos($result, 'currentBranch') !== false and strpos($result, '分支1') !== false)) && p() && e('1');
diff --git a/module/product/test/tao/getbranchselect4pc.php b/module/product/test/tao/getbranchselect4pc.php
new file mode 100755
index 0000000000..693fe8dfc5
--- /dev/null
+++ b/module/product/test/tao/getbranchselect4pc.php
@@ -0,0 +1,44 @@
+#!/usr/bin/env php
+gen(50);
+$branch = zdTable('branch');
+$branch->product->range('41');
+$branch->gen(5);
+
+/**
+
+title=测试productModel->getBranchSelect4PC();
+timeout=0
+cid=1
+
+*/
+
+global $tester;
+$productTest = $tester->loadModel('product');
+$product = $productTest->dao->select('*')->from(TABLE_PRODUCT)->where('id')->eq(1)->fetch();
+
+$moduleName = 'product';
+$methodName = 'browse';
+r($productTest->getBranchSelect4PC(new stdclass(), '', $moduleName, $methodName)) && p() && e('0');
+r($productTest->getBranchSelect4PC($product, '', $moduleName, $methodName)) && p() && e('0');
+
+$product = $productTest->dao->select('*')->from(TABLE_PRODUCT)->where('id')->eq(41)->fetch();
+$result = $productTest->getBranchSelect4PC($product, '', $moduleName, $methodName);
+r((strpos($result, 'currentBranch') !== false and strpos($result, '所有') !== false)) && p() && e('1');
+
+$result = $productTest->getBranchSelect4PC($product, 1, $moduleName, $methodName);
+r((strpos($result, 'currentBranch') !== false and strpos($result, '分支1') !== false)) && p() && e('1');
+
+r((strpos($productTest->getBranchSelect4PC($product, 1, 'testcase', 'showimport'), 'currentBranch') !== false)) && p() && e('0');
+r((strpos($productTest->getBranchSelect4PC($product, 1, 'tree', 'browse'), 'currentBranch') !== false)) && p() && e('1');
+r((strpos($productTest->getBranchSelect4PC($product, 1, 'product', 'view'), 'currentBranch') !== false)) && p() && e('0');
+r((strpos($productTest->getBranchSelect4PC($product, 1, 'release', 'create'), 'currentBranch') !== false)) && p() && e('1');
+r((strpos($productTest->getBranchSelect4PC($product, 1, 'release', 'view'), 'currentBranch') !== false)) && p() && e('0');
+
+$productTest->app->tab = 'qa';
+r((strpos($productTest->getBranchSelect4PC($product, 1, 'bug', 'view'), 'currentBranch') !== false)) && p() && e('1');
+r((strpos($productTest->getBranchSelect4PC($product, 1, 'testcase', 'view'), 'currentBranch') !== false)) && p() && e('1');
+r((strpos($productTest->getBranchSelect4PC($product, 1, 'testtask', 'view'), 'currentBranch') !== false)) && p() && e('1');
+r((strpos($productTest->getBranchSelect4PC($product, 1, 'testtask', 'create'), 'currentBranch') !== false)) && p() && e('0');
diff --git a/module/product/zen.php b/module/product/zen.php
index 74dd7f943e..f6fb53276b 100644
--- a/module/product/zen.php
+++ b/module/product/zen.php
@@ -19,7 +19,7 @@ class productZen extends product
* @access protected
* @return void
*/
- protected function setEnvAll()
+ protected function setMenu4All()
{
/* Set redirect URI. */
$this->session->set('productList', $this->app->getURI(true), 'product');
@@ -28,7 +28,7 @@ class productZen extends product
if($this->app->viewType == 'mhtml')
{
$productID = $this->saveVisitState(0, $this->products);
- $this->setMenu($productID);
+ $this->product->setMenu($productID);
}
}
@@ -48,7 +48,7 @@ class productZen extends product
setcookie('preBranch', $branch, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
$this->session->set('createProjectLocate', $this->app->getURI(true), 'product');
- $this->setMenu($productID, $branch);
+ $this->product->setMenu($productID, $branch);
}
/**
@@ -67,7 +67,7 @@ class productZen extends product
if($this->app->getViewType() != 'mhtml') return;
if($this->app->rawModule == 'projectstory' and $this->app->rawMethod == 'story') return $this->loadModel('project')->setMenu();
- $this->setMenu();
+ $this->product->setMenu();
}
/**
@@ -82,7 +82,7 @@ class productZen extends product
protected function setEditMenu(int $productID, int $programID)
{
if($programID) return $this->loadModel('program')->setMenu($programID);
- $this->setMenu($productID);
+ $this->product->setMenu($productID);
}
/**
@@ -97,7 +97,7 @@ class productZen extends product
*/
protected function setShowErrorNoneMenu(string $moduleName, string $activeMenu, int $objectID)
{
- if($this->app->getViewType() == 'mhtml') return $this->setMenu();
+ if($this->app->getViewType() == 'mhtml') return $this->product->setMenu();
if($moduleName == 'qa') $this->setShowErrorNoneMenu4QA($activeMenu);
if($moduleName == 'project') $this->setShowErrorNoneMenu4Project($activeMenu, $objectID);
@@ -845,7 +845,7 @@ class productZen extends product
return;
}
- $this->product->setMenu($productID, $branch, 0, '', "storyType=$storyType");
+ $this->product->setMenu($productID, $branch, "storyType=$storyType");
}
/**
diff --git a/module/programplan/control.php b/module/programplan/control.php
index 6961ccf6fb..28897a122e 100644
--- a/module/programplan/control.php
+++ b/module/programplan/control.php
@@ -54,6 +54,7 @@ class programplan extends control
if(!defined('RUN_MODE') || RUN_MODE != 'api') $projectID = $this->project->saveState($projectID, $this->project->getPairsByProgram());
+ /* 获取项目下产品并调整三级导航操作按钮。 */
$products = $this->loadModel('product')->getProducts($projectID);
if($this->session->hasProduct) $this->lang->modulePageNav = $this->product->select($products, $productID, 'programplan', 'browse', $type, 0, 0, '', false);
diff --git a/module/programplan/model.php b/module/programplan/model.php
index 11524ebcf9..80bc48c081 100755
--- a/module/programplan/model.php
+++ b/module/programplan/model.php
@@ -1540,13 +1540,14 @@ class programplanModel extends model
}
/**
+ * 检查阶段是否是叶子阶段。
* Check if the stage is a leaf stage.
*
* @param int $planID
* @access public
* @return bool
*/
- public function checkLeafStage($planID)
+ public function checkLeafStage(int $planID): bool
{
$subStageList = $this->dao->select('id')->from(TABLE_EXECUTION)->where('parent')->eq($planID)->andWhere('deleted')->eq(0)->fetchAll('id');
diff --git a/module/programplan/test/model/checkleafstage.php b/module/programplan/test/model/checkleafstage.php
index 95cbd14024..f766303bcb 100755
--- a/module/programplan/test/model/checkleafstage.php
+++ b/module/programplan/test/model/checkleafstage.php
@@ -1,23 +1,16 @@
#!/usr/bin/env php
gen(5);
+
+function initData()
+{
+ zdTable('user')->gen(5);
+ zdTable('project')->config('checkleafstage')->gen(5);
+}
+
su('admin');
-$execution = zdTable('project');
-$execution->id->range('1-5');
-$execution->name->range('瀑布项目1,阶段a,阶段a子1,阶段a子1子1,阶段b');
-$execution->type->range('project,stage{4}');
-$execution->project->range('0,1{4}');
-$execution->parent->range('0,1,2,3,1');
-$execution->path->range("`,1,`,`,1,2,`,`,1,2,3,`,`,1,2,3,4,`,`,1,5,`");
-$execution->status->range('doing,doing,doing,closed,suspended');
-$execution->openedBy->range('admin,user1');
-$execution->begin->range('20220112 000000:0')->type('timestamp')->format('YY/MM/DD');
-$execution->end->range('20220212 000000:0')->type('timestamp')->format('YY/MM/DD');
-$execution->realBegan->range('20220212 000000:0')->type('timestamp')->format('YY/MM/DD');
-$execution->gen(5);
/**
@@ -25,8 +18,9 @@ title=测试programplanModel->checkLeafStage();
cid=1
pid=1
-测试id为2判断是否为叶子节点 >> 0
-测试id为5判断是否为叶子节点 >> 1
+- 测试id为2判断是否为叶子节点 @0
+
+- 测试id为5判断是否为叶子节点 @1
*/
diff --git a/module/programplan/test/model/yaml/checkleafstage/checkleafstage.yaml b/module/programplan/test/model/yaml/checkleafstage/checkleafstage.yaml
new file mode 100644
index 0000000000..52225e216a
--- /dev/null
+++ b/module/programplan/test/model/yaml/checkleafstage/checkleafstage.yaml
@@ -0,0 +1,33 @@
+title: programplanModel::checkLeafStage UTC.
+desc: programplanModel::checkLeafStage UTC.
+author: xushenjie
+version: '1.0'
+fields:
+ - field: name
+ range: '瀑布项目1,阶段a,阶段a子1,阶段a子1子1,阶段b'
+ - field: type
+ range: '0,1{4}'
+ - field: project
+ range: '0,1{4}'
+ - field: parent
+ range: '0,1,2,3,1'
+ - field: grade
+ range: 1
+ - field: path
+ range: "`,1,`,`,1,2,`,`,1,2,3,`,`,1,2,3,4,`,`,1,5,`"
+ - field: status
+ range: 'doing,doing,doing,closed,suspended'
+ - field: openedBy
+ range: 'admin,user1'
+ - field: begin
+ range: '20230501 000000:0'
+ type: 'timestamp'
+ format: 'YY/MM/DD'
+ - field: end
+ range: '20300501 000000:0'
+ type: 'timestamp'
+ format: 'YY/MM/DD'
+ - field: realBegan
+ range: '20230501 000000:0'
+ type: 'timestamp'
+ format: 'YY/MM/DD'
diff --git a/module/project/tao.php b/module/project/tao.php
index 50f7d99196..cc5fd4853d 100755
--- a/module/project/tao.php
+++ b/module/project/tao.php
@@ -630,10 +630,10 @@ class projectTao extends projectModel
* @param int $program
* @param string $path
* @param int $grade
- * @access public
+ * @access protected
* @return string
*/
- public function getParentProgram(string $path, int $grade): string
+ protected function getParentProgram(string $path, int $grade): string
{
$programList = $this->dao->select('id,name')->from(TABLE_PROGRAM)
->where('id')->in(trim($path, ','))
@@ -761,10 +761,10 @@ class projectTao extends projectModel
* Get the number of stories associated with the project.
*
* @param array $projectIdList
- * @access public
+ * @access protected
* @return array
*/
- public function getTotalStoriesByProject(array $projectIdList): array
+ protected function getTotalStoriesByProject(array $projectIdList): array
{
return $this->dao->select("t1.project, count(t2.id) as allStories, count(if(t2.status = 'active' or t2.status = 'changing', 1, null)) as leftStories, count(if(t2.status = 'closed' and t2.closedReason = 'done', 1, null)) as doneStories")->from(TABLE_PROJECTSTORY)->alias('t1')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id')
@@ -780,10 +780,10 @@ class projectTao extends projectModel
* Get the number of tasks associated with the project.
*
* @param array $projectIdList
- * @access public
+ * @access protected
* @return array
*/
- public function getTotalTaskByProject(array $projectIdList): array
+ protected function getTotalTaskByProject(array $projectIdList): array
{
return $this->dao->select("t1.project, count(t1.id) as allTasks, count(if(t1.status = 'wait', 1, null)) as waitTasks, count(if(t1.status = 'doing', 1, null)) as doingTasks, count(if(t1.status = 'done', 1, null)) as doneTasks, count(if(t1.status = 'wait' or t1.status = 'pause' or t1.status = 'cancel', 1, null)) as leftTasks, count(if(t1.status = 'done' or t1.status = 'closed', 1, null)) as litedoneTasks")->from(TABLE_TASK)->alias('t1')
->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.execution=t2.id')
@@ -812,10 +812,10 @@ class projectTao extends projectModel
* Get the number of bugs associated with the project.
*
* @param array $projectIdList
- * @access public
+ * @access protected
* @return array
*/
- public function getTotalBugByProject(array $projectIdList): array
+ protected function getTotalBugByProject(array $projectIdList): array
{
return $this->dao->select("project, count(id) as allBugs, count(if(status = 'active', 1, null)) as leftBugs, count(if(status = 'resolved', 1, null)) as doneBugs")->from(TABLE_BUG)
->where('project')->in($projectIdList)
diff --git a/module/project/test/model/getprogrammaxend.php b/module/project/test/model/getprogrammaxend.php
index 22e75d8070..53f3e1fdcf 100755
--- a/module/project/test/model/getprogrammaxend.php
+++ b/module/project/test/model/getprogrammaxend.php
@@ -15,14 +15,10 @@ pid=1
global $tester;
$tester->loadModel('project');
-$project1 = $tester->project->getProgramMaxEnd(1);
-$project2 = $tester->project->getProgramMaxEnd(3);
-$project3 = $tester->project->getProgramMaxEnd(6);
+$project4 = $tester->project->getProgramMaxEnd(1);
+$project5 = $tester->project->getProgramMaxEnd(3);
+$project6 = $tester->project->getProgramMaxEnd(6);
-a($project1);die;
-r($project1) && p() && e(); //获取一级项目集最小开始时间
-r($project1) && p() && e(); //获取一级项目集最大结束时间
-r($project2) && p() && e(); //获取二级项目集最小开始时间
-r($project2) && p() && e(); //获取二级项目集最大结束时间
-r($project3) && p() && e(); //获取三级项目集最小开始时间
-r($project3) && p() && e(); //获取三级项目集最大结束时间
+r($project6) && p('maxEnd') && e('2023-06-12'); //获取一级项目集最大结束时间:尾级项目结束时间最大
+r($project5) && p('maxEnd') && e('2023-07-03'); //获取二级项目集最大结束时间:顶级项目结束时间最大
+r($project4) && p('maxEnd') && e('2023-05-08'); //获取三级项目集最大结束时间:开始时间等于结束时间
diff --git a/module/project/test/model/getprogramminbegin.php b/module/project/test/model/getprogramminbegin.php
new file mode 100644
index 0000000000..6a76ce2df8
--- /dev/null
+++ b/module/project/test/model/getprogramminbegin.php
@@ -0,0 +1,24 @@
+#!/usr/bin/env php
+config('project')->gen(6);
+
+/**
+
+title=测试 projectModel->getProgramMinBegin();
+cid=1
+pid=1
+*/
+
+global $tester;
+
+$tester->loadModel('project');
+$project1 = $tester->project->getProgramMinBegin(1);
+$project2 = $tester->project->getProgramMinBegin(3);
+$project3 = $tester->project->getProgramMinBegin(6);
+
+r($project1) && p('minBegin') && e('2023-05-01'); //获取一级项目集最小开始时间:顶级项目开始时间最小
+r($project2) && p('minBegin') && e('2023-04-22'); //获取二级项目集最小开始时间:次级项目开始时间最小
+r($project3) && p('minBegin') && e('2023-05-08'); //获取三级项目集最小开始时间:开始时间等于结束时间
diff --git a/module/project/test/model/yaml/getprogrammaxend/project.yaml b/module/project/test/model/yaml/getprogrammaxend/project.yaml
index 25ed2bb9ad..230181f50b 100644
--- a/module/project/test/model/yaml/getprogrammaxend/project.yaml
+++ b/module/project/test/model/yaml/getprogrammaxend/project.yaml
@@ -22,7 +22,5 @@ fields:
range: '项目集1, 项目集1-1, 项目1-1-2, 项目集3, 项目3-4, 无迭代无产品项目6'
- field: code
range: 'program1, program1-1, project1-1-2, program3, project3-4, project6'
- - field: begin
- range: "'2023-05-01', '2023-05-07', '2023-05-20', '2023-04-04', '2023-05-01', '2023-05-08'"
- field: end
- range: "'2023-06-01', '2023-05-19', '2023-06-12', '2023-07-03', '2023-06-03', '2023-05-08'"
+ range: '2023-06-01', '2023-05-19', '2023-06-12', '2023-07-03', '2023-06-03', '2023-05-08'
diff --git a/module/project/test/model/yaml/getprogramminbegin/project.yaml b/module/project/test/model/yaml/getprogramminbegin/project.yaml
new file mode 100644
index 0000000000..aef1007a25
--- /dev/null
+++ b/module/project/test/model/yaml/getprogramminbegin/project.yaml
@@ -0,0 +1,26 @@
+title: zt_project
+author: liuhong
+version: "1.0"
+fields:
+ - field: id
+ range: 1-6
+ - field: project
+ range: 0
+ - field: model
+ range: ', , ,scrum, ,scrum,scrum'
+ - field: type
+ range: 'program,program,project,program,project,project'
+ - field: status
+ range: 'wait,doing,closed,suspended'
+ - field: parent
+ range: 0, 1, 2, 0, 3, 0
+ - field: grade
+ range: 1, 2, 3, 1, 2, 1
+ - field: path
+ range: '`,1,`, `,1,2,`, `,1,2,3,`, `,4,`, `,4,5,`, `,6,`'
+ - field: name
+ range: '项目集1, 项目集1-1, 项目1-1-2, 项目集3, 项目3-4, 无迭代无产品项目6'
+ - field: code
+ range: 'program1, program1-1, project1-1-2, program3, project3-4, project6'
+ - field: begin
+ range: '2023-05-01', '2023-05-07', '2023-05-20', '2023-05-01', '2023-04-22', '2023-05-08'
diff --git a/module/task/config/form.php b/module/task/config/form.php
index a8a3ef0941..3b2c531017 100644
--- a/module/task/config/form.php
+++ b/module/task/config/form.php
@@ -25,15 +25,21 @@ $config->task->form->create['version'] = array('type' => 'int', 'required'
$config->task->form->assign = array();
$config->task->form->assign['assignedTo'] = array('type' => 'string', 'required' => false, 'default' => '');
$config->task->form->assign['left'] = array('type' => 'float', 'required' => true);
-$config->task->form->assign['lastEditedBy'] = array('type' => 'string', 'required' => false, 'default' => $app->user->account);
$config->task->form->assign['lastEditedDate'] = array('type' => 'string', 'required' => false, 'default' => helper::now());
$config->task->form->assign['assignedDate'] = array('type' => 'string', 'required' => false, 'default' => helper::now());
+$config->task->form->manageTeam = array();
+$config->task->form->manageTeam['status'] = array('type' => 'string', 'required' => false, 'default' => '');
+$config->task->form->manageTeam['estimate'] = array('type' => 'float', 'required' => false, 'default' => 0);
+$config->task->form->manageTeam['left'] = array('type' => 'float', 'required' => false, 'default' => 0);
+$config->task->form->manageTeam['consumed'] = array('type' => 'float', 'required' => false, 'default' => 0);
+$config->task->form->manageTeam['lastEditedDate'] = array('type' => 'string', 'required' => false, 'default' => helper::now());
+$config->task->form->manageTeam['assignedDate'] = array('type' => 'string', 'required' => false, 'default' => helper::now());
+
$config->task->form->edit = array();
$config->task->form->edit['name'] = array('type' => 'string', 'required' => true);
$config->task->form->edit['color'] = array('type' => 'string', 'required' => false, 'default' => '');
$config->task->form->edit['desc'] = array('type' => 'string', 'required' => false, 'default' => '');
-$config->task->form->edit['lastEditedBy'] = array('type' => 'string', 'required' => false, 'default' => $app->user->account);
$config->task->form->edit['execution'] = array('type' => 'int', 'required' => true);
$config->task->form->edit['story'] = array('type' => 'int', 'required' => false, 'default' => 0);
$config->task->form->edit['module'] = array('type' => 'int', 'required' => false, 'default' => 0);
diff --git a/module/task/control.php b/module/task/control.php
index e8ce797d1e..22577d5843 100755
--- a/module/task/control.php
+++ b/module/task/control.php
@@ -174,16 +174,18 @@ class task extends control
}
/**
+ * 编辑任务。
* Edit a task.
*
- * @param int $taskID
+ * @param string $taskID
* @param string $comment
- * @param string $from
+ * @param string $from ''|taskkanban
* @access public
* @return void
*/
- public function edit(string $taskID, string $comment = 'false', string $from = '')
+ public function edit(string $taskID, string $comment = '', string $from = '')
{
+ $taskID = (int)$taskID;
$this->commonAction($taskID);
if(!empty($_POST))
@@ -192,15 +194,17 @@ class task extends control
$changes = array();
$postDataFixer = form::data($this->config->task->form->edit);
- $rawData = $postDataFixer->rawdata;
+ $rawData = $postDataFixer->rawdata;
- if(!$comment or $comment == 'false')
+ /* Update task. */
+ if(empty($comment))
{
$task = $this->taskZen->prepareEdit($postDataFixer, $taskID);
$changes = $this->task->update($task, $rawData);
if(dao::isError()) return print(js::error(dao::getError()));
}
+ /* Record log. */
if($rawData->comment != '' or !empty($changes))
{
$action = !empty($changes) ? 'Edited' : 'Commented';
@@ -208,9 +212,9 @@ class task extends control
if(!empty($changes)) $this->action->logHistory($actionID, $changes);
}
+ /* Execute hooks and synchronize the status of related objects. */
$this->executeHooks($taskID);
-
- if($rawData->status == 'doing') $this->loadModel('common')->syncPPEStatus($taskID);
+ if($task->status == 'doing') $this->loadModel('common')->syncPPEStatus($taskID);
$reponse = $this->taskZen->reponseAfterEdit($taskID, $from, $changes);
return is_array($reponse) ? $this->send($reponse) : $reponse;
@@ -359,47 +363,45 @@ class task extends control
}
/**
+ * 指派任务。
* Update assign of task
*
- * @param int $requestID
- * @param int $taskID
- * @param string $kanbanGroup
- * @param string $from
+ * @param stirng $executionID
+ * @param string $taskID
+ * @param string $from ''|taskkanban
* @access public
* @return void
*/
- public function assignTo(int $executionID, int $taskID, string $kanbanGroup = 'default', string $from = '')
+ public function assignTo(string $executionID, string $taskID, string $from = '')
{
+ $executionID = (int)$executionID;
+ $taskID = (int)$taskID;
$this->commonAction($taskID);
- $task = $this->task->getByID($taskID);
-
- if(!empty($task->team) and $task->mode == 'multi' and strpos('done,cencel,closed', $task->status) === false)
- {
- return $this->editTeam($executionID, $taskID, $kanbanGroup, $from);
- }
if(!empty($_POST))
{
$postDataFixer = form::data($this->config->task->form->assign);
- $rawData = $postDataFixer->rawdata;
+ /* Assign task. */
$task = $this->taskZen->prepareAssignTo($postDataFixer, $taskID);
- $changes = $this->task->assign($task);
+ $changes = $this->task->assign($task, $this->post->uid);
if(dao::isError())
{
if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return print(js::error(dao::getError()));
}
- $actionID = $this->loadModel('action')->create('task', $taskID, 'Assigned', $rawData->comment, $task->assignedTo);
+ /* Record log. */
+ $actionID = $this->loadModel('action')->create('task', $taskID, 'Assigned', $this->post->comment, $task->assignedTo);
$this->action->logHistory($actionID, $changes);
$this->executeHooks($taskID);
- return $this->taskZen->reponseAfterAssignTo($taskID, $from);
+ $reponse = $this->taskZen->reponseAfterAssignTo($taskID, $from);
+ return is_array($reponse) ? $this->send($reponse) : $reponse;
}
- $this->taskZen->buildAssignToForm($executionID, $task);
+ $this->taskZen->buildAssignToForm($executionID, $taskID);
}
/**
@@ -1902,24 +1904,29 @@ class task extends control
}
/**
+ * 管理多人任务的团队。
* Update assign of multi task.
*
- * @param int $requestID
- * @param object $taskID
- * @param string $kanbanGroup
- * @param string $from
+ * @param string $executionID
+ * @param string $taskID
+ * @param string $from ''|taskkanban
* @access public
* @return void
*/
- public function editTeam($executionID, $taskID, $kanbanGroup = 'default', $from = '')
+ public function manageTeam(string $executionID, string $taskID, string $from = '')
{
- $task = $this->task->getById($taskID);
+ $executionID = (int)$executionID;
+ $taskID = (int)$taskID;
$this->commonAction($taskID);
if(!empty($_POST))
{
$this->loadModel('action');
- $changes = $this->task->updateTeam($taskID);
+
+ /* Update assign of multi task. */
+ $postData = form::data($this->config->task->form->manageTeam);
+ $task = $this->taskZen->prepareManageTeam($postData, $taskID);
+ $changes = $this->task->updateTeam($task, $this->post->team, $this->post->teamSouce, $this->post->teamEstimate, $this->post->teamConsumed, $this->post->teamLeft);
if(dao::isError())
{
@@ -1927,43 +1934,19 @@ class task extends control
return print(js::error(dao::getError()));
}
+ /* Record log. */
$actionID = $this->action->create('task', $taskID, 'Edited');
$this->action->logHistory($actionID, $changes);
$this->executeHooks($taskID);
- if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'success'));
- if(isonlybody())
- {
- $execution = $this->execution->getByID($task->execution);
-
- if(($this->app->tab == 'execution' or ($this->config->vision == 'lite' and $this->app->tab == 'project' and $this->session->kanbanview == 'kanban')) and $execution->type == 'kanban')
- {
- $rdSearchValue = $this->session->rdSearchValue ? $this->session->rdSearchValue : '';
- $kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $execLaneType, 'id_desc', 0, $execGroupBy, $rdSearchValue);
- $kanbanData = json_encode($kanbanData);
-
- return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
- }
-
- if($from == 'taskkanban')
- {
- $rdSearchValue = $this->session->rdSearchValue ? $this->session->rdSearchValue : '';
- $kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', 0, $kanbanGroup, $rdSearchValue);
- $kanbanData = json_encode($kanbanData);
-
- return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
- }
-
- return print(js::closeModal('parent.parent', 'this'));
- }
- return print(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
+ $reponse = $this->taskZen->reponseAfterAssignTo($taskID, $from);
+ return is_array($reponse) ? $this->send($reponse) : $reponse;
}
- $this->view->task = $task;
$this->view->members = $this->loadModel('user')->getTeamMemberPairs($executionID, 'execution', 'nodeleted');
$this->view->users = $this->loadModel('user')->getPairs();
- $this->display('', 'editTeam');
+ $this->display('', 'editteam');
}
/**
diff --git a/module/task/model.php b/module/task/model.php
index d5fd6d5f2f..1d679d7f32 100755
--- a/module/task/model.php
+++ b/module/task/model.php
@@ -452,7 +452,7 @@ class taskModel extends model
* Manage multi task team members.
*
* @param string $mode
- * @param object $taskID
+ * @param object $task
* @param array $teamList
* @param array $teamSourceList
* @param array $teamEstimateList
@@ -469,10 +469,10 @@ class taskModel extends model
$this->dao->delete()->from(TABLE_TASKTEAM)->where('task')->eq($task->id)->exec();
/* If status of the task is doing, get the person who did not complete the task. */
+ $undoneUsers = array();
if($task->status == 'doing')
{
- $efforts = $this->getTaskEfforts($task->id);
- $undoneUsers = array();
+ $efforts = $this->getTaskEfforts($task->id);
foreach($efforts as $effort)
{
if($effort->left != 0) $undoneUsers[$effort->account] = $effort->account;
@@ -1140,14 +1140,15 @@ class taskModel extends model
}
/**
+ * 任务指派用户。
* Assign a task to a user again.
*
* @param object $task
* @param int $taskID
* @access public
- * @return array
+ * @return array|false
*/
- public function assign(object $task): array|false
+ public function assign(object $task, string $uid): array|false
{
$oldTask = $this->getById($task->id);
@@ -1159,11 +1160,10 @@ class taskModel extends model
if($oldTask->parent > 0) $this->updateParentStatus($task->id);
- $task = $this->loadModel('file')->processImgURL($task, $this->config->task->editor->assignto['id'], $this->post->uid);
+ $task = $this->loadModel('file')->processImgURL($task, $this->config->task->editor->assignto['id'], $uid);
$this->dao->update(TABLE_TASK)
->data($task)
->autoCheck()
- ->check('left', 'float')
->checkFlow()
->where('id')->eq($task->id)
->exec();
@@ -1172,56 +1172,46 @@ class taskModel extends model
}
/**
- * Update a task team.
+ * 更新团队信息。
+ * Update team.
*
- * @param int $taskID
+ * @param object $task
+ * @param array $team
+ * @param array $teamConsumed
+ * @param array $teamLeft
* @access public
- * @return void
+ * @return array|false
*/
- public function updateTeam($taskID)
+ public function updateTeam(object $task, array $team, array $teamSource, array $teamEstimate, array $teamConsumed, array $teamLeft): array|false
{
+ $taskID = $task->id;
$oldTask = $this->getById($taskID);
- foreach($this->post->team as $i => $account)
+
+ /* Check team data. */
+ foreach($team as $i => $account)
{
if(!$account) continue;
- if($this->post->teamConsumed[$i] == 0 and $this->post->teamLeft[$i] == 0)
+ if($teamConsumed[$i] == 0 and $teamLeft[$i] == 0)
{
dao::$errors[] = $this->lang->task->noticeTaskStart;
return false;
}
}
- $now = helper::now();
- $task = fixer::input('post')
- ->add('id', $taskID)
- ->setDefault('estimate, left, consumed', 0)
- ->setIF(is_numeric($this->post->estimate), 'estimate', (float)$this->post->estimate)
- ->setIF(is_numeric($this->post->consumed), 'consumed', (float)$this->post->consumed)
- ->setIF(is_numeric($this->post->left), 'left', (float)$this->post->left)
- ->setDefault('lastEditedBy', $this->app->user->account)
- ->setDefault('lastEditedDate', $now)
- ->setDefault('assignedDate', $now)
- ->stripTags($this->config->task->editor->assignto['id'], $this->config->allowedTags)
- ->remove('comment,showModule,team,teamEstimate,teamConsumed,teamLeft,teamSource')
- ->get();
-
- if(count(array_filter($this->post->team)) > 1)
+ /* Manage the team and calculate task work information. */
+ if(count(array_filter($team)) > 1)
{
- $teams = $this->manageTaskTeam($oldTask->mode, $taskID, $task->status);
+ $teams = $this->manageTaskTeam($oldTask->mode, $task, $team, $teamSource, $teamEstimate, $teamConsumed, $teamLeft);
if(!empty($teams)) $task = $this->computeHours4Multiple($oldTask, $task);
}
if(empty($teams)) $task->mode = '';
if($oldTask->parent > 0) $this->updateParentStatus($taskID);
- $task = $this->loadModel('file')->processImgURL($task, $this->config->task->editor->assignto['id'], $this->post->uid);
$this->dao->update(TABLE_TASK)
->data($task)
->autoCheck()
- ->checkIF($task->estimate != false, 'estimate', 'float')
- ->checkIF($task->left != false, 'left', 'float')
- ->checkIF($task->consumed != false, 'consumed', 'float')
->checkFlow()
->where('id')->eq($taskID)
->exec();
@@ -1955,6 +1945,7 @@ class taskModel extends model
*/
public function getByList($taskIDList = 0)
{
+ if(empty($taskIDList)) return array();
return $this->dao->select('*')->from(TABLE_TASK)
->where('deleted')->eq(0)
->beginIF($taskIDList)->andWhere('id')->in($taskIDList)->fi()
@@ -3339,7 +3330,14 @@ class taskModel extends model
$btnClass .= $task->assignedTo == 'closed' ? ' disabled' : '';
$btnClass .= ' iframe btn btn-icon-left btn-sm';
- $assignToLink = $task->assignedTo == 'closed' ? '#' : helper::createLink('task', 'assignTo', "executionID=$task->execution&taskID=$task->id", '', true);
+ if(!empty($task->team) and $task->mode == 'multi' and strpos('done,cencel,closed', $task->status) === false)
+ {
+ $assignToLink = $task->assignedTo == 'closed' ? '#' : helper::createLink('task', 'manageTeam', "executionID=$task->execution&taskID=$task->id", '', true);
+ }
+ else
+ {
+ $assignToLink = $task->assignedTo == 'closed' ? '#' : helper::createLink('task', 'assignTo', "executionID=$task->execution&taskID=$task->id", '', true);
+ }
$assignToHtml = html::a($assignToLink, " {$assignedToText}", '', "class='$btnClass'");
echo !common::hasPriv('task', 'assignTo', $task) ? "{$assignedToText}" : $assignToHtml;
@@ -3918,6 +3916,7 @@ class taskModel extends model
/* If both of lane id and column id are not empty, add task to the kanban cell. */
if($laneID and $columnID) $this->kanban->addKanbanCell($kanbanID, $laneID, $columnID, 'task', $task->id);
+
/* If lane id or column id is empty, update the task type lane of the kanban. */
if(!$laneID or !$columnID) $this->kanban->updateLane($kanbanID, 'task');
}
diff --git a/module/task/tao.php b/module/task/tao.php
index b7bac12155..d5cd3a61cf 100644
--- a/module/task/tao.php
+++ b/module/task/tao.php
@@ -545,7 +545,7 @@ class taskTao extends taskModel
}
elseif($task->status == 'doing')
{
- $teamSource = $teamSourceList[$row];
+ $teamSource = zget($teamSourceList, $row);
if(!empty($teamSource) and $teamSource != $account and isset($undoneUsers[$teamSource])) $member->transfer = $teamSource;
if(isset($undoneUsers[$account]) and ($mode == 'multi' or ($mode == 'linear' and $minStatus != 'wait'))) $member->status = 'doing';
diff --git a/module/task/test/model/aftercreate.php b/module/task/test/model/aftercreate.php
new file mode 100755
index 0000000000..519b3fbb1b
--- /dev/null
+++ b/module/task/test/model/aftercreate.php
@@ -0,0 +1,74 @@
+#!/usr/bin/env php
+id->range('1-4');
+$task->type->range('test,devel,design,story');
+$task->design->range('0{2},1,0{4}');
+$task->name->range('测试,开发,设计,需求')->postfix('任务1');
+$task->story->range('0{3},1');
+$task->status->range('wait');
+$task->gen(4);
+
+$bug = zdTable('bug');
+$bug->id->range(1);
+$bug->product->range('1');
+$bug->title->range('Bug1');
+$bug->gen(1);
+
+$todo = zdTable('todo');
+$todo->id->range(1);
+$todo->name->range('待办1');
+$todo->gen(1);
+
+$design = zdTable('design');
+$design->id->range(1);
+$design->name->range('设计1');
+$design->gen(1);
+
+$story = zdTable('story');
+$story->id->range('1-5');
+$story->product->range('1');
+$story->title->range('1-5')->prefix('需求');
+$story->type->range('story');
+$story->gen(5);
+
+/**
+
+title=测试taskModel->afterCreate();
+timeout=0
+cid=1
+
+*/
+
+$taskIdList['test'] = array(1);
+$taskIdList['todo'] = array(2);
+$taskIdList['design'] = array(3);
+$taskIdList['story'] = array(4);
+
+$testTasks[2] = new stdclass();
+$testTasks[2]->name = '测试子任务1';
+$testTasks[2]->type = 'test';
+$testTasks[2]->mailto = '';
+
+$testTasks[3] = new stdclass();
+$testTasks[3]->name = '测试子任务2';
+$testTasks[3]->type = 'test';
+$testTasks[3]->mailto = '';
+
+$taskTester = new taskTest();
+r($taskTester->afterCreateTest()) && p() && e('0'); // 测试空数据
+r($taskTester->afterCreateTest(0, $taskIdList['test'])) && p() && e('0'); // 测试taskID为空的情况
+r($taskTester->afterCreateTest(5, $taskIdList['test'])) && p() && e('0'); // 测试taskID不存在的情况
+r($taskTester->afterCreateTest(1)) && p('name') && e('测试任务1'); // 测试taskIdList为空的情况
+r($taskTester->afterCreateTest(1, array(), 1)) && p('title') && e('Bug1'); // 测试taskIdList为空,但是有BugID的情况
+r($taskTester->afterCreateTest(1, array(), 0, 1)) && p('name') && e('待办1'); // 测试taskIdList为空,但是有todoID的情况
+r($taskTester->afterCreateTest(1, array(), 0, 0, $testTasks)) && p('name') && e('测试任务1'); // 测试taskIdList为空,但是有testTasks的情况
+r($taskTester->afterCreateTest(1, $taskIdList['test'], 1)) && p('toTask') && e('1'); // 测试Bug转任务后,更新Bug的信息
+r($taskTester->afterCreateTest(2, $taskIdList['todo'], 0, 1)) && p('status') && e('done'); // 测试待办转任务后,更新待办的信息
+r($taskTester->afterCreateTest(3, $taskIdList['design'])) && p('designVersion') && e('1'); // 测试任务关联设计后,更新任务中的designVersion字段
+r($taskTester->afterCreateTest(4, $taskIdList['story'])) && p('stage') && e('planned'); // 测试任务关联需求后,更新需求的阶段
+r($taskTester->afterCreateTest(1, $taskIdList['test'], 0, 0, $testTasks)) && p('parent') && e('-1'); // 测试任务创建子任务后,父任务的parent字段的值
diff --git a/module/task/test/model/assign.php b/module/task/test/model/assign.php
index 0881dd1338..9e498c60d4 100755
--- a/module/task/test/model/assign.php
+++ b/module/task/test/model/assign.php
@@ -10,43 +10,41 @@ title=taskModel->assign();
timeout=0
cid=1
-- 执行task模块的assign方法,参数是$taskIDlist[0],$waitTask
+- wait状态任务指派
- 第0条的field属性 @assignedTo
- 第0条的old属性 @old1
- 第0条的new属性 @user92
-- 执行task模块的assign方法,参数是$taskIDlist[0],$waitTaskLeft
+- wait状态任务指派修改预计剩余
- 第1条的field属性 @left
- 第1条的old属性 @0
- 第1条的new属性 @1
-- 执行task模块的assign方法,参数是$taskIDlist[1],$doingTask
+- doing状态任务指派
- 第0条的field属性 @assignedTo
- 第0条的old属性 @old2
- 第0条的new属性 @user93
-- 执行task模块的assign方法,参数是$taskIDlist[2],$doneTask
+- done状态任务指派
- 第0条的field属性 @assignedTo
- 第0条的old属性 @old3
- 第0条的new属性 @user94
-- 执行task模块的assign方法,参数是$taskIDlist[3],$pauseTask
+- pause状态任务指派
- 第0条的field属性 @assignedTo
- 第0条的old属性 @old4
- 第0条的new属性 @user95
-- 执行task模块的assign方法,参数是$taskIDlist[4],$cancelTask
+- cancel状态任务指派
- 第0条的field属性 @assignedTo
- 第0条的old属性 @old5
- 第0条的new属性 @user96
-- 执行task模块的assign方法,参数是$taskIDlist[5],$closedTask
+- closed状态任务指派
- 第0条的field属性 @assignedTo
- 第0条的old属性 @old6
- 第0条的new属性 @user97
-
-
*/
function initData()
@@ -87,4 +85,4 @@ r($task->assignTest($taskIDlist[1],$doingTask)) && p('0:field,old,new') && e('a
r($task->assignTest($taskIDlist[2],$doneTask)) && p('0:field,old,new') && e('assignedTo,old3,user94'); // done状态任务指派
r($task->assignTest($taskIDlist[3],$pauseTask)) && p('0:field,old,new') && e('assignedTo,old4,user95'); // pause状态任务指派
r($task->assignTest($taskIDlist[4],$cancelTask)) && p('0:field,old,new') && e('assignedTo,old5,user96'); // cancel状态任务指派
-r($task->assignTest($taskIDlist[5],$closedTask)) && p('0:field,old,new') && e('assignedTo,old6,user97'); // closed状态任务指派
\ No newline at end of file
+r($task->assignTest($taskIDlist[5],$closedTask)) && p('0:field,old,new') && e('assignedTo,old6,user97'); // closed状态任务指派
diff --git a/module/task/test/model/updateteam.php b/module/task/test/model/updateteam.php
new file mode 100644
index 0000000000..140f13ceb3
--- /dev/null
+++ b/module/task/test/model/updateteam.php
@@ -0,0 +1,44 @@
+#!/usr/bin/env php
+updateTeam();
+timeout=0
+cid=1
+
+- 分配2个成员团队后任务
+ - 第1条的field属性 @estimate
+ - 第1条的old属性 @0
+ - 第1条的new属性 @3.5
+
+- 分配1个成员团队后任务
+ - 第1条的field属性 @mode
+ - 第1条的old属性 @multi
+ - 第1条的new属性 @~~
+
+- 分配预计剩余为0工时团队后任务 @总计消耗"和"预计剩余"不能同时为0
+
+*/
+
+function initData()
+{
+ $task = zdTable('task');
+ $task->mode->range('multi');
+ $task->gen(6);
+
+ $user = zdTable('user')->gen(50);
+}
+
+initData();
+$taskIDList = array('1','2','3','4','5','6');
+$taskStatusList = array('doing','wait','done');
+$teamList = array('user1','user2','user3');
+
+$task = new taskTest();
+r($task->updateTeamTest($taskIDList[0], $taskStatusList[1], array($teamList[0], $teamList[1]), array($teamList[0], $teamList[1]), $teamEstimateList = array(1, 2.5), $teamConsumedList = array(0, 0), $teamLeftList = array(1, 0.5))) && p('1:field,old,new') && e('estimate,0,3.5'); //分配2个成员团队后任务
+r($task->updateTeamTest($taskIDList[1], $taskStatusList[1], array($teamList[0]), array($teamList[0]), $teamEstimateList = array(1), $teamConsumedList = array(0), $teamLeftList = array(1))) && p('1:field,old,new') && e('mode,multi,~~'); //分配1个成员团队后任务
+r($task->updateTeamTest($taskIDList[2], $taskStatusList[1], array($teamList[0], $teamList[1]), array($teamList[0], $teamList[1]), $teamEstimateList = array(1, 2.5), $teamConsumedList = array(0, 0), $teamLeftList = array(0, 0))) && p() && e('"总计消耗"和"预计剩余"不能同时为0'); //分配预计剩余为0工时团队后任务
diff --git a/module/task/test/tao/batchcomputeprogress.php b/module/task/test/tao/batchcomputeprogress.php
index d60aed8d18..c6ab7d5ce9 100755
--- a/module/task/test/tao/batchcomputeprogress.php
+++ b/module/task/test/tao/batchcomputeprogress.php
@@ -19,6 +19,16 @@ title=taskModel->batchComputeProgress();
timeout=0
cid=2
+sed: can't read /home/tianshujie/repo/zentaopms/test/config/my.php: No such file or directory
+- 测试任务消耗工时为0,剩余工时为0的情况第1条的progress属性 @0
+
+- 测试任务消耗工时不为0,剩余工时为0的情况第2条的progress属性 @100
+
+- 测试任务消耗工时为15,剩余工时为1的情况第3条的progress属性 @94
+
+- 测试任务消耗工时为20,剩余工时为5的情况第4条的progress属性 @80
+
+- 测试任务消耗工时为25,剩余工时为10的情况第5条的progress属性 @71
*/
$tester->loadModel('task');
@@ -32,4 +42,4 @@ r($tester->task->batchComputeProgress($taskList)) && p('1:progress') && e('0');
r($tester->task->batchComputeProgress($taskList)) && p('2:progress') && e('100'); // 测试任务消耗工时不为0,剩余工时为0的情况
r($tester->task->batchComputeProgress($taskList)) && p('3:progress') && e('94'); // 测试任务消耗工时为15,剩余工时为1的情况
r($tester->task->batchComputeProgress($taskList)) && p('4:progress') && e('80'); // 测试任务消耗工时为20,剩余工时为5的情况
-r($tester->task->batchComputeProgress($taskList)) && p('5:progress') && e('71'); // 测试任务消耗工时为25,剩余工时为10的情况
+r($tester->task->batchComputeProgress($taskList)) && p('5:progress') && e('71'); // 测试任务消耗工时为25,剩余工时为10的情况
\ No newline at end of file
diff --git a/module/task/test/tao/buildtasktree.php b/module/task/test/tao/buildtasktree.php
index 0e9d143261..e05439a036 100755
--- a/module/task/test/tao/buildtasktree.php
+++ b/module/task/test/tao/buildtasktree.php
@@ -22,6 +22,25 @@ title=taskModel->buildTaskTree();
timeout=0
cid=1
+sed: can't read /home/tianshujie/repo/zentaopms/test/config/my.php: No such file or directory
+- 测试空数据的情况 @0
+
+- 测试数据中有父任务时,重构结构后的任务数量 @6
+
+- 测试数据中有父任务时,重构结构后子任务的数据第children[4]条的name属性 @子任务4
+
+- 测试数据中没有父任务时,重构结构后的任务数量 @6
+
+- 测试数据中没有父任务时,重构结构后的子任务中父任务的名称第4条的parentName属性 @父任务1
+
+- 测试数据中有父子任务时,重构结构后的子任务中父任务的名称第1条的name属性 @父任务1
+
+- 测试数据中有父子任务时,重构结构后的任务数量 @2
+
+- 测试数据中只有父任务时,重构结构后的父任务的名称第1条的name属性 @父任务1
+
+- 测试数据中只有父任务时,重构结构后的任务数量 @3
+
*/
$taskTester = new taskTest();
@@ -49,4 +68,4 @@ r($notParentTasks) && p('4:parentName') && e('父任务1'); // 测试
r($hasParentTasks) && p('1:name') && e('父任务1'); // 测试数据中有父子任务时,重构结构后的子任务中父任务的名称
r($hasParentTasksCount) && p() && e('2'); // 测试数据中有父子任务时,重构结构后的任务数量
r($parentTasks) && p('1:name') && e('父任务1'); // 测试数据中只有父任务时,重构结构后的父任务的名称
-r($parentTasksCount) && p() && e('3'); // 测试数据中只有父任务时,重构结构后的任务数量
+r($parentTasksCount) && p() && e('3'); // 测试数据中只有父任务时,重构结构后的任务数量
\ No newline at end of file
diff --git a/module/task/test/tao/computecurrenttaskstatus.php b/module/task/test/tao/computecurrenttaskstatus.php
index 12330b9202..aae518b794 100755
--- a/module/task/test/tao/computecurrenttaskstatus.php
+++ b/module/task/test/tao/computecurrenttaskstatus.php
@@ -65,92 +65,91 @@ title=taskModel->computeCurrentTaskStatus();
timeout=0
cid=1
-- 执行$task1
+sed: can't read /home/tianshujie/repo/zentaopms/test/config/my.php: No such file or directory
+- 查询 task1 情况的task信息 currentTask[0] taskID 1 currentTasksestimate 状态自动变更 没有工时消耗 团队成员members[0]
- 属性status @doing
- 属性assignedTo @user1
- 属性estimate @9
- 属性left @0
- 属性consumed @10
-- 执行$task2
+- 查询 task2 情况的task信息 currentTask[0] taskID 1 currentTasksestimate 状态自动变更 没有工时消耗 团队成员members[0]
- 属性status @doing
- 属性assignedTo @user1
- 属性estimate @9
- 属性left @0
- 属性consumed @10
-- 执行$task3
+- 查询 task3 情况的task信息 currentTask[0] taskID 1 currentTasksestimate 状态自动变更 没有工时消耗 团队成员members[0]
- 属性status @doing
- 属性assignedTo @user1
- 属性estimate @9
- 属性left @0
- 属性consumed @10
-- 执行$task4
+- 查询 task4 情况的task信息 currentTask[0] taskID 1 currentTasksestimate 状态非自动变更 没有工时消耗 团队成员members[0]
- 属性status @doing
- 属性assignedTo @user1
- 属性estimate @9
- 属性left @0
- 属性consumed @10
-- 执行$task5
+- 查询 task5 情况的task信息 currentTask[0] taskID 1 currentTasksestimate 状态非自动变更 有工时消耗 团队成员members[0]
- 属性status @doing
- 属性assignedTo @user1
- 属性estimate @9
- 属性left @0
- 属性consumed @10
-- 执行$task6
+- 查询 task6 情况的task信息 currentTask[0] taskID 1 currentTasksestimate 状态非自动变更 有工时消耗 团队成员members[1]
- 属性status @doing
- 属性assignedTo @user1
- 属性estimate @9
- 属性left @0
- 属性consumed @10
-- 执行$task7
+- 查询 task7 情况的task信息 currentTask[1] taskID 2 currentTasksestimate 状态自动变更 有工时消耗 团队成员members[0]
- 属性status @done
- 属性assignedTo @admin
- 属性estimate @8
- 属性left @8
- 属性consumed @0
-- 执行$task8
+- 查询 task8 情况的task信息 currentTask[1] taskID 2 currentTasksestimate 状态自动变更 有工时消耗 团队成员members[0]
- 属性status @done
- 属性assignedTo @admin
- 属性estimate @8
- 属性left @8
- 属性consumed @0
-- 执行$task9
+- 查询 task9 情况的task信息 currentTask[1] taskID 2 currentTasksestimate 状态自动变更 有工时消耗 团队成员members[0]
- 属性status @done
- 属性assignedTo @admin
- 属性estimate @8
- 属性left @8
- 属性consumed @0
-- 执行$task10
+- 查询 task10 情况的task信息 currentTask[1] taskID 2 currentTasksestimate 状态非自动变更 有工时消耗 团队成员members[0]
- 属性status @done
- 属性assignedTo @admin
- 属性estimate @8
- 属性left @8
- 属性consumed @0
-- 执行$task11
+- 查询 task11 情况的task信息 currentTask[1] taskID 2 currentTasksestimate 状态非自动变更 没有工时消耗 团队成员members[0]
- 属性status @done
- 属性assignedTo @admin
- 属性estimate @8
- 属性left @8
- 属性consumed @0
-- 执行$task12
+- 查询 task12 情况的task信息 currentTask[1] taskID 2 currentTasksestimate 状态非自动变更 没有工时消耗 团队成员members[1]
- 属性status @done
- 属性assignedTo @admin
- 属性estimate @8
- 属性left @8
- 属性consumed @0
-
-
*/
$task = new taskTest();
diff --git a/module/task/test/tao/computetaskprogress.php b/module/task/test/tao/computetaskprogress.php
index d5b6d9966a..2cd5e358e3 100755
--- a/module/task/test/tao/computetaskprogress.php
+++ b/module/task/test/tao/computetaskprogress.php
@@ -16,8 +16,20 @@ function initData()
/**
title=测试computeTaskProgress
+timeout=0
cid=1
+sed: can't read /home/tianshujie/repo/zentaopms/test/config/my.php: No such file or directory
+- 测试任务消耗工时为0,剩余工时为0的情况 @0
+
+- 测试任务消耗工时不为0,剩余工时为0的情况 @100
+
+- 测试任务消耗工时为15,剩余工时为1的情况 @94
+
+- 测试任务消耗工时为20,剩余工时为5的情况 @80
+
+- 测试任务消耗工时为25,剩余工时为10的情况 @71
+
*/
initData();
@@ -30,4 +42,4 @@ r($tester->task->computeTaskProgress($taskList[1])) && p() && e('0'); //测试
r($tester->task->computeTaskProgress($taskList[2])) && p() && e('100'); //测试任务消耗工时不为0,剩余工时为0的情况
r($tester->task->computeTaskProgress($taskList[3])) && p() && e('94'); //测试任务消耗工时为15,剩余工时为1的情况
r($tester->task->computeTaskProgress($taskList[4])) && p() && e('80'); //测试任务消耗工时为20,剩余工时为5的情况
-r($tester->task->computeTaskProgress($taskList[5])) && p() && e('71'); //测试任务消耗工时为25,剩余工时为10的情况
+r($tester->task->computeTaskProgress($taskList[5])) && p() && e('71'); //测试任务消耗工时为25,剩余工时为10的情况
\ No newline at end of file
diff --git a/module/task/test/tao/docreate.php b/module/task/test/tao/docreate.php
index b96669178c..af5e401fe7 100755
--- a/module/task/test/tao/docreate.php
+++ b/module/task/test/tao/docreate.php
@@ -12,6 +12,95 @@ title=taskModel->doCreate();
timeout=0
cid=2
+sed: can't read /home/tianshujie/repo/zentaopms/test/config/my.php: No such file or directory
+- 测试正常的创建开发任务
+ - 属性name @开发任务一
+ - 属性execution @101
+ - 属性type @devel
+ - 属性estimate @1
+ - 属性version @1
+ - 属性estStarted @0000-00-00
+ - 属性deadline @0000-00-00
+
+- 测试正常的创建设计任务
+ - 属性name @设计任务一
+ - 属性execution @101
+ - 属性type @design
+ - 属性estimate @1
+ - 属性version @1
+ - 属性estStarted @2023-04-01
+ - 属性deadline @0000-00-00
+
+- 测试正常的创建需求任务
+ - 属性name @需求任务一
+ - 属性execution @101
+ - 属性type @request
+ - 属性estimate @1
+ - 属性version @1
+ - 属性estStarted @0000-00-00
+ - 属性deadline @2024-01-01
+
+- 测试正常的创建测试任务
+ - 属性name @测试任务一
+ - 属性execution @101
+ - 属性type @test
+ - 属性estimate @1
+ - 属性version @1
+ - 属性estStarted @0000-00-00
+ - 属性deadline @0000-00-00
+
+- 测试正常的创建研究任务
+ - 属性name @研究任务一
+ - 属性execution @101
+ - 属性type @study
+ - 属性estimate @1
+ - 属性version @1
+ - 属性estStarted @2023-04-01
+ - 属性deadline @2024-01-01
+
+- 测试正常的创建讨论任务
+ - 属性name @讨论任务一
+ - 属性execution @101
+ - 属性type @discuss
+ - 属性estimate @0
+ - 属性version @1
+ - 属性estStarted @2021-01-10
+ - 属性deadline @2021-03-19
+
+- 测试正常的创建界面任务
+ - 属性name @界面任务一
+ - 属性execution @101
+ - 属性type @ui
+ - 属性estimate @1
+ - 属性version @1
+ - 属性estStarted @2021-01-10
+ - 属性deadline @2021-03-19
+
+- 测试正常的创建事务任务
+ - 属性name @事务任务一
+ - 属性execution @101
+ - 属性type @affair
+ - 属性estimate @1
+ - 属性version @1
+ - 属性estStarted @2021-01-10
+ - 属性deadline @2021-03-19
+
+- 测试正常的创建其他任务
+ - 属性name @其他任务一
+ - 属性execution @101
+ - 属性type @misc
+ - 属性estimate @1
+ - 属性version @1
+ - 属性estStarted @2021-01-10
+ - 属性deadline @2021-03-19
+
+- 测试不输入执行创建任务 @『所属执行』不能为空。
+
+- 测试不输入名称创建任务 @『任务名称』不能为空。
+
+- 测试不输入类型创建任务 @『任务类型』不能为空。
+
+- 测试不输入类型创建任务 @『最初预计』应当是数字,可以是小数。
*/
$devel = array('execution' => 101, 'name' => '开发任务一', 'type' => 'devel', 'estimate' => 1, 'version' => 1, 'estStarted' => null, 'deadline' => null);
@@ -42,4 +131,4 @@ r($task->doCreateObject($misc)) && p('name,execution,type,estimate,vers
r($task->doCreateObject($noexecution)) && p('execution:0') && e('『所属执行』不能为空。'); // 测试不输入执行创建任务
r($task->doCreateObject($noname)) && p('name:0') && e('『任务名称』不能为空。'); // 测试不输入名称创建任务
r($task->doCreateObject($notype)) && p('type:0') && e('『任务类型』不能为空。'); // 测试不输入类型创建任务
-r($task->doCreateObject($errorEstimate)) && p('estimate:0') && e('『最初预计』应当是数字,可以是小数。'); // 测试不输入类型创建任务
+r($task->doCreateObject($errorEstimate)) && p('estimate:0') && e('『最初预计』应当是数字,可以是小数。'); // 测试不输入类型创建任务
\ No newline at end of file
diff --git a/module/task/test/tao/fetchexecutiontasks.php b/module/task/test/tao/fetchexecutiontasks.php
index 12c641ef88..336ff4b522 100755
--- a/module/task/test/tao/fetchexecutiontasks.php
+++ b/module/task/test/tao/fetchexecutiontasks.php
@@ -64,163 +64,162 @@ title=taskModel->fetchExecutionTasks();
timeout=0
cid=1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[0], $productIdList[0], $type[0], $modules[0], $orderBy[0], $count[0]属性 @0
+sed: can't read /home/tianshujie/repo/zentaopms/test/config/my.php: No such file or directory
+- 测试获取执行ID 0 product 0 type all module 空 orederBy 'status_asc, id_desc' 的任务 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[0], $productIdList[0], $type[0], $modules[0], $orderBy[0], $count[1]属性 @0
+- 测试获取执行ID 0 product 0 type all module 空 orederBy 'status_asc, id_desc' 的任务数量 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[0], $type[0], $modules[0], $orderBy[0], $count[0]第1条的name属性 @任务1
+- 测试获取执行ID 1 product 0 type all module 空 orederBy 'status_asc, id_desc' 的任务第1条的name属性 @任务1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[0], $type[0], $modules[0], $orderBy[0], $count[1]属性 @10
+- 测试获取执行ID 1 product 0 type all module 空 orederBy 'status_asc, id_desc' 的任务数量 @10
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[0], $modules[0], $orderBy[0], $count[0]第1条的name属性 @任务1
+- 测试获取执行ID 1 product 1 type all module 空 orederBy 'status_asc, id_desc' 的任务第1条的name属性 @任务1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[0], $modules[0], $orderBy[0], $count[1]属性 @2
+- 测试获取执行ID 1 product 1 type all module 空 orederBy 'status_asc, id_desc' 的任务数量 @2
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[1], $modules[0], $orderBy[0], $count[0]属性 @0
+- 测试获取执行ID 1 product 1 type assignedbyme module 空 orederBy 'status_asc, id_desc' 的任务 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[1], $modules[0], $orderBy[0], $count[1]属性 @0
+- 测试获取执行ID 1 product 1 type assignedbyme module 空 orederBy 'status_asc, id_desc' 的任务数量 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[2], $modules[0], $orderBy[0], $count[0]第1条的name属性 @任务1
+- 测试获取执行ID 1 product 1 type myinvolved module 空 orederBy 'status_asc, id_desc' 的任务第1条的name属性 @任务1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[2], $modules[0], $orderBy[0], $count[1]属性 @1
+- 测试获取执行ID 1 product 1 type myinvolved module 空 orederBy 'status_asc, id_desc' 的任务数量 @1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[3], $modules[0], $orderBy[0], $count[0]第1条的name属性 @任务1
+- 测试获取执行ID 1 product 1 type undone module 空 orederBy 'status_asc, id_desc' 的任务第1条的name属性 @任务1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[3], $modules[0], $orderBy[0], $count[1]属性 @2
+- 测试获取执行ID 1 product 1 type undone module 空 orederBy 'status_asc, id_desc' 的任务数量 @2
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[4], $modules[0], $orderBy[0], $count[0]属性 @0
+- 测试获取执行ID 1 product 1 type needconfirm module 空 orederBy 'status_asc, id_desc' 的任务 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[4], $modules[0], $orderBy[0], $count[1]属性 @0
+- 测试获取执行ID 1 product 1 type needconfirm module 空 orederBy 'status_asc, id_desc' 的任务数量 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[5], $modules[0], $orderBy[0], $count[0]第1条的name属性 @任务1
+- 测试获取执行ID 1 product 1 type assignedtome module 空 orederBy 'status_asc, id_desc' 的任务第1条的name属性 @任务1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[5], $modules[0], $orderBy[0], $count[1]属性 @1
+- 测试获取执行ID 1 product 1 type assignedtome module 空 orederBy 'status_asc, id_desc' 的任务数量 @1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[6], $modules[0], $orderBy[0], $count[0]第1条的name属性 @任务1
+- 测试获取执行ID 1 product 1 type finishedbyme module 空 orederBy 'status_asc, id_desc' 的任务第1条的name属性 @任务1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[6], $modules[0], $orderBy[0], $count[1]属性 @1
+- 测试获取执行ID 1 product 1 type finishedbyme module 空 orederBy 'status_asc, id_desc' 的任务数量 @1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[7], $modules[0], $orderBy[0], $count[0]第1条的name属性 @任务1
+- 测试获取执行ID 1 product 1 type delayed module 空 orederBy 'status_asc, id_desc' 的任务第1条的name属性 @任务1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[7], $modules[0], $orderBy[0], $count[1]属性 @2
+- 测试获取执行ID 1 product 1 type delayed module 空 orederBy 'status_asc, id_desc' 的任务数量 @2
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[8], $modules[0], $orderBy[0], $count[0]第1条的name属性 @任务1
+- 测试获取执行ID 1 product 1 type wait module 空 orederBy 'status_asc, id_desc' 的任务第1条的name属性 @任务1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[8], $modules[0], $orderBy[0], $count[1]属性 @1
+- 测试获取执行ID 1 product 1 type wait module 空 orederBy 'status_asc, id_desc' 的任务数量 @1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[9], $modules[0], $orderBy[0], $count[0]第11条的name属性 @任务11
+- 测试获取执行ID 1 product 1 type doing module 空 orederBy 'status_asc, id_desc' 的任务第11条的name属性 @任务11
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[9], $modules[0], $orderBy[0], $count[1]属性 @1
+- 测试获取执行ID 1 product 1 type doing module 空 orederBy 'status_asc, id_desc' 的任务数量 @1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[10], $modules[0], $orderBy[0], $count[0]属性 @0
+- 测试获取执行ID 1 product 1 type done module 空 orederBy 'status_asc, id_desc' 的任务 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[10], $modules[0], $orderBy[0], $count[1]属性 @0
+- 测试获取执行ID 1 product 1 type done module 空 orederBy 'status_asc, id_desc' 的任务数量 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[11], $modules[0], $orderBy[0], $count[0]属性 @0
+- 测试获取执行ID 1 product 1 type pause module 空 orederBy 'status_asc, id_desc' 的任务 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[11], $modules[0], $orderBy[0], $count[1]属性 @0
+- 测试获取执行ID 1 product 1 type pause module 空 orederBy 'status_asc, id_desc' 的任务数量 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[12], $modules[0], $orderBy[0], $count[0]属性 @0
+- 测试获取执行ID 1 product 1 type cancel module 空 orederBy 'status_asc, id_desc' 的任务 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[12], $modules[0], $orderBy[0], $count[1]属性 @0
+- 测试获取执行ID 1 product 1 type cancel module 空 orederBy 'status_asc, id_desc' 的任务数量 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[13], $modules[0], $orderBy[0], $count[0]第1条的name属性 @任务1
+- 测试获取执行ID 1 product 1 type array('wait', 'doing', 'done', 'pause', 'cancel') module 空 orederBy 'status_asc, id_desc' 的任务第1条的name属性 @任务1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[1], $type[13], $modules[0], $orderBy[0], $count[1]属性 @2
+- 测试获取执行ID 1 product 1 type array('wait', 'doing', 'done', 'pause', 'cancel') module 空 orederBy 'status_asc, id_desc' 的任务数量 @2
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[0], $type[0], $modules[1], $orderBy[0], $count[0]第17条的name属性 @任务17
+- 测试获取执行ID 1 product 0 type all module array(2) orederBy 'status_asc, id_desc' 的任务第17条的name属性 @任务17
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[0], $type[0], $modules[1], $orderBy[0], $count[1]属性 @2
+- 测试获取执行ID 1 product 0 type all module array(2) orederBy 'status_asc, id_desc' 的任务数量 @2
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[0], $type[0], $modules[2], $orderBy[0], $count[0]属性 @0
+- 测试获取执行ID 1 product 0 type all module array(8) orederBy 'status_asc, id_desc' 的任务 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[0], $type[0], $modules[2], $orderBy[0], $count[1]属性 @0
+- 测试获取执行ID 1 product 0 type all module array(8) orederBy 'status_asc, id_desc' 的任务数量 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[0], $type[0], $modules[3], $orderBy[0], $count[0]第17条的name属性 @任务17
+- 测试获取执行ID 1 product 0 type all module array(2,8) orederBy 'status_asc, id_desc' 的任务第17条的name属性 @任务17
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[0], $type[0], $modules[3], $orderBy[0], $count[1]属性 @2
+- 测试获取执行ID 1 product 0 type all module array(2,8) orederBy 'status_asc, id_desc' 的任务数量 @2
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[0], $type[0], $modules[0], $orderBy[1], $count[0]第1条的name属性 @任务1
+- 测试获取执行ID 1 product 0 type all module 空 orederBy 'pri_desc' 的任务第1条的name属性 @任务1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[1], $productIdList[0], $type[0], $modules[0], $orderBy[1], $count[1]属性 @10
+- 测试获取执行ID 1 product 0 type all module 空 orederBy 'pri_desc' 的任务数量 @10
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[0], $type[0], $modules[0], $orderBy[0], $count[0]第18条的name属性 @任务18
+- 测试获取执行ID 2 product 0 type all module 空 orederBy 'status_asc, id_desc' 的任务第18条的name属性 @任务18
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[0], $type[0], $modules[0], $orderBy[0], $count[1]属性 @10
+- 测试获取执行ID 2 product 0 type all module 空 orederBy 'status_asc, id_desc' 的任务数量 @10
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[0], $modules[0], $orderBy[0], $count[0]第6条的name属性 @任务6
+- 测试获取执行ID 2 product 1 type all module 空 orederBy 'status_asc, id_desc' 的任务第6条的name属性 @任务6
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[0], $modules[0], $orderBy[0], $count[1]属性 @2
+- 测试获取执行ID 2 product 1 type all module 空 orederBy 'status_asc, id_desc' 的任务数量 @2
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[1], $modules[0], $orderBy[0], $count[0]属性 @0
+- 测试获取执行ID 2 product 1 type assignedbyme module 空 orederBy 'status_asc, id_desc' 的任务 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[1], $modules[0], $orderBy[0], $count[1]属性 @0
+- 测试获取执行ID 2 product 1 type assignedbyme module 空 orederBy 'status_asc, id_desc' 的任务数量 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[2], $modules[0], $orderBy[0], $count[0]第6条的name属性 @任务6
+- 测试获取执行ID 2 product 1 type myinvolved module 空 orederBy 'status_asc, id_desc' 的任务第6条的name属性 @任务6
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[2], $modules[0], $orderBy[0], $count[1]属性 @2
+- 测试获取执行ID 2 product 1 type myinvolved module 空 orederBy 'status_asc, id_desc' 的任务数量 @2
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[3], $modules[0], $orderBy[0], $count[0]第6条的name属性 @任务6
+- 测试获取执行ID 2 product 1 type undone module 空 orederBy 'status_asc, id_desc' 的任务第6条的name属性 @任务6
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[3], $modules[0], $orderBy[0], $count[1]属性 @1
+- 测试获取执行ID 2 product 1 type undone module 空 orederBy 'status_asc, id_desc' 的任务数量 @1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[4], $modules[0], $orderBy[0], $count[0]第6条的name属性 @任务6
+- 测试获取执行ID 2 product 1 type needconfirm module 空 orederBy 'status_asc, id_desc' 的任务第6条的name属性 @任务6
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[4], $modules[0], $orderBy[0], $count[1]属性 @2
+- 测试获取执行ID 2 product 1 type needconfirm module 空 orederBy 'status_asc, id_desc' 的任务数量 @2
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[5], $modules[0], $orderBy[0], $count[0]第6条的name属性 @任务6
+- 测试获取执行ID 2 product 1 type assignedtome module 空 orederBy 'status_asc, id_desc' 的任务第6条的name属性 @任务6
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[5], $modules[0], $orderBy[0], $count[1]属性 @2
+- 测试获取执行ID 2 product 1 type assignedtome module 空 orederBy 'status_asc, id_desc' 的任务数量 @2
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[6], $modules[0], $orderBy[0], $count[0]第6条的name属性 @任务6
+- 测试获取执行ID 2 product 1 type finishedbyme module 空 orederBy 'status_asc, id_desc' 的任务第6条的name属性 @任务6
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[6], $modules[0], $orderBy[0], $count[1]属性 @2
+- 测试获取执行ID 2 product 1 type finishedbyme module 空 orederBy 'status_asc, id_desc' 的任务数量 @2
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[7], $modules[0], $orderBy[0], $count[0]属性 @0
+- 测试获取执行ID 2 product 1 type delayed module 空 orederBy 'status_asc, id_desc' 的任务 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[7], $modules[0], $orderBy[0], $count[1]属性 @0
+- 测试获取执行ID 2 product 1 type delayed module 空 orederBy 'status_asc, id_desc' 的任务数量 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[8], $modules[0], $orderBy[0], $count[0]属性 @0
+- 测试获取执行ID 2 product 1 type wait module 空 orederBy 'status_asc, id_desc' 的任务 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[8], $modules[0], $orderBy[0], $count[1]属性 @0
+- 测试获取执行ID 2 product 1 type wait module 空 orederBy 'status_asc, id_desc' 的任务数量 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[9], $modules[0], $orderBy[0], $count[0]属性 @0
+- 测试获取执行ID 2 product 1 type doing module 空 orederBy 'status_asc, id_desc' 的任务 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[9], $modules[0], $orderBy[0], $count[1]属性 @0
+- 测试获取执行ID 2 product 1 type doing module 空 orederBy 'status_asc, id_desc' 的任务数量 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[10], $modules[0], $orderBy[0], $count[0]属性 @0
+- 测试获取执行ID 2 product 1 type done module 空 orederBy 'status_asc, id_desc' 的任务 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[10], $modules[0], $orderBy[0], $count[1]属性 @0
+- 测试获取执行ID 2 product 1 type done module 空 orederBy 'status_asc, id_desc' 的任务数量 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[11], $modules[0], $orderBy[0], $count[0]第6条的name属性 @任务6
+- 测试获取执行ID 2 product 1 type pause module 空 orederBy 'status_asc, id_desc' 的任务第6条的name属性 @任务6
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[11], $modules[0], $orderBy[0], $count[1]属性 @1
+- 测试获取执行ID 2 product 1 type pause module 空 orederBy 'status_asc, id_desc' 的任务数量 @1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[12], $modules[0], $orderBy[0], $count[0]属性 @0
+- 测试获取执行ID 2 product 1 type cancel module 空 orederBy 'status_asc, id_desc' 的任务 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[12], $modules[0], $orderBy[0], $count[1]属性 @0
+- 测试获取执行ID 2 product 1 type cancel module 空 orederBy 'status_asc, id_desc' 的任务数量 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[13], $modules[0], $orderBy[0], $count[0]第6条的name属性 @任务6
+- 测试获取执行ID 2 product 1 type array('wait', 'doing', 'done', 'pause', 'cancel') module 空 orederBy 'status_asc, id_desc' 的任务第6条的name属性 @任务6
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[1], $type[13], $modules[0], $orderBy[0], $count[1]属性 @1
+- 测试获取执行ID 2 product 1 type array('wait', 'doing', 'done', 'pause', 'cancel') module 空 orederBy 'status_asc, id_desc' 的任务数量 @1
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[0], $type[0], $modules[1], $orderBy[0], $count[0]第2条的name属性 @任务2
+- 测试获取执行ID 2 product 0 type all module array(2) orederBy 'status_asc, id_desc' 的任务第2条的name属性 @任务2
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[0], $type[0], $modules[1], $orderBy[0], $count[1]属性 @2
+- 测试获取执行ID 2 product 0 type all module array(2) orederBy 'status_asc, id_desc' 的任务数量 @2
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[0], $type[0], $modules[2], $orderBy[0], $count[0]属性 @0
+- 测试获取执行ID 2 product 0 type all module array(8) orederBy 'status_asc, id_desc' 的任务 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[0], $type[0], $modules[2], $orderBy[0], $count[1]属性 @0
+- 测试获取执行ID 2 product 0 type all module array(8) orederBy 'status_asc, id_desc' 的任务数量 @0
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[0], $type[0], $modules[3], $orderBy[0], $count[0]第2条的name属性 @任务2
+- 测试获取执行ID 2 product 0 type all module array(2,8) orederBy 'status_asc, id_desc' 的任务第2条的name属性 @任务2
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[0], $type[0], $modules[3], $orderBy[0], $count[1]属性 @2
-
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[0], $type[0], $modules[0], $orderBy[1], $count[0]第20条的name属性 @任务20
-
-- 执行task模块的fetchExecutionTasks方法,参数是$executionIdList[2], $productIdList[0], $type[0], $modules[0], $orderBy[1], $count[1]属性 @10
+- 测试获取执行ID 2 product 0 type all module array(2,8) orederBy 'status_asc, id_desc' 的任务数量 @2
+- 测试获取执行ID 2 product 0 type all module 空 orederBy 'pri_desc' 的任务第20条的name属性 @任务20
+- 测试获取执行ID 2 product 0 type all module 空 orederBy 'pri_desc' 的任务数量 @10
*/
diff --git a/module/task/test/tao/getassignedto4multi.php b/module/task/test/tao/getassignedto4multi.php
index ce43dba8e6..4ffb987525 100755
--- a/module/task/test/tao/getassignedto4multi.php
+++ b/module/task/test/tao/getassignedto4multi.php
@@ -28,11 +28,16 @@ title=taskModel->getAssignedTo4Multi();
timeout=0
cid=1
-- 执行taskTester模块的getAssignedTo4Multi方法,参数是$taskIdList[0] @admin
-- 执行taskTester模块的getAssignedTo4Multi方法,参数是$taskIdList[1] @dev01
-- 执行taskTester模块的getAssignedTo4Multi方法,参数是$taskIdList[1], next @dev02
-- 执行taskTester模块的getAssignedTo4Multi方法,参数是$taskIdList[2] @dev01
-- 执行taskTester模块的getAssignedTo4Multi方法,参数是$taskIdList[3] @admin
+sed: can't read /home/tianshujie/repo/zentaopms/test/config/my.php: No such file or directory
+- 测试获取并行任务的指派人 @admin
+
+- 测试获取串行任务的当前指派人 @dev01
+
+- 测试获取并行任务的下一个指派人 @dev02
+
+- 测试获取已完成的串行任务的当前指派人 @dev01
+
+- 测试获取普通任务的指派人 @admin
*/
@@ -43,4 +48,4 @@ r($taskTester->getAssignedTo4MultiTest($taskIdList[0])) && p() && e('adm
r($taskTester->getAssignedTo4MultiTest($taskIdList[1])) && p() && e('dev01'); // 测试获取串行任务的当前指派人
r($taskTester->getAssignedTo4MultiTest($taskIdList[1], 'next')) && p() && e('dev02'); // 测试获取并行任务的下一个指派人
r($taskTester->getAssignedTo4MultiTest($taskIdList[2])) && p() && e('dev01'); // 测试获取已完成的串行任务的当前指派人
-r($taskTester->getAssignedTo4MultiTest($taskIdList[3])) && p() && e('admin'); // 测试获取普通任务的指派人
+r($taskTester->getAssignedTo4MultiTest($taskIdList[3])) && p() && e('admin'); // 测试获取普通任务的指派人
\ No newline at end of file
diff --git a/module/task/test/tao/getlistbyreportcondition.php b/module/task/test/tao/getlistbyreportcondition.php
old mode 100644
new mode 100755
index 63e706859b..c745adcede
--- a/module/task/test/tao/getlistbyreportcondition.php
+++ b/module/task/test/tao/getlistbyreportcondition.php
@@ -43,6 +43,7 @@ title=taskModel->getDataOfTasksPerExecution();
timeout=0
cid=1
+sed: can't read /home/tianshujie/repo/zentaopms/test/config/my.php: No such file or directory
- 获取任务id,execution列表信息在执行2中
- 第2条的id属性 @2
- 第2条的execution属性 @2
@@ -57,8 +58,6 @@ cid=1
- 获取执行3的任务个数 @2
-
-
*/
initData();
diff --git a/module/task/test/tao/getteammembersbyidlist.php b/module/task/test/tao/getteammembersbyidlist.php
index d3dfe6dba0..7a2d4a4eec 100755
--- a/module/task/test/tao/getteammembersbyidlist.php
+++ b/module/task/test/tao/getteammembersbyidlist.php
@@ -18,9 +18,12 @@ title=taskModel->getTeamMembersByIdList();
timeout=0
cid=1
-- 执行$emptyData属性 @0
-- 执行count($taskTeamGroup)属性 @2
-- 执行$firstTaskTeam第0条的account属性 @admin
+sed: can't read /home/tianshujie/repo/zentaopms/test/config/my.php: No such file or directory
+- 测试传入空的taskIdList @0
+
+- 测试查询给定taskIdList的任务数量 @2
+
+- 测试查询任务id为1团队中第一个人的用户名第0条的account属性 @admin
*/
@@ -34,4 +37,4 @@ $firstTaskTeam = current($taskTeamGroup);
r($emptyData) && p() && e('0'); // 测试传入空的taskIdList
r(count($taskTeamGroup)) && p() && e('2'); // 测试查询给定taskIdList的任务数量
-r($firstTaskTeam) && p('0:account') && e('admin'); // 测试查询任务id为1团队中第一个人的用户名
+r($firstTaskTeam) && p('0:account') && e('admin'); // 测试查询任务id为1团队中第一个人的用户名
\ No newline at end of file
diff --git a/module/task/test/tao/managetaskteammember.php b/module/task/test/tao/managetaskteammember.php
new file mode 100755
index 0000000000..fce3436ac5
--- /dev/null
+++ b/module/task/test/tao/managetaskteammember.php
@@ -0,0 +1,112 @@
+#!/usr/bin/env php
+manageTaskTeamMember();
+cid=1
+pid=1
+
+*/
+
+$modeList = array('linear', 'multi');
+$taskIdList = array(1, 2, 3);
+$taskStatusList = array('wait', 'doing', 'done');
+$row = array(0, 1, 2, 3, 4, 5);
+$account = array('admin', 'user1', 'user2', 'user3', 'user4', 'user5', 'user6', 'user7', 'user9');
+$minStatus = array('done', 'doing', 'wait');
+$undoneUsersList = array(array('admin' => 'admin', 'user1' => 'user1', 'user2' => 'user2', 'user3' => 'user3'), array('user4' => 'user4', 'user5' => 'user5', 'user6' => 'user6', 'user7' => 'user7', 'user8' => 'user8'), array());
+$teamSourceList = array(array('admin', 'user1', 'user2', 'user3'), array('admin', 'user1', 'user2', 'user4'), array('user4', 'user5', 'user6', 'user7', 'user9'), array('user4', 'user5', 'user6', 'user7', 'user8'));
+$teamEstimateList = array(array(1, 2, 3, 4), array(2, 3, 4, 5, 7));
+$teamConsumedList = array(array(4, 3, 2, 1), array(4, 3, 2, 1, 0));
+$teamLeftList = array(array(0, 0, 0, 0), array(0, 1, 3, 5, 7));
+$inTeams = array(true, false);
+
+$task = new taskTest();
+
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[0], $modeList[0], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 wait 最小任务状态为done 的串行多人任务内用户 admin 不存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[0], $modeList[0], $row[5], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 wait 最小任务状态为done 的串行多人任务内用户 admin 不存在期望 消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[0], $modeList[0], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 wait 最小任务状态为done 的串行多人任务内用户 admin 存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[0], $modeList[0], $row[0], $account[0], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 wait 最小任务状态为done 的串行多人任务内用户 admin 存在消耗和剩余的 不在未完成任务列表 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[0], $modeList[0], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 wait 最小任务状态为done 的串行多人任务内用户 admin 存在消耗和剩余的 不在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[0], $modeList[0], $row[0], $account[0], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 wait 最小任务状态为done 的串行多人任务内用户 admin 存在消耗和剩余的 不在未完成任务列表 不在用户列表中的成员信息
+
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[1], $modeList[0], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 doing 最小任务状态为done 的串行多人任务内用户 admin 不存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[1], $modeList[0], $row[5], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 doing 最小任务状态为done 的串行多人任务内用户 admin 不存在期望 消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[1], $modeList[0], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 doing 最小任务状态为done 的串行多人任务内用户 admin 存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[1], $modeList[0], $row[0], $account[0], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 doing 最小任务状态为done 的串行多人任务内用户 admin 存在消耗和剩余的 不在未完成任务列表 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[1], $modeList[0], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 doing 最小任务状态为done 的串行多人任务内用户 admin 存在消耗和剩余的 不在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[1], $modeList[0], $row[0], $account[0], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 doing 最小任务状态为done 的串行多人任务内用户 admin 存在消耗和剩余的 不在未完成任务列表 不在用户列表中的成员信息
+
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[2], $modeList[0], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 done 最小任务状态为done 的串行多人任务内用户 admin 不存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[2], $modeList[0], $row[5], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 done 最小任务状态为done 的串行多人任务内用户 admin 不存在期望 消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[2], $modeList[0], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 done 最小任务状态为done 的串行多人任务内用户 admin 存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[2], $modeList[0], $row[0], $account[0], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 done 最小任务状态为done 的串行多人任务内用户 admin 存在消耗和剩余的 不在未完成任务列表 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[2], $modeList[0], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 done 最小任务状态为done 的串行多人任务内用户 admin 存在消耗和剩余的 不在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[2], $modeList[0], $row[0], $account[0], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 done 最小任务状态为done 的串行多人任务内用户 admin 存在消耗和剩余的 不在未完成任务列表 不在用户列表中的成员信息
+
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[0], $modeList[1], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 wait 最小任务状态为done 的并行多人任务内用户 admin 不存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[0], $modeList[1], $row[5], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 wait 最小任务状态为done 的并行多人任务内用户 admin 不存在期望 消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[0], $modeList[1], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 wait 最小任务状态为done 的并行多人任务内用户 admin 存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[0], $modeList[1], $row[0], $account[0], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 wait 最小任务状态为done 的并行多人任务内用户 admin 存在消耗和剩余的 不在未完成任务列表 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[0], $modeList[1], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 wait 最小任务状态为done 的并行多人任务内用户 admin 存在消耗和剩余的 不在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[0], $modeList[1], $row[0], $account[0], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 wait 最小任务状态为done 的并行多人任务内用户 admin 存在消耗和剩余的 不在未完成任务列表 不在用户列表中的成员信息
+
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[1], $modeList[1], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 doing 最小任务状态为done 的并行多人任务内用户 admin 不存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[1], $modeList[1], $row[5], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 doing 最小任务状态为done 的并行多人任务内用户 admin 不存在期望 消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[1], $modeList[1], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 doing 最小任务状态为done 的并行多人任务内用户 admin 存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[1], $modeList[1], $row[0], $account[0], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 doing 最小任务状态为done 的并行多人任务内用户 admin 存在消耗和剩余的 不在未完成任务列表 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[1], $modeList[1], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 doing 最小任务状态为done 的并行多人任务内用户 admin 存在消耗和剩余的 不在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[1], $modeList[1], $row[0], $account[0], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 doing 最小任务状态为done 的并行多人任务内用户 admin 存在消耗和剩余的 不在未完成任务列表 不在用户列表中的成员信息
+
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[2], $modeList[1], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 done 最小任务状态为done 的并行多人任务内用户 admin 不存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[2], $modeList[1], $row[5], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 done 最小任务状态为done 的并行多人任务内用户 admin 不存在期望 消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[2], $modeList[1], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 done 最小任务状态为done 的并行多人任务内用户 admin 存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[2], $modeList[1], $row[0], $account[0], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 done 最小任务状态为done 的并行多人任务内用户 admin 存在消耗和剩余的 不在未完成任务列表 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[2], $modeList[1], $row[0], $account[0], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 done 最小任务状态为done 的并行多人任务内用户 admin 存在消耗和剩余的 不在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[0], $taskStatusList[2], $modeList[1], $row[0], $account[0], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 1 任务状态为 done 最小任务状态为done 的并行多人任务内用户 admin 存在消耗和剩余的 不在未完成任务列表 不在用户列表中的成员信息
+
+
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[0], $modeList[0], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 wait 最小任务状态为done 的串行多人任务内用户 user6 不存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[0], $modeList[0], $row[5], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 wait 最小任务状态为done 的串行多人任务内用户 user6 不存在期望 消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[0], $modeList[0], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 wait 最小任务状态为done 的串行多人任务内用户 user6 存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[0], $modeList[0], $row[0], $account[6], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 wait 最小任务状态为done 的串行多人任务内用户 user6 存在消耗和剩余的 不在未完成任务列表 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[0], $modeList[0], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 wait 最小任务状态为done 的串行多人任务内用户 user6 存在消耗和剩余的 不在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[0], $modeList[0], $row[0], $account[6], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 wait 最小任务状态为done 的串行多人任务内用户 user6 存在消耗和剩余的 不在未完成任务列表 不在用户列表中的成员信息
+
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[1], $modeList[0], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 doing 最小任务状态为done 的串行多人任务内用户 user6 不存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[1], $modeList[0], $row[5], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 doing 最小任务状态为done 的串行多人任务内用户 user6 不存在期望 消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[1], $modeList[0], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 doing 最小任务状态为done 的串行多人任务内用户 user6 存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[1], $modeList[0], $row[0], $account[6], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 doing 最小任务状态为done 的串行多人任务内用户 user6 存在消耗和剩余的 不在未完成任务列表 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[1], $modeList[0], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 doing 最小任务状态为done 的串行多人任务内用户 user6 存在消耗和剩余的 不在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[1], $modeList[0], $row[0], $account[6], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 doing 最小任务状态为done 的串行多人任务内用户 user6 存在消耗和剩余的 不在未完成任务列表 不在用户列表中的成员信息
+
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[2], $modeList[0], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 done 最小任务状态为done 的串行多人任务内用户 user6 不存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[2], $modeList[0], $row[5], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 done 最小任务状态为done 的串行多人任务内用户 user6 不存在期望 消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[2], $modeList[0], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 done 最小任务状态为done 的串行多人任务内用户 user6 存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[2], $modeList[0], $row[0], $account[6], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 done 最小任务状态为done 的串行多人任务内用户 user6 存在消耗和剩余的 不在未完成任务列表 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[2], $modeList[0], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 done 最小任务状态为done 的串行多人任务内用户 user6 存在消耗和剩余的 不在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[2], $modeList[0], $row[0], $account[6], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 done 最小任务状态为done 的串行多人任务内用户 user6 存在消耗和剩余的 不在未完成任务列表 不在用户列表中的成员信息
+
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[0], $modeList[1], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 wait 最小任务状态为done 的并行多人任务内用户 user6 不存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[0], $modeList[1], $row[5], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 wait 最小任务状态为done 的并行多人任务内用户 user6 不存在期望 消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[0], $modeList[1], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 wait 最小任务状态为done 的并行多人任务内用户 user6 存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[0], $modeList[1], $row[0], $account[6], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 wait 最小任务状态为done 的并行多人任务内用户 user6 存在消耗和剩余的 不在未完成任务列表 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[0], $modeList[1], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 wait 最小任务状态为done 的并行多人任务内用户 user6 存在消耗和剩余的 不在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[0], $modeList[1], $row[0], $account[6], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 wait 最小任务状态为done 的并行多人任务内用户 user6 存在消耗和剩余的 不在未完成任务列表 不在用户列表中的成员信息
+
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[1], $modeList[1], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 doing 最小任务状态为done 的并行多人任务内用户 user6 不存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[1], $modeList[1], $row[5], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 doing 最小任务状态为done 的并行多人任务内用户 user6 不存在期望 消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[1], $modeList[1], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 doing 最小任务状态为done 的并行多人任务内用户 user6 存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[1], $modeList[1], $row[0], $account[6], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 doing 最小任务状态为done 的并行多人任务内用户 user6 存在消耗和剩余的 不在未完成任务列表 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[1], $modeList[1], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 doing 最小任务状态为done 的并行多人任务内用户 user6 存在消耗和剩余的 不在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[1], $modeList[1], $row[0], $account[6], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 doing 最小任务状态为done 的并行多人任务内用户 user6 存在消耗和剩余的 不在未完成任务列表 不在用户列表中的成员信息
+
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[2], $modeList[1], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 done 最小任务状态为done 的并行多人任务内用户 user6 不存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[2], $modeList[1], $row[5], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], false, false, $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 done 最小任务状态为done 的并行多人任务内用户 user6 不存在期望 消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[2], $modeList[1], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 done 最小任务状态为done 的并行多人任务内用户 user6 存在消耗和剩余的 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[2], $modeList[1], $row[0], $account[6], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[0])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 done 最小任务状态为done 的并行多人任务内用户 user6 存在消耗和剩余的 不在未完成任务列表 在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[2], $modeList[1], $row[0], $account[6], $minStatus[0], $undoneUsersList[0], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 done 最小任务状态为done 的并行多人任务内用户 user6 存在消耗和剩余的 不在用户列表中的成员信息
+r($task->manageTaskTeamMemberTest($taskIdList[1], $taskStatusList[2], $modeList[1], $row[0], $account[6], $minStatus[0], $undoneUsersList[2], $teamSourceList[0], $teamEstimateList[0], $teamConsumedList[0], $teamLeftList[0], $inTeams[1])) && p('minStatus,memberData') && e(''); // 测试更新任务ID 2 任务状态为 done 最小任务状态为done 的并行多人任务内用户 user6 存在消耗和剩余的 不在未完成任务列表 不在用户列表中的成员信息
diff --git a/module/task/test/tao/removecreaterequiredfields.php b/module/task/test/tao/removecreaterequiredfields.php
index 7fd9a53e30..a83c095cca 100755
--- a/module/task/test/tao/removecreaterequiredfields.php
+++ b/module/task/test/tao/removecreaterequiredfields.php
@@ -21,8 +21,80 @@ title=taskModel->removeCreateRequiredFields();
timeout=0
cid=1
-*/
+sed: can't read /home/tianshujie/repo/zentaopms/test/config/my.php: No such file or directory
+- 测试任务执行为短期执行 阶段类型为mix 任务类型为dev 没有选择需求时候的必填项 @name,type,execution,story,estimate,estStarted,deadline,module
+- 测试任务执行为短期执行 阶段类型为mix 任务类型为dev 有选择需求时候的必填项 @name,type,execution,story,estimate,estStarted,deadline,module
+
+- 测试任务执行为短期执行 阶段类型为request 任务类型为dev 没有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为短期执行 阶段类型为request 任务类型为dev 有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为短期执行 阶段类型为review 任务类型为dev 没有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为短期执行 阶段类型为review 任务类型为dev 有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为长期执行 阶段类型为mix 任务类型为dev 没有选择需求时候的必填项 @name,type,execution,story,estimate,estStarted,deadline,module
+
+- 测试任务执行为长期执行 阶段类型为mix 任务类型为dev 有选择需求时候的必填项 @name,type,execution,story,estimate,estStarted,deadline,module
+
+- 测试任务执行为长期执行 阶段类型为request 任务类型为dev 没有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为长期执行 阶段类型为request 任务类型为dev 有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为长期执行 阶段类型为review 任务类型为dev 没有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为长期执行 阶段类型为review 任务类型为dev 有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为运维执行 阶段类型为mix 任务类型为dev 没有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为运维执行 阶段类型为mix 任务类型为dev 有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为运维执行 阶段类型为request 任务类型为dev 没有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为运维执行 阶段类型为request 任务类型为dev 有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为运维执行 阶段类型为review 任务类型为dev 没有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为运维执行 阶段类型为review 任务类型为dev 有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为短期执行 阶段类型为mix 任务类型为test 没有选择需求时候的必填项 @name,type,execution,story,estimate,estStarted,deadline,module
+
+- 测试任务执行为短期执行 阶段类型为mix 任务类型为test 有选择需求时候的必填项 @name,type,execution
+
+- 测试任务执行为短期执行 阶段类型为request 任务类型为test 没有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为短期执行 阶段类型为request 任务类型为test 有选择需求时候的必填项 @name,type,execution
+
+- 测试任务执行为短期执行 阶段类型为review 任务类型为test 没有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为短期执行 阶段类型为review 任务类型为test 有选择需求时候的必填项 @name,type,execution
+
+- 测试任务执行为长期执行 阶段类型为mix 任务类型为test 没有选择需求时候的必填项 @name,type,execution,story,estimate,estStarted,deadline,module
+
+- 测试任务执行为长期执行 阶段类型为mix 任务类型为test 有选择需求时候的必填项 @name,type,execution
+
+- 测试任务执行为长期执行 阶段类型为request 任务类型为test 没有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为长期执行 阶段类型为request 任务类型为test 有选择需求时候的必填项 @name,type,execution
+
+- 测试任务执行为长期执行 阶段类型为review 任务类型为test 没有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为长期执行 阶段类型为review 任务类型为test 有选择需求时候的必填项 @name,type,execution
+
+- 测试任务执行为运维执行 阶段类型为mix 任务类型为test 没有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为运维执行 阶段类型为mix 任务类型为test 有选择需求时候的必填项 @name,type,execution
+
+- 测试任务执行为运维执行 阶段类型为request 任务类型为test 没有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为运维执行 阶段类型为request 任务类型为test 有选择需求时候的必填项 @name,type,execution
+
+- 测试任务执行为运维执行 阶段类型为review 任务类型为test 没有选择需求时候的必填项 @name,type,execution,estimate,estStarted,deadline,module
+
+- 测试任务执行为运维执行 阶段类型为review 任务类型为test 有选择需求时候的必填项 @name,type,execution
+
+*/
$selectTestStoryList = array(false, true);
@@ -63,4 +135,4 @@ r($task->removeCreateRequiredFieldsTest($tasks[15], $selectTestStoryList[1])) &
r($task->removeCreateRequiredFieldsTest($tasks[16], $selectTestStoryList[0])) && p() && e('name,type,execution,estimate,estStarted,deadline,module'); // 测试任务执行为运维执行 阶段类型为request 任务类型为test 没有选择需求时候的必填项
r($task->removeCreateRequiredFieldsTest($tasks[16], $selectTestStoryList[1])) && p() && e('name,type,execution'); // 测试任务执行为运维执行 阶段类型为request 任务类型为test 有选择需求时候的必填项
r($task->removeCreateRequiredFieldsTest($tasks[17], $selectTestStoryList[0])) && p() && e('name,type,execution,estimate,estStarted,deadline,module'); // 测试任务执行为运维执行 阶段类型为review 任务类型为test 没有选择需求时候的必填项
-r($task->removeCreateRequiredFieldsTest($tasks[17], $selectTestStoryList[1])) && p() && e('name,type,execution'); // 测试任务执行为运维执行 阶段类型为review 任务类型为test 有选择需求时候的必填项
+r($task->removeCreateRequiredFieldsTest($tasks[17], $selectTestStoryList[1])) && p() && e('name,type,execution'); // 测试任务执行为运维执行 阶段类型为review 任务类型为test 有选择需求时候的必填项
\ No newline at end of file
diff --git a/module/task/test/tao/settaskfiles.php b/module/task/test/tao/settaskfiles.php
index 544269bade..133e557e6b 100755
--- a/module/task/test/tao/settaskfiles.php
+++ b/module/task/test/tao/settaskfiles.php
@@ -21,6 +21,17 @@ title=taskModel->setTaskFiles();
timeout=0
cid=1
+sed: can't read /home/tianshujie/repo/zentaopms/test/config/my.php: No such file or directory
+- 测试空数据 @0
+
+- 测试传入的任务ID @0
+
+- 测试插入任务附件的数量 @10
+
+- 测试插入附件数据的对象ID第1条的objectID属性 @6
+
+- 测试获取任务ID为5的附件数据的数量 @0
+
*/
$taskIdList = range(1, 5);
@@ -35,4 +46,4 @@ r($emptyData) && p() && e('0'); // 测试空数据
r($emptyTaskID) && p() && e('0'); // 测试传入的任务ID
r(count($insertData)) && p() && e('10'); // 测试插入任务附件的数量
r($insertData) && p('1:objectID') && e('6'); // 测试插入附件数据的对象ID
-r(count($taskFiles)) && p() && e('0'); // 测试获取任务ID为5的附件数据的数量
+r(count($taskFiles)) && p() && e('0'); // 测试获取任务ID为5的附件数据的数量
\ No newline at end of file
diff --git a/module/task/test/tao/yaml/managetaskteammember/effort_managetaskteammember.yaml b/module/task/test/tao/yaml/managetaskteammember/effort_managetaskteammember.yaml
new file mode 100644
index 0000000000..6982b41d06
--- /dev/null
+++ b/module/task/test/tao/yaml/managetaskteammember/effort_managetaskteammember.yaml
@@ -0,0 +1,13 @@
+---
+title: zt_effort
+author: auto_managetaskteammember
+version: "1.0"
+fields:
+- field: objectType
+ range: task
+- field: objectID
+ range: 1{4},2{6}
+- field: left
+ range: 0{4},0-7,0-7,0-7
+...
+
diff --git a/module/task/test/tao/yaml/managetaskteammember/taskteam_managetaskteammember.yaml b/module/task/test/tao/yaml/managetaskteammember/taskteam_managetaskteammember.yaml
new file mode 100644
index 0000000000..80d838bf18
--- /dev/null
+++ b/module/task/test/tao/yaml/managetaskteammember/taskteam_managetaskteammember.yaml
@@ -0,0 +1,24 @@
+---
+title: zt_taskteam
+author: auto_managetaskteammember
+version: "1.0"
+fields:
+- field: task
+ range: 1-5
+- field: left
+ range: 0-4
+- field: estimate
+ range: 1-10{2}
+- field: consumed
+ range: 1,3,0,2
+- field: account
+ note: "用户账号"
+ fields:
+ - field: account1
+ range: admin,user{99}
+ - field: account2
+ range: "[],1-99"
+- field: status
+ range: "done,doing,wait,doing"
+...
+
diff --git a/module/task/test/task.class.php b/module/task/test/task.class.php
index 2468b770b0..5c05263afa 100644
--- a/module/task/test/task.class.php
+++ b/module/task/test/task.class.php
@@ -304,6 +304,38 @@ class taskTest
}
}
+ /**
+ * Test assign a task to a team again.
+ *
+ * @param int $taskID
+ * @param string $status
+ * @param array $team
+ * @param array $teamSource
+ * @param array $teamConsumed
+ * @param araay $teamLeft
+ * @access public
+ * @return object
+ */
+ public function updateTeamTest($taskID, $status, $team, $teamSource, $teamEstimate, $teamConsumed, $teamLeft)
+ {
+ global $tester;
+
+ $task = new stdclass();
+ $task->id = $taskID;
+ $task->status = $status;
+ $task->lastEditedBy = $tester->app->user->account;
+ $object = $this->objectModel->updateTeam($task, $team, $teamSource, $teamEstimate, $teamConsumed, $teamLeft);
+ if(dao::isError())
+ {
+ $errors = dao::getError();
+ return array_shift($errors);
+ }
+ else
+ {
+ return $object;
+ }
+ }
+
/**
* Test cancel a task.
*
@@ -1721,4 +1753,114 @@ class taskTest
return $cards;
}
+
+ /**
+ * Other data processing after task creation.
+ *
+ * @param int $taskID
+ * @param int $taskIdList
+ * @param int $bugID
+ * @param int $todoID
+ * @param array $testTasks
+ * @access public
+ * @return object|bool
+ */
+ public function afterCreateTest($taskID = 0, $taskIdList = array(), $bugID = 0, $todoID = 0, $testTasks = array())
+ {
+ global $tester;
+ $_SERVER['HTTP_HOST'] = $tester->config->db->host;
+
+ $task = $this->objectModel->getByID($taskID);
+ if(!$task) return false;
+
+ $result = $this->objectModel->afterCreate($task, $taskIdList, $bugID, $todoID, $testTasks);
+ if(!$result) return false;
+
+ if($bugID)
+ {
+ $object = $tester->dao->findById($bugID)->from(TABLE_BUG)->fetch();
+ }
+ elseif($todoID)
+ {
+ $object = $tester->dao->findById($todoID)->from(TABLE_TODO)->fetch();
+ }
+ elseif($task->story)
+ {
+ $object = $tester->dao->findById($task->story)->from(TABLE_STORY)->fetch();
+ }
+ else
+ {
+ $object = $tester->dao->findById($taskID)->from(TABLE_TASK)->fetch();
+ }
+
+ return $object;
+ }
+
+ /**
+ * Test manage multi task team members.
+ *
+ * @param int $taskID
+ * @param string $taskStatus
+ * @param string $mode
+ * @param array $teamList
+ * @param array $teamSourceList
+ * @param array $teamEstimateList
+ * @param array|bool $teamConsumedList
+ * @param array|bool $teamLeftList
+
+ * @access public
+ * @return array
+ */
+ public function manageTaskTeamTest(int $taskID, string $taskStatus, string $mode, array $teamList, array $teamSourceList, array $teamEstimateList, array|bool $teamConsumedList, array|bool $teamLeftList): array
+ {
+ $task = new stdclass();
+ $task->id = $taskID;
+ $task->status = $taskStatus;
+ $teams = $this->objectModel->manageTaskTeam($mode, $task, $teamList, $teamSourceList, $teamEstimateList, $teamConsumedList, $teamLeftList);
+ if(dao::isError())
+ {
+ return dao::getError();
+ }
+ else
+ {
+ return $teams;
+ }
+ }
+
+ /**
+ * Test manage multi task team member.
+ *
+ * @param int $taskID
+ * @param string $taskStatus
+ * @param string $mode
+ * @param int $row
+ * @param string $account
+ * @param string $minStatus
+ * @param array $undoneUsers
+ * @param array $teamSourceList
+ * @param array $teamEstimateList
+ * @param array|bool $teamConsumedList
+ * @param array|bool $teamLeftList
+ * @param bool $inTeams
+ * @access public
+ * @return string
+ */
+ public function manageTaskTeamMemberTest(int $taskID, string $taskStatus, string $mode, int $row, string $account, string $minStatus, array $undoneUsers, array $teamSourceList, array $teamEstimateList, array|bool $teamConsumedList, array|bool $teamLeftList, bool $inTeams): string
+ {
+ global $tester;
+ $tester->dao->delete()->from(TABLE_TASKTEAM)->where('task')->eq($taskID)->exec();
+
+ $task = new stdclass();
+ $task->id = $taskID;
+ $task->status = $taskStatus;
+ $minStatus = $this->objectModel->manageTaskTeamMember($mode, $task, $row, $account, $minStatus, $undoneUsers, $teamSourceList, $teamEstimateList, $teamConsumedList, $teamLeftList, $inTeams);
+ if(dao::isError())
+ {
+ return dao::getError();
+ }
+ else
+ {
+ return $minStatus;
+ }
+ }
}
diff --git a/module/task/ui/assignto.html.php b/module/task/ui/assignto.html.php
index 51b1e7d8da..27bf1d3e4b 100644
--- a/module/task/ui/assignto.html.php
+++ b/module/task/ui/assignto.html.php
@@ -1,4 +1,5 @@
name;
+$formTitle = $task->name;
$assignedToOptions = $members;
diff --git a/module/task/ui/edit.html.php b/module/task/ui/edit.html.php
index 8e164412bf..819fe66ed9 100644
--- a/module/task/ui/edit.html.php
+++ b/module/task/ui/edit.html.php
@@ -68,363 +68,417 @@ formPanel
(
set::title($formTitle), // The form title is diffrent from the page title,
setStyle(['max-width' => '100%']),
+ setClass('mx-8'),
div
(
- setClass('flex'),
- cell
- (
- set('width', '67%'),
- formGroup
+ setClass('flex'),
+ cell
(
- set::label($lang->task->name),
- set::name('name'),
- set::value($task->name),
- set::placeholder($lang->task->name),
- set::control('input'),
- set::required(true),
- set::autofocus(true),
- ),
- formGroup
- (
- set::label($lang->task->desc),
- set::name('desc'),
- set::value(htmlSpecialString($task->desc)),
- set::control('textarea'),
- ),
- formGroup
- (
- set::label($lang->comment),
- set::name('comment'),
- set::value(''),
- set::control('textarea'),
- ),
- history
- (
- set::actions($actions),
- set::users($users),
- set::methodName($methodName),
- )
- ),
- cell
- (
- on::change('#execution'),
- set('width', '33%'),
- formGroup
- (
- set::name("execution"),
- set::label($lang->task->execution),
- set::required(true),
- set::value($task->execution),
- set::control("picker"),
- set::items($executionOptions)
- ),
- formGroup
- (
- set::name("module"),
- set::label($lang->task->module),
- set::value($task->module),
- set::control("picker"),
- set::items($moduleOptions)
- ),
- formGroup
- (
- set::name("story"),
- set::label($lang->task->story),
- set::value($task->story),
- set::control("picker"),
- set::items($storyOptions)
- ),
- (empty($modeText))
- ? formGroup
- (
- set::name("mode"),
- set::label($lang->task->mode),
- set::value($task->mode),
- set::control("picker"),
- set::items($modeOptions)
- )
- : label
- (
- $modeText
- ),
- formGroup
- (
- set::label($lang->task->assignedTo),
- inputGroup
+ set('width', '67%'),
+ h::strong
(
- control(set(array
- (
- 'name' => "assignedTo",
- 'id' => "assignedTo",
- 'value' => $task->assignedTo,
- 'disabled' => (!empty($task->team) and $task->mode == 'linear') ? true : false,
- 'type' => "picker",
- 'items' => $assignedToOptions
- ))),
- btn(set(array
- (
- 'type' => "btn",
- 'text' => $lang->task->team,
- 'class' => "input-group-btn team-group"
- )))
+ $lang->task->name,
+ setClass('leading-8')
+ ),
+ input
+ (
+ set::label($lang->task->name),
+ set::name('name'),
+ set::value($task->name),
+ set::placeholder($lang->task->name),
+ set::control('input'),
+ set::required(true),
+ set::autofocus(true),
+ ),
+ h::strong
+ (
+ $lang->task->desc,
+ setClass('leading-8')
+ ),
+ textarea
+ (
+ set::label($lang->task->desc),
+ set::name('desc'),
+ set::value(htmlSpecialString($task->desc)),
+ set::control('textarea'),
+ ),
+ h::strong
+ (
+ $lang->comment,
+ setClass('leading-8')
+ ),
+ textarea
+ (
+ set::label($lang->comment),
+ set::name('comment'),
+ set::value(''),
+ set::control('textarea'),
+ ),
+ history
+ (
+ set::actions($actions),
+ set::users($users),
+ set::methodName($methodName),
)
),
- formGroup
+ cell
(
- set::name("type"),
- set::label($lang->task->type),
- set::required(true),
- set::value($task->type),
- set::control("picker"),
- set::items($typeOptions)
- ),
- empty($task->children)
- ? formGroup
- (
- set::name("status"),
- set::label($lang->task->status),
- set::value($task->status),
- set::control("picker"),
- set::items($statusOptions)
- )
- : null,
- formGroup
- (
- set::name("pri"),
- set::label($lang->task->pri),
- set::value($task->pri),
- set::control("picker"),
- set::items($priOptions)
- ),
- formGroup
- (
- set::label($lang->task->mailto),
- inputGroup
+ on::change('#execution'),
+ set('width', '33%'),
+ setClass('pl-5'),
+ h::strong
(
- control(set(array
- (
- 'name' => "mailto[]",
- 'id' => "mailto",
- 'value' => $task->mailto,
- 'type' => "picker",
- 'items' => $mailtoOptions,
- 'multiple' => true
- ))),
- control(set(array
- (
- 'name' => "contactListMenu",
- 'id' => "contactListMenu",
- 'value' => "",
- 'disabled' => false,
- 'type' => "picker",
- 'onchange' => "setMailto",
- 'items' => $contactListMenuOptions
- )))
- )
- ),
- formGroup
- (
- set::name("estStarted"),
- set::label($lang->task->estStarted),
- set::value($task->estStarted),
- set::control("date")
- ),
- formGroup
- (
- set::name("deadline"),
- set::label($lang->task->deadline),
- set::value($task->deadline),
- set::control("date")
- ),
- formGroup
- (
- set::name("estimate"),
- set::label($lang->task->estimate),
- set::value($task->estimate),
- set::control("text")
- ),
- formGroup
- (
- set::name("left"),
- set::label($lang->task->left),
- set::value($task->left),
- set::control("text")
- ),
- formGroup
- (
- set::name("realStarted"),
- set::label($lang->task->realStarted),
- set::value(helper::isZeroDate($task->realStarted) ? '' : $task->realStarted),
- set::control("datetime")
- ),
- formGroup
- (
- set::name("finishedBy"),
- set::label($lang->task->finishedBy),
- set::value($task->finishedBy),
- set::control("picker"),
- set::items($finishedByOptions)
- ),
- formGroup
- (
- set::name("finishedDate"),
- set::label($lang->task->finishedDate),
- set::value($task->finishedDate),
- set::control("datetime")
- ),
- formGroup
- (
- set::name("canceledBy"),
- set::label($lang->task->canceledBy),
- set::value($task->canceledBy),
- set::control("picker"),
- set::items($canceledByOptions)
- ),
- formGroup
- (
- set::name("canceledDate"),
- set::label($lang->task->canceledDate),
- set::value($task->canceledDate),
- set::control("datetime")
- ),
- formGroup
- (
- set::name("closedBy"),
- set::label($lang->task->closedBy),
- set::value($task->closedBy),
- set::control("picker"),
- set::items($closedByOptions)
- ),
- formGroup
- (
- set::name("closedReason"),
- set::label($lang->task->closedReason),
- set::value($task->closedReason),
- set::control("picker"),
- set::items($closedReasonOptions)
- ),
- formGroup
- (
- set::name("closedDate"),
- set::label($lang->task->closedDate),
- set::value($task->closedDate),
- set::control("datetime")
- ),
- formRow
- (
- set::hidden(true),
- formGroup
- (
- set::name("team[]"),
- set::value("zenggang"),
- set::control("picker"),
- set::id("team"),
- set::items($teamOptions)
+ $lang->task->legendBasic,
+ setClass('leading-8')
),
formGroup
(
- inputGroup
- (
-
- )
- )
- ),
- formRow
- (
- set::hidden(true),
- formGroup
- (
- set::name("team[]"),
- set::value("zenggang"),
+ set::name("execution"),
+ set::label($lang->task->execution),
+ set::required(true),
+ set::value($task->execution),
set::control("picker"),
- set::id("team"),
- set::items($teamOptions)
+ set::strong(true),
+ set::items($executionOptions)
),
formGroup
(
- inputGroup
- (
-
- )
- )
- ),
- formRow
- (
- set::hidden(true),
- formGroup
- (
- set::name("team[]"),
+ set::name("module"),
+ set::label($lang->task->module),
+ set::value($task->module),
set::control("picker"),
- set::id("team"),
- set::items($teamOptions)
+ set::strong(true),
+ set::items($moduleOptions)
),
formGroup
(
- inputGroup
- (
-
- )
- )
- ),
- formRow
- (
- set::hidden(true),
- formGroup
- (
- set::name("team[]"),
+ set::name("story"),
+ set::label($lang->task->story),
+ set::value($task->story),
set::control("picker"),
- set::id("team"),
- set::items($teamOptions)
+ set::strong(true),
+ set::items($storyOptions)
+ ),
+ (empty($modeText))
+ ? formGroup
+ (
+ set::name("mode"),
+ set::label($lang->task->mode),
+ set::value($task->mode),
+ set::control("picker"),
+ set::strong(true),
+ set::items($modeOptions)
+ )
+ : label
+ (
+ $modeText
),
formGroup
(
+ set::label($lang->task->assignedTo),
+ set::strong(true),
inputGroup
(
-
+ control(set(array
+ (
+ 'name' => "assignedTo",
+ 'id' => "assignedTo",
+ 'value' => $task->assignedTo,
+ 'disabled' => (!empty($task->team) and $task->mode == 'linear') ? true : false,
+ 'type' => "picker",
+ 'items' => $assignedToOptions
+ ))),
+ btn(set(array
+ (
+ 'type' => "btn",
+ 'text' => $lang->task->team,
+ 'class' => "input-group-btn team-group"
+ )))
)
- )
- ),
- formRow
- (
- set::hidden(true),
- formGroup
- (
- set::name("team[]"),
- set::control("picker"),
- set::id("team"),
- set::items($teamOptions)
),
formGroup
(
- inputGroup
- (
-
- )
+ set::name("type"),
+ set::label($lang->task->type),
+ set::required(true),
+ set::value($task->type),
+ set::control("picker"),
+ set::strong(true),
+ set::items($typeOptions)
+ ),
+ empty($task->children)
+ ? formGroup
+ (
+ set::name("status"),
+ set::label($lang->task->status),
+ set::value($task->status),
+ set::control("picker"),
+ set::strong(true),
+ set::items($statusOptions)
)
- ),
- formRow
- (
- set::hidden(true),
+ : null,
formGroup
(
- set::name("team[]"),
+ set::name("pri"),
+ set::label($lang->task->pri),
+ set::value($task->pri),
set::control("picker"),
- set::id("team"),
- set::items($teamOptions)
+ set::strong(true),
+ set::items($priOptions)
),
formGroup
(
+ set::label($lang->task->mailto),
+ set::strong(true),
inputGroup
(
+ control(set(array
+ (
+ 'name' => "mailto[]",
+ 'id' => "mailto",
+ 'value' => $task->mailto,
+ 'type' => "picker",
+ 'items' => $mailtoOptions,
+ 'multiple' => true
+ ))),
+ control(set(array
+ (
+ 'name' => "contactListMenu",
+ 'id' => "contactListMenu",
+ 'value' => "",
+ 'disabled' => false,
+ 'type' => "picker",
+ 'onchange' => "setMailto",
+ 'items' => $contactListMenuOptions
+ )))
+ )
+ ),
+ h::strong
+ (
+ $lang->task->legendEffort,
+ setClass('leading-8')
+ ),
+ formGroup
+ (
+ set::name("estStarted"),
+ set::label($lang->task->estStarted),
+ set::value($task->estStarted),
+ set::strong(true),
+ set::control("date")
+ ),
+ formGroup
+ (
+ set::name("deadline"),
+ set::label($lang->task->deadline),
+ set::value($task->deadline),
+ set::strong(true),
+ set::control("date")
+ ),
+ formGroup
+ (
+ set::name("estimate"),
+ set::label($lang->task->estimate),
+ set::value($task->estimate),
+ set::strong(true),
+ set::control("text")
+ ),
+ formGroup
+ (
+ set::name("left"),
+ set::label($lang->task->left),
+ set::value($task->left),
+ set::strong(true),
+ set::control("text")
+ ),
+ h::strong
+ (
+ $lang->task->legendLife,
+ setClass('leading-8')
+ ),
+ formGroup
+ (
+ set::name("realStarted"),
+ set::label($lang->task->realStarted),
+ set::value(helper::isZeroDate($task->realStarted) ? '' : $task->realStarted),
+ set::strong(true),
+ set::control("datetime")
+ ),
+ formGroup
+ (
+ set::name("finishedBy"),
+ set::label($lang->task->finishedBy),
+ set::value($task->finishedBy),
+ set::control("picker"),
+ set::strong(true),
+ set::items($finishedByOptions)
+ ),
+ formGroup
+ (
+ set::name("finishedDate"),
+ set::label($lang->task->finishedDate),
+ set::value($task->finishedDate),
+ set::strong(true),
+ set::control("datetime")
+ ),
+ formGroup
+ (
+ set::name("canceledBy"),
+ set::label($lang->task->canceledBy),
+ set::value($task->canceledBy),
+ set::control("picker"),
+ set::strong(true),
+ set::items($canceledByOptions)
+ ),
+ formGroup
+ (
+ set::name("canceledDate"),
+ set::label($lang->task->canceledDate),
+ set::value($task->canceledDate),
+ set::strong(true),
+ set::control("datetime")
+ ),
+ formGroup
+ (
+ set::name("closedBy"),
+ set::label($lang->task->closedBy),
+ set::value($task->closedBy),
+ set::control("picker"),
+ set::strong(true),
+ set::items($closedByOptions)
+ ),
+ formGroup
+ (
+ set::name("closedReason"),
+ set::label($lang->task->closedReason),
+ set::value($task->closedReason),
+ set::control("picker"),
+ set::strong(true),
+ set::items($closedReasonOptions)
+ ),
+ formGroup
+ (
+ set::name("closedDate"),
+ set::label($lang->task->closedDate),
+ set::value($task->closedDate),
+ set::strong(true),
+ set::control("datetime")
+ ),
+ formRow
+ (
+ set::hidden(true),
+ formGroup
+ (
+ set::name("team[]"),
+ set::value("zenggang"),
+ set::control("picker"),
+ set::id("team"),
+ set::strong(true),
+ set::items($teamOptions)
+ ),
+ formGroup
+ (
+ inputGroup
+ (
+ )
+ )
+ ),
+ formRow
+ (
+ set::hidden(true),
+ formGroup
+ (
+ set::name("team[]"),
+ set::value("zenggang"),
+ set::control("picker"),
+ set::id("team"),
+ set::strong(true),
+ set::items($teamOptions)
+ ),
+ formGroup
+ (
+ inputGroup
+ (
+
+ )
+ )
+ ),
+ formRow
+ (
+ set::hidden(true),
+ formGroup
+ (
+ set::name("team[]"),
+ set::control("picker"),
+ set::id("team"),
+ set::items($teamOptions)
+ ),
+ formGroup
+ (
+ inputGroup
+ (
+
+ )
+ )
+ ),
+ formRow
+ (
+ set::hidden(true),
+ formGroup
+ (
+ set::name("team[]"),
+ set::control("picker"),
+ set::id("team"),
+ set::items($teamOptions)
+ ),
+ formGroup
+ (
+ inputGroup
+ (
+
+ )
+ )
+ ),
+ formRow
+ (
+ set::hidden(true),
+ formGroup
+ (
+ set::name("team[]"),
+ set::control("picker"),
+ set::id("team"),
+ set::items($teamOptions)
+ ),
+ formGroup
+ (
+ inputGroup
+ (
+
+ )
+ )
+ ),
+ formRow
+ (
+ set::hidden(true),
+ formGroup
+ (
+ set::name("team[]"),
+ set::control("picker"),
+ set::id("team"),
+ set::items($teamOptions)
+ ),
+ formGroup
+ (
+ inputGroup
+ (
+
+ )
)
)
)
- )
)
);
-
/* ====== Render page ====== */
render();
diff --git a/module/task/ui/manageteam.html.php b/module/task/ui/manageteam.html.php
new file mode 100644
index 0000000000..ab92f5907a
--- /dev/null
+++ b/module/task/ui/manageteam.html.php
@@ -0,0 +1,135 @@
+
+ * @package task
+ * @link https://www.zentao.net
+ */
+namespace zin;
+
+formPanel
+(
+ set::title($formTitle), // The form title is diffrent from the page title,
+ formRow
+ (
+ formGroup
+ (
+ set::width("1/3"),
+ set::name("team[]"),
+ set::value("productManager"),
+ set::control("picker"),
+ set::id("team"),
+ set::items($teamOptions)
+ ),
+ formGroup
+ (
+ set::width("1/3"),
+ inputGroup
+ (
+
+ )
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width("1/3"),
+ set::name("team[]"),
+ set::value("zenggang"),
+ set::control("picker"),
+ set::id("team"),
+ set::items($teamOptions)
+ ),
+ formGroup
+ (
+ set::width("1/3"),
+ inputGroup
+ (
+
+ )
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width("1/3"),
+ set::name("team[]"),
+ set::control("picker"),
+ set::id("team"),
+ set::items($teamOptions)
+ ),
+ formGroup
+ (
+ set::width("1/3"),
+ inputGroup
+ (
+
+ )
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width("1/3"),
+ set::name("team[]"),
+ set::control("picker"),
+ set::id("team"),
+ set::items($teamOptions)
+ ),
+ formGroup
+ (
+ set::width("1/3"),
+ inputGroup
+ (
+
+ )
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width("1/3"),
+ set::name("team[]"),
+ set::control("picker"),
+ set::id("team"),
+ set::items($teamOptions)
+ ),
+ formGroup
+ (
+ set::width("1/3"),
+ inputGroup
+ (
+
+ )
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width("1/3"),
+ set::name("team[]"),
+ set::control("picker"),
+ set::id("team"),
+ set::items($teamOptions)
+ ),
+ formGroup
+ (
+ set::width("1/3"),
+ inputGroup
+ (
+
+ )
+ )
+ )
+);
+
+render();
+
diff --git a/module/task/view/editteam.html.php b/module/task/view/editteam.html.php
index 2623b1d505..474c6aae40 100755
--- a/module/task/view/editteam.html.php
+++ b/module/task/view/editteam.html.php
@@ -37,7 +37,7 @@
-