diff --git a/module/product/control.php b/module/product/control.php
index b7be9b7d2c..8519c41426 100755
--- a/module/product/control.php
+++ b/module/product/control.php
@@ -832,6 +832,7 @@ class product extends control
$this->view->browseType = $browseType;
$this->view->param = $param;
$this->view->storyType = $storyType;
+ $this->view->users = $this->loadModel('user')->getPairs('noletter|nodeleted');
$this->display();
}
diff --git a/module/product/js/track.ui.js b/module/product/js/track.ui.js
index d7a60b1d2a..279742ad6b 100644
--- a/module/product/js/track.ui.js
+++ b/module/product/js/track.ui.js
@@ -8,7 +8,7 @@ window.getItem = function(info)
info.item.content.push({html: "
" + langStoryStatusList[info.item.status] + "
"});
info.item.content.push({html: "" + langStoryStageList[info.item.stage] + '
'})
}
- if(col == 'project' || col == 'execution')
+ else if(col == 'project' || col == 'execution')
{
let delayHtml = '';
let titleHtml = info.item.title;
@@ -20,6 +20,37 @@ window.getItem = function(info)
info.item.content.push({html: "" + langProjectStatusList[info.item.status] + "
"});
info.item.content.push({component: 'ProgressCircle', props: {percent: info.item.progress, size: 24}});
}
+ else if(col == 'task')
+ {
+ console.log(info);
+ titleHtml = "" + info.item.title + "";
+ info.item.title = {html: "" + langTaskPriList[info.item.pri] + " " + titleHtml + '
'}
+ info.item.content = [];
+ if(info.item.parent == '-1') info.item.content.push({html: "" + langChildren + " "});
+ info.item.content.push({html: "" + langTaskStatusList[info.item.status] + "
"});
+ if(info.item.assignedTo) info.item.content.push({html: " " + (typeof(users[info.item.assignedTo]) ? users[info.item.assignedTo] : info.item.assignedTo)});
+ info.item.content.push({component: 'ProgressCircle', props: {percent: info.item.progress, size: 24}});
+ }
+}
+
+window.itemRender = function(info)
+{
+ if(info.col == 'task' && info.item.parent > '0') info.item.className.push('hidden parent-' + info.item.parent);
+}
+
+window.toggleChildren = function(obj, parentID)
+{
+ console.log(obj);
+ if($(obj).hasClass('is-expanded'))
+ {
+ $(obj).removeClass('is-expanded').addClass('is-collapsed');
+ $('.parent-' + parentID).addClass('hidden')
+ }
+ else
+ {
+ $(obj).removeClass('is-collapsed').addClass('is-expanded');
+ $('.parent-' + parentID).removeClass('hidden')
+ }
}
window.canDrop = function(){ return false;}
diff --git a/module/product/ui/track.html.php b/module/product/ui/track.html.php
index d7dce3cb87..f3862dfd93 100644
--- a/module/product/ui/track.html.php
+++ b/module/product/ui/track.html.php
@@ -45,10 +45,15 @@ toolbar
);
$this->loadModel('project');
-jsVar('langStoryPriList', $lang->story->priList);
-jsVar('langStoryStatusList', $lang->story->statusList);
-jsVar('langStoryStageList', $lang->story->stageList);
+$this->loadModel('task');
+jsVar('langStoryPriList', $lang->story->priList);
+jsVar('langStoryStatusList', $lang->story->statusList);
+jsVar('langStoryStageList', $lang->story->stageList);
jsVar('langProjectStatusList', $lang->project->statusList);
+jsVar('langTaskPriList', $lang->task->priList);
+jsVar('langTaskStatusList', $lang->task->statusList);
+jsVar('langChildren', $lang->task->childrenAB);
+jsVar('users', $users);
empty($tracks) ? div(setClass('dtable-empty-tip bg-white shadow'), span(setClass('text-gray'), $lang->noData)) : div
(
@@ -56,7 +61,7 @@ empty($tracks) ? div(setClass('dtable-empty-tip bg-white shadow'), span(setClass
zui::kanbanList
(
set::key('kanban'),
- set::items(array(array('data' => $tracks, 'getItem' => jsRaw('window.getItem'), 'canDrop' => jsRaw('window.canDrop')))),
+ set::items(array(array('data' => $tracks, 'getItem' => jsRaw('window.getItem'), 'itemRender' => jsRaw('window.itemRender'), 'canDrop' => jsRaw('window.canDrop')))),
set::height('calc(100vh - 130px)')
),
pager(setClass('justify-end'))
diff --git a/module/story/tao.php b/module/story/tao.php
index 51e995a48a..9601529c13 100644
--- a/module/story/tao.php
+++ b/module/story/tao.php
@@ -2197,7 +2197,7 @@ class storyTao extends storyModel
$executions = zget($projectGroup, 'execution', array());
$designs = zget($designGroup, 'design', array());
$commits = zget($designGroup, 'commit', array());
- $tasks = $this->dao->select('id,pri,status,name as title,assignedTo,story')->from(TABLE_TASK)->where('story')->in($storyIdList)->andWhere('deleted')->eq(0)->orderBy('parent')->fetchGroup('story', 'id');
+ $tasks = $this->getTasksForTrack($storyIdList);
$cases = $this->dao->select('id,pri,status,title,story')->from(TABLE_CASE)->where('story')->in($storyIdList)->andWhere('deleted')->eq(0)->fetchGroup('story', 'id');
$bugs = $this->dao->select('id,pri,status,title,story')->from(TABLE_BUG)->where('story')->in($storyIdList)->andWhere('deleted')->eq(0)->fetchGroup('story', 'id');
$storyGrade = $this->getGradeGroup();
@@ -2297,4 +2297,43 @@ class storyTao extends storyModel
return $storyGroup;
}
+
+ /**
+ * 根据需求ID列表获取关联的任务
+ * Get linked tasks by story id list.
+ *
+ * @param array $storyIdList
+ * @access public
+ * @return array
+ */
+ public function getTasksForTrack(array $storyIdList): array
+ {
+ $stmt = $this->dao->select('id,pri,status,name as title,assignedTo,story,estimate,consumed,`left`,parent')->from(TABLE_TASK)->where('story')->in($storyIdList)->andWhere('deleted')->eq(0)->orderBy('parent')->query();
+ $tasks = array();
+ while($task = $stmt->fetch())
+ {
+ $task->progress = 0;
+ if($task->consumed + $task->left) $task->progress = round(($task->consumed / ($task->consumed + $task->left)) * 100, 2);
+
+ if($task->parent > 0 && isset($tasks[$task->parent]))
+ {
+ $tasks[$task->parent]->children[$task->id] = $task;
+ }
+ else
+ {
+ $tasks[$task->id] = $task;
+ }
+ }
+
+ $taskGroup = array();
+ foreach($tasks as $task)
+ {
+ $children = !empty($task->children) ? $task->children : array();
+ unset($task->children);
+
+ $taskGroup[$task->story][$task->id] = $task;
+ foreach($children as $subTask) $taskGroup[$subTask->story][$subTask->id] = $subTask;
+ }
+ return $taskGroup;
+ }
}