| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- <?php
- /**
- * The view file of charter module of ZenTaoPMS.
- *
- * @copyright Copyright 2009-2024 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
- * @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
- * @author Yuting Wang <wangyuting@easycorp.ltd>
- * @package charter
- * @link https://www.zentao.net
- */
- namespace zin;
- jsVar('browseType', zget($_SESSION, 'browseType', 'all'));
- jsVar('vision', $config->vision);
- jsVar('userViewProjects', ",{$app->user->view->projects},");
- /* 初始化头部右上方工具栏。Init detail toolbar. */
- $toolbar = array();
- if(!isInModal() && hasPriv('charter', 'create'))
- {
- $toolbar[] = array
- (
- 'icon' => 'plus',
- 'type' => 'primary',
- 'text' => $lang->charter->create,
- 'url' => createLink('charter', 'create')
- );
- }
- /* 基本信息 */
- $basicInfoItems = array();
- $basicInfoItems[$lang->charter->level] = array('control' => 'priLabel', 'text' => zget($levelList, $charter->level), 'pri' => $charter->level);
- $basicInfoItems[$lang->charter->category] = array('control' => 'text', 'text' => zget($lang->charter->categoryList, $charter->category));
- $basicInfoItems[$lang->charter->market] = array('control' => 'text', 'text' => zget($lang->charter->marketList, $charter->market));
- $basicInfoItems[$lang->charter->budget] = array('control' => 'text', 'text' => $charter->budget);
- $basicInfoItems[$lang->charter->status] = array('control' => 'text', 'text' => zget($lang->charter->statusList, $charter->status));
- $basicInfoItems[$lang->charter->reviewStatus] = array('control' => 'text', 'text' => $charter->status == 'closed' || ($charter->status == 'wait' && $charter->reviewStatus == 'wait') || ($charter->status == 'canceled' && $charter->prevCanceledStatus == 'wait') ? '' : zget($lang->charter->reviewStatusList, $charter->reviewStatus));
- $basicInfo = datalist
- (
- set::className('charter-basic-info'),
- set::items($basicInfoItems)
- );
- $projectApproval = zget($charter->approvalList, 'projectApproval', array());
- $completionApproval = zget($charter->approvalList, 'completionApproval', array());
- $cancelProjectApproval = zget($charter->approvalList, 'cancelProjectApproval', array());
- $activateProjectApproval = zget($charter->approvalList, 'activateProjectApproval', array());
- function convertUserName($accounts, $users)
- {
- $userName = '';
- foreach(explode(',', $accounts) as $account)
- {
- if(empty($account)) continue;
- $userName .= zget($users, trim($account)) . ' ';
- }
- return $userName;
- }
- /* 立项的一生 */
- $lifeTimeItems = array();
- $lifeTimeItems[$lang->charter->createdBy] = array('control' => 'text', 'text' => $charter->createdBy ? zget($users, $charter->createdBy) . $lang->at . $charter->createdDate : '');
- $lifeTimeItems[$lang->charter->charteredBy] = array('control' => 'text', 'text' => !empty($projectApproval['appliedBy']) ? zget($users, $projectApproval['appliedBy']) . $lang->at . $projectApproval['appliedDate'] : '');
- $lifeTimeItems[$lang->charter->charterReviewers] = array('control' => 'text', 'text' => !empty($projectApproval['reviewers']) ? convertUserName($projectApproval['reviewers'], $users) : '');
- $lifeTimeItems[$lang->charter->completionBy] = array('control' => 'text', 'text' => !empty($completionApproval['appliedBy']) ? zget($users, $completionApproval['appliedBy']) . $lang->at . $completionApproval['appliedDate'] : '');
- $lifeTimeItems[$lang->charter->completionReviewers] = array('control' => 'text', 'text' => !empty($completionApproval['reviewers']) ? convertUserName($completionApproval['reviewers'], $users) : '');
- $lifeTimeItems[$lang->charter->canceledBy] = array('control' => 'text', 'text' => !empty($cancelProjectApproval['appliedBy']) ? zget($users, $cancelProjectApproval['appliedBy']) . $lang->at . $cancelProjectApproval['appliedDate'] : '');
- $lifeTimeItems[$lang->charter->canceledReviewers] = array('control' => 'text', 'text' => !empty($cancelProjectApproval['reviewers']) ? convertUserName($cancelProjectApproval['reviewers'], $users) : '');
- $lifeTimeItems[$lang->charter->activatedBy] = array('control' => 'text', 'text' => !empty($activateProjectApproval['appliedBy']) ? zget($users, $activateProjectApproval['appliedBy']) . $lang->at . $activateProjectApproval['appliedDate'] : '');
- $lifeTimeItems[$lang->charter->activatedReviewers] = array('control' => 'text', 'text' => !empty($activateProjectApproval['reviewers']) ? convertUserName($activateProjectApproval['reviewers'], $users) : '');
- $lifeTimeItems[$lang->charter->closedBy] = array('control' => 'text', 'text' => $charter->closedBy ? zget($users, $charter->closedBy) . $lang->at . $charter->closedDate : '');
- $lifeTime = datalist
- (
- set::className('charter-life-item'),
- set::items($lifeTimeItems)
- );
- $tabs = array();
- $tabs[] = setting()
- ->group('basic')
- ->title($lang->charter->legendBasicInfo)
- ->children(wg($basicInfo));
- $tabs[] = setting()
- ->group('life')
- ->title($lang->charter->legendLifeTime)
- ->children(wg($lifeTime));
- /* 获取文件信息。*/
- function getFileData($charter, $reviewType)
- {
- global $config;
- $fileData = array();
- $charterFiles = !empty($charter->filesConfig) ? json_decode($charter->filesConfig, true) : json_decode($config->custom->charterFiles, true);
- if(!empty($charterFiles[$charter->level]))
- {
- foreach($charterFiles[$charter->level][$reviewType] as $file)
- {
- $fileData[] = div(setClass('flex'), cell(set::width('100px'), setClass('p-1 text-left text-gray text-clip'), set::title($file['name']), $file['name']), cell(setClass('pl-1'), fileList(set::files($charter->files), set::extra($reviewType . '-' . $file['index']), set::object($charter), set::fieldset(false), set::showDelete(false))));
- }
- }
- return $fileData;
- }
- /* 产品和计划/路标 */
- $tableData = array();
- $canViewProduct = common::hasPriv('product', 'view');
- $this->loadModel('productplan');
- foreach($groupDate as $productID => $linkedList)
- {
- $hasPriv = $this->product->checkPriv($productID);
- $linkedData = array();
- $productInfo = zget($products, $productID);
- $isLaunched = $productInfo->vision == 'rnd' || strpos(",{$productInfo->vision},", ",{$config->vision},") !== false;
- foreach($linkedList as $data)
- {
- $module = $data->linkedType == 'plan' ? 'productplan' : $data->linkedType;
- $linkedURL = $this->createLink($module, 'view', "id=$data->id");
- $linkedName = $data->linkedName . " [{$data->begin} ~ {$data->end}]";;
- if($data->begin == $this->config->productplan->future && $data->end == $this->config->productplan->future) $linkedName = $data->linkedName . ' ' . $this->lang->productplan->future;
- if($productInfo->type != 'normal')
- {
- $branchName = '';
- foreach(explode(',', (string)$data->branch) as $dataBranch) $branchName .= !empty($branchGroups[$data->product]) && !empty($branchGroups[$data->product][$dataBranch]) ? $branchGroups[$data->product][$dataBranch] . ',' : '';
- $linkedName = $linkedName . ' / ' . trim($branchName, ',');
- }
- $class = 'clip';
- if(count($linkedList) <= 2) $class .= ' flex flex-1 w-0 items-center';
- if(count($linkedList) > 2) $class .= ' flex-none w-1/3';
- if(count($linkedData) > 2) $class .= ' mt-2';
- if(count($linkedData) % 3 != 0) $class .= ' pl-6';
- $linkedData[] = div
- (
- setClass($class),
- icon('productplan mr-2 '),
- hasPriv($module, 'view') ? a
- (
- set::title($linkedName),
- set::href($linkedURL),
- span($linkedName)
- )
- : span($linkedName)
- );
- }
- $productItems = array();
- $productLink = $this->createLink('product', 'view', "productID=$productID");
- if(isset($branchGroups[$productID]))
- {
- foreach($branchGroups[$productID] as $branchID => $branchName)
- {
- $branchName = $productInfo->name . '/' . $branchName;
- $productItems[] = $canViewProduct && $isLaunched && $hasPriv ? div(setClass('flex clip w-full items-center'), icon('product mr-2'), a(setClass('flex'), set::href($productLink), set::title($branchName), span(setClass('flex-1'), setStyle('width', '0'), $branchName))) : div($branchName);
- }
- }
- else
- {
- $productItems[] = $canViewProduct && $isLaunched && $hasPriv ? div(setClass('flex clip w-full items-center'), icon('product mr-2'), a(setClass('flex'), set::href($productLink), set::title($productInfo->name), span(setClass('flex-1'), setStyle('width', '0'), $productInfo->name))) : div($productInfo->name);
- }
- $tableData[] = h::tr(setClass('text-center'), h::td(html($productItems)), h::td(div(setClass('flex flex-wrap'), $linkedData)));
- }
- /* 立项信息 */
- $charterInfo = div
- (
- div
- (
- setClass('text-base font-semibold py-1'),
- $lang->charter->spec
- ),
- div
- (
- setClass('py-1'),
- html($charter->spec)
- ),
- div
- (
- setClass('text-base font-semibold py-1'),
- $lang->charter->charterFiles
- ),
- div
- (
- setClass('py-1'),
- div(getFileData($charter, 'projectApproval'))
- ),
- div
- (
- setClass('text-base font-semibold py-1'),
- $charter->type == 'plan' ? $lang->charter->productAndPlan : $lang->charter->productRoadmap
- ),
- !empty($groupDate) ? h::table
- (
- setClass('table bordered'),
- h::tr(h::th(setClass('w-64'), $lang->charter->product), h::th($charter->type == 'plan' ? $lang->charter->plan : $lang->charter->roadmap)),
- $tableData
- ) : null
- );
- $sections = array();
- $sections[] = setting()
- ->title($lang->charter->charterInfo)
- ->children(wg($charterInfo));
- /* 项目集和项目 */
- $programAndProjectDetail = null;
- foreach($programList as $program)
- {
- $programBudget = $this->loadModel('project')->getBudgetWithUnit($program->budget);
- $program->budget = !empty($program->budget) ? zget($lang->project->currencySymbol, $program->budgetUnit) . ' ' . $programBudget : $lang->project->future;
- }
- if(!empty($programList))
- {
- $programAndProjectDetail = div
- (
- setClass('detail-sections canvas shadow rounded px-6 py-4'),
- div
- (
- setClass('detail-section'),
- div
- (
- setClass('detail-section-title row items-center gap-2'),
- span
- (
- setClass('text-md py-1 font-bold'),
- $lang->charter->programAndProject
- )
- ),
- div
- (
- dtable
- (
- set::onRenderCell(jsRaw('window.onRenderCell')),
- set::cols($config->charter->programList->fieldList),
- set::data(array_values($programList)),
- set::checkable(false),
- set::sortType(false),
- set::userMap(array(0 => '') + $users)
- )
- )
- )
- );
- }
- function printBlockInfo($blockTitle, $blockContent)
- {
- $blockInfo = div
- (
- setClass('detail-sections canvas shadow rounded px-6 py-4'),
- div
- (
- setClass('detail-section'),
- div
- (
- setClass('detail-section-title row items-center gap-2'),
- span
- (
- setClass('text-md py-1 font-bold'),
- $blockTitle
- )
- ),
- div
- (
- setClass('detail-section-content py-1'),
- div
- (
- setClass('text-base font-semibold py-1'),
- $blockContent['desc']['title']
- ),
- div
- (
- setClass('py-1'),
- html($blockContent['desc']['content'])
- ),
- div
- (
- setClass('text-base font-semibold py-1'),
- $blockContent['file']['title']
- ),
- div
- (
- setClass('py-1'),
- div($blockContent['file']['content'])
- )
- )
- )
- );
- return $blockInfo;
- }
- /* 操作栏 */
- if(!empty($charter->approval)) $config->charter->actions->view['mainActions'][] = 'approvalProgress';
- if($config->vision == 'rnd' && $charter->status == 'launched' && !in_array($charter->reviewStatus, array('completionDoing', 'cancelDoing'))) $config->charter->actions->view['mainActions'][] = 'createProgramAndProject';
- if($this->charter->isClickable($charter, 'projectapproval'))
- {
- $config->charter->actionList['cancelProjectApproval']['hint'] = $lang->charter->abbr->cancel;
- $config->charter->actionList['cancelProjectApproval']['data-toggle'] = 'modal';
- }
- if($charter->prevCanceledStatus == 'wait')
- {
- $config->charter->actionList['activateProjectApproval']['hint'] = $lang->charter->abbr->activate;
- }
- $operateList = $this->loadModel('common')->buildOperateMenu($charter);
- $actions = empty($operateList['suffixActions']) ? $operateList['mainActions'] : array_merge($operateList['mainActions'], array(array('type' => 'divider')), $operateList['suffixActions']);
- detail
- (
- set::urlFormatter(array('{id}' => $charter->id, '{from}' => 'view', '{approval}' => $charter->approval)),
- set::toolbar($toolbar),
- set::sections($sections),
- $programAndProjectDetail,
- set::tabs($tabs),
- set::actions(array_values($actions)),
- in_array($charter->reviewStatus, array('completionDoing', 'completionReject', 'completionPass')) ? printBlockInfo($lang->charter->completionInfo, array('desc' => array('title' => $lang->charter->completionDesc, 'content' => zget($charter, 'completionApprovalDesc', '')), 'file' => array('title' => $lang->charter->completionFiles, 'content' => getFileData($charter, 'completeApproval')))) : null,
- in_array($charter->reviewStatus, array('cancelDoing', 'cancelReject', 'cancelPass', 'activateDoing', 'activateReject')) ? printBlockInfo($lang->charter->canceledInfo, array('desc' => array('title' => $lang->charter->canceledDesc, 'content' => zget($charter, 'cancelProjectApprovalDesc', '')), 'file' => array('title' => $lang->charter->canceledFiles, 'content' => getFileData($charter, 'cancelApproval')))) : null
- );
|