This commit is contained in:
wangyidong
2024-06-12 10:22:23 +08:00
14 changed files with 199 additions and 4 deletions
+10 -1
View File
@@ -14547,7 +14547,16 @@ REPLACE INTO `zt_approvalflowspec` (`id`, `flow`, `version`, `nodes`, `createdBy
REPLACE INTO `zt_lang` (`lang`, `module`, `section`, `key`, `value`, `system`) VALUES
('all', 'process', 'classify', 'support', '支持过程', '1'),
('all', 'process', 'classify', 'engineering', '工程支持', '1'),
('all', 'process', 'classify', 'project', '项目管理', '1');
('all', 'process', 'classify', 'project', '项目管理', '1'),
('all', 'process', 'scrumClassify', 'support', '支持过程', '1'),
('all', 'process', 'scrumClassify', 'engineering', '工程支持', '1'),
('all', 'process', 'scrumClassify', 'project', '项目管理', '1'),
('all', 'process', 'agileplusClassify', 'support', '支持过程', '1'),
('all', 'process', 'agileplusClassify', 'engineering', '工程支持', '1'),
('all', 'process', 'agileplusClassify', 'project', '项目管理', '1'),
('all', 'process', 'waterfallplusClassify', 'support', '支持过程', '1'),
('all', 'process', 'waterfallplusClassify', 'engineering', '工程支持', '1'),
('all', 'process', 'waterfallplusClassify', 'project', '项目管理', '1');
REPLACE INTO `zt_process` (`id`, `model`, `name`, `type`, `abbr`, `desc`, `assignedTo`, `status`, `order`, `createdBy`, `createdDate`, `editedBy`, `editedDate`, `assignedBy`, `assignedDate`, `deleted`) VALUES
(11, 'waterfall', '立项管理', 'project', 'PIM', '', '', '', 55, 'admin', '2020-01-09 10:29:55', '', '1970-01-01 00:00:01', '', '1970-01-01 00:00:01', '0'),
+1 -1
View File
@@ -135,7 +135,7 @@ class form extends fixer
}
else
{
$configObject[$field->field] = array('required' => $required, 'type' => 'string');
$configObject[$field->field] = array('required' => $required, 'type' => 'string', 'default' => '');
if($field->control == 'richtext') $configObject[$field->field]['control'] = 'editor';
}
}
+1
View File
@@ -35,3 +35,4 @@ $config->index->oldPages[] = 'ai-promptview';
$config->index->oldPages[] = 'api-debug';
$config->index->oldPages[] = 'datatable-ajaxoldcustom';
$config->index->oldPages[] = 'weekly-index';
$config->index->oldPages[] = 'kanban-importticket';
+2
View File
@@ -381,6 +381,8 @@ class kanban extends control
$regionID = !isset($regions[$regionID]) ? 'all' : $regionID;
$this->session->set('regionID', $regionID, 'kanban');
$this->kanbanZen->setUserAvatar();
$this->view->title = $this->lang->kanban->view;
$this->view->kanban = $kanban;
$this->view->regions = $regions;
+34 -1
View File
@@ -114,7 +114,7 @@ window.buildColCardActions = function(col)
if(kanban.object.indexOf('releases') != -1) items.push({text: kanbanLang.importRelease, url: $.createLink('kanban', 'importRelease', `kanbanID=${kanbanID}&regionID=${col.region}&groupID=${col.group}&columnID=${col.id}`), 'data-toggle': 'modal', 'data-size': 'lg'});
if(kanban.object.indexOf('executions') != -1) items.push({text: kanbanLang.importExecution, url: $.createLink('kanban', 'importExecution', `kanbanID=${kanbanID}&regionID=${col.region}&groupID=${col.group}&columnID=${col.id}`), 'data-toggle': 'modal', 'data-size': 'lg'});
if(kanban.object.indexOf('builds') != -1) items.push({text: kanbanLang.importBuild, url: $.createLink('kanban', 'importBuild', `kanbanID=${kanbanID}&regionID=${col.region}&groupID=${col.group}&columnID=${col.id}`), 'data-toggle': 'modal', 'data-size': 'lg'});
//{text: kanbanLang.importTicket, url: $.createLink('kanban', 'importTicket', `kanbanID=${kanbanID}&regionID=${col.region}&groupID=${col.group}&columnID=${col.id}`), 'data-toggle': 'modal', 'data-size': 'lg'},
if(kanban.object.indexOf('tickets') != -1) items.push({text: kanbanLang.importTicket, url: $.createLink('kanban', 'importTicket', `kanbanID=${kanbanID}&regionID=${col.region}&groupID=${col.group}&columnID=${col.id}`), 'data-toggle': 'modal', 'data-type': 'iframe'}),
actions.push(
{
text: kanbanLang.importAB,
@@ -301,8 +301,41 @@ window.renderProductplanItem = function(info)
info.item.contentClass = 'text-gray clip mr-2';
info.item.footer = {html: statusBox + date}
}
window.renderTicketItem = function(info)
{
info.item.icon = 'ticket';
info.item.titleUrl = canViewTicket ? $.createLink('ticket', 'view', `id=${info.item.fromID}`) : '';
info.item.titleAttrs = {'class': 'card-title clip', 'title': info.item.title};
if(info.item.deleted == '0')
{
statusBox = '<span class="label label-' + info.item.objectStatus + '">' + ticketLang.statusList[info.item.objectStatus] + '</span>';
}
else
{
statusBox = '<span class="label label-deleted">' + ticketLang.deleted + '</span>';
}
const date = info.item.deadline && info.item.deadline != '0000-00-00' ? '<span class="ml-2 label gray-pale">' + info.item.deadline.slice(5) + ' ' + cardLang.deadlineAB + '</span>' : '';
let avatar = '';
if(info.item.assignedTo && typeof userList[info.item.assignedTo] != 'undefined')
{
const user = userList[info.item.assignedTo];
const assignedTo = user.realname;
const userAvatar = user.avatar ? "<img src='" + user.avatar + "' />" : info.item.assignedTo.substr(0, 1).toUpperCase();
avatar = "<span class='avatar rounded-full size-xs ml-1 primary' title=" + assignedTo + '>' + userAvatar + '</span>';
}
const content = `
<div class='flex items-center'>
${statusBox}
${date}
<div class='flex-1 flex justify-end'>${avatar}</div>
</div>
`;
info.item.content = {html: content};
}
function renderAvatar(avatarList)
+3
View File
@@ -63,6 +63,7 @@ jsVar('cardLang', $lang->kanbancard);
jsVar('executionLang', $lang->execution);
jsVar('releaseLang', $lang->release);
jsVar('productplanLang', $lang->productplan);
jsVar('ticketLang', isset($lang->ticket) ? $lang->ticket : '');
jsVar('kanbanID', $kanban->id);
jsVar('kanban', $kanban);
jsVar('groupCols', $groupCols);
@@ -74,6 +75,8 @@ jsVar('canViewPlan', common::hasPriv('productplan', 'view') && $config->vision !
jsVar('canViewRelease', common::hasPriv('release', 'view') && $config->vision != 'lite');
jsVar('canViewExecution', common::hasPriv('execution', 'task') && $config->vision != 'lite');
jsVar('canViewBuild', common::hasPriv('build', 'view') && $config->vision != 'lite');
jsVar('canViewTicket', common::hasPriv('ticket', 'view'));
jsVar('userList', $userList);
dropmenu(set::tab('kanban'), set::objectID($kanban->id));
+26
View File
@@ -61,4 +61,30 @@ class kanbanZen extends kanban
$this->display();
}
/**
* 设置用户头像。
* Set user avatar data.
*
* @access public
* @return void
*/
public function setUserAvatar(): void
{
/* Get user list. */
$userList = array();
$users = $this->loadModel('user')->getPairs('noletter|nodeleted');
$avatarPairs = $this->user->getAvatarPairs('all');
foreach($avatarPairs as $account => $avatar)
{
if(!isset($users[$account])) continue;
$userList[$account]['realname'] = $users[$account];
$userList[$account]['avatar'] = $avatar;
}
$userList['closed']['account'] = 'Closed';
$userList['closed']['realname'] = 'Closed';
$userList['closed']['avatar'] = '';
$this->view->userList = $userList;
}
}
+2 -1
View File
@@ -1324,7 +1324,8 @@ class storyModel extends model
}
$story->reviewer = implode(',', $story->reviewer);
if($story->reviewer) $story->status = ($this->config->systemMode == 'PLM' and $oldStory->type == 'requirement' and $story->status == 'active' and $this->config->vision == 'rnd') ? 'launched' : 'reviewing';
if($story->reviewer) $story->status = 'reviewing';
if($this->config->systemMode == 'PLM' && $this->config->vision == 'rnd' && $oldStory->type == 'requirement' && $story->status == 'active') $story->status = 'launched';
$this->dao->update(TABLE_STORY)->data($story, 'reviewer')->where('id')->in($twinsIdList)->exec();
+1
View File
@@ -120,6 +120,7 @@ $fields->field('pri')
$fields->field('estimate')
->width('1/4')
->control(array('control' => 'number'))
->required($createFields['estimate']['required'])
->label($lang->story->estimateAB . $lang->story->estimateUnit)
->value($createFields['estimate']['default']);
+1
View File
@@ -97,6 +97,7 @@ $config->upgrade->execFlow['20_0_alpha1'] = array('functions' => 'revertStoryCus
$config->upgrade->execFlow['20_0_beta1'] = array('functions' => 'hideOA,updateMetricDateType,update18101,migrateAIModelConfig');
$config->upgrade->execFlow['20_0_beta2'] = array('functions' => 'updateWorkflowFieldDefaultValue,update1811,updateZeroDateToNull,updateProgramplanCustom');
$config->upgrade->execFlow['20_0'] = array('functions' => 'openCacheByAPCu');
$config->upgrade->execFlow['20_1_0'] = array('functions' => 'completeClassifyLang');
if(!empty($config->isINT))
{
+42
View File
@@ -8816,4 +8816,46 @@ class upgradeModel extends model
{
return $this->loadModel('install')->enableDaoCache();
}
/**
* 补充分类项语言项。
* Complete classify lang.
*
* @access public
* @return bool
*/
public function completeClassifyLang()
{
$this->app->loadLang('install');
$classifyLang = $this->dao->select('*')->from(TABLE_LANG)
->where('lang')->eq('all')
->andWhere('module')->eq('process')
->andWhere('section')->in(array('scrumClassify', 'agileplusClassify', 'waterfallplusClassify'))
->andWhere('`key`')->in(array('support', 'engineering', 'project'))
->andWhere('vision')->eq('rnd')
->fetchGroup('section', 'key');
foreach(array('scrum', 'agileplus', 'waterfallplus') as $modal)
{
foreach($this->lang->install->langList as $langInfo)
{
if($langInfo['module'] != 'process') continue;
if(isset($classifyLang[$modal . 'Classify'][$langInfo['key']])) continue;
$classifyData = new stdclass();
$classifyData->lang = 'all';
$classifyData->module = 'process';
$classifyData->section = $modal . 'Classify';
$classifyData->key = $langInfo['key'];
$classifyData->value = $langInfo['value'];
$classifyData->vision = 'rnd';
$classifyData->system = 1;
$this->dao->replace(TABLE_LANG)->data($classifyData)->exec();
}
}
return true;
}
}
@@ -738,4 +738,26 @@ class upgradeTest
$this->objectModel->revertStoryCustomFields();
return $this->objectModel->dao->select('*')->from(TABLE_CONFIG)->where('module')->eq('datatable')->andWhere('section')->eq('productBrowse')->andWhere('key')->eq('cols')->fetch();
}
/**
* 测试补充模型分类项。
* Test complete classify lang.
*
* @param string $section
* @param string $key
* @access public
* @return string
*/
public function completeClassifyLangTest(string $section, string $key): string
{
$this->objectModel->completeClassifyLang();
return $this->objectModel->dao->select('value')->from(TABLE_LANG)
->where('lang')->eq('all')
->andWhere('module')->eq('process')
->andWhere('section')->eq($section)
->andWhere('`key`')->eq($key)
->andWhere('system')->eq(1)
->andWhere('vision')->eq('rnd')
->fetch('value');
}
}
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env php
<?php
/**
title=测试 upgradeModel->completeClassifyLang();
timeout=0
cid=1
- 检查数据库中已经给融合敏捷模型添加了project分类项 @项目管理
- 检查数据库中敏捷模型未添加project分类项 @项目管理
- 检查数据库中已经给融合瀑布模型添加了support,engineering,没添加project分类项 @项目管理
*/
include dirname(__FILE__, 5) . '/test/lib/init.php';
include dirname(__FILE__, 2) . '/lib/upgrade.unittest.class.php';
su('admin');
$langData = zenData('lang')->loadYaml('lang_completeclassifylang')->gen(8);
global $tester, $app;
$upgrade = new upgradeTest();
r($upgrade->completeClassifyLangTest('agileplusClassify', 'project')) && p() && e('项目管理'); // 检查数据库中已经给融合敏捷模型添加了project分类项
r($upgrade->completeClassifyLangTest('scrumClassify', 'project')) && p() && e('项目管理'); // 检查数据库中敏捷模型未添加project分类项
r($upgrade->completeClassifyLangTest('waterfallplusClassify', 'project')) && p() && e('项目管理'); // 检查数据库中已经给融合瀑布模型添加了support,engineering,没添加project分类项
@@ -0,0 +1,26 @@
title: table zt_lang
desc: "语言项"
author: Fangzhou Hu
version: "1.0"
fields:
- field: lang
note: "语言"
range: all
- field: module
note: "模块"
range: process
- field: section
note: "板块"
range: waterfall{3},agileplusClassify{3},waterfallplusClassify{2}
- field: key
note: "键"
range: support,engineering,project
- field: value
note: "值"
range: 支持过程,工程支持,项目管理
- field: system
note: "是否系统内置"
range: 1
- field: vision
note: "界面"
range: rnd