From 35030b29c8e39830974943c26adfffd55ee6530b Mon Sep 17 00:00:00 2001 From: sunguangming Date: Mon, 14 Apr 2025 07:50:01 +0000 Subject: [PATCH 001/136] * [misc] show resolution. --- lib/zin/wg/buglifeinfo/v1.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/zin/wg/buglifeinfo/v1.php b/lib/zin/wg/buglifeinfo/v1.php index dd5ee45347..a015587e85 100644 --- a/lib/zin/wg/buglifeinfo/v1.php +++ b/lib/zin/wg/buglifeinfo/v1.php @@ -49,11 +49,8 @@ class bugLifeInfo extends wg setData('size', 'lg') ) : null ); - $items[$lang->bug->resolution] = array - ( - 'control' => 'div', - 'content' => $duplicateBugText - ); + + $items[$lang->bug->resolution] = array('children' => $duplicateBugText); $items[$lang->bug->closedBy] = zget($users, $bug->closedBy) . (formatTime($bug->closedDate) ? $lang->at . $bug->closedDate : ''); $items[$lang->bug->lblLastEdited] = zget($users, $bug->lastEditedBy, $bug->lastEditedBy) . (formatTime($bug->lastEditedDate) ? $lang->at . $bug->lastEditedDate : ''); From 685cec4483b45a7643f6b3f941f85bdcdf7db585 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Mon, 14 Apr 2025 08:09:48 +0000 Subject: [PATCH 002/136] * [task#141575,done,0.2h] finish task. --- lib/zin/wg/dropmenu/css/v1.css | 2 +- module/admin/lang/zh-cn.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/zin/wg/dropmenu/css/v1.css b/lib/zin/wg/dropmenu/css/v1.css index a1308d5d1a..9904ddbb1d 100644 --- a/lib/zin/wg/dropmenu/css/v1.css +++ b/lib/zin/wg/dropmenu/css/v1.css @@ -1,4 +1,4 @@ -#pick-pop-admin-menu {width: 139px!important;} +#pick-pop-admin-menu {width: 145px!important;} #pick-pop-admin-menu .dropmenu-list {padding: 8px;} #pick-pop-admin-menu .dropmenu-item + .dropmenu-item {margin-top: 4px} #pick-pop-admin-menu .dropmenu-item.active {background-color: unset;} diff --git a/module/admin/lang/zh-cn.php b/module/admin/lang/zh-cn.php index 2be5c58512..fda8f7b722 100755 --- a/module/admin/lang/zh-cn.php +++ b/module/admin/lang/zh-cn.php @@ -170,7 +170,7 @@ $lang->admin->menuSetting['user']['name'] = '人员管理'; $lang->admin->menuSetting['user']['desc'] = '维护部门、添加人员、分组配置权限。'; $lang->admin->menuSetting['switch']['name'] = '功能开关'; $lang->admin->menuSetting['switch']['desc'] = '打开、关闭系统部分功能。'; -$lang->admin->menuSetting['model']['name'] = '模型配置'; +$lang->admin->menuSetting['model']['name'] = '项目模型配置'; $lang->admin->menuSetting['model']['desc'] = '不同项目管理模型和项目通用要素配置。'; $lang->admin->menuSetting['feature']['name'] = '功能配置'; $lang->admin->menuSetting['feature']['desc'] = '按照功能菜单进行系统的要素配置。'; From 952a94fedb3aa2ffcd24c2b2f66739091f72726d Mon Sep 17 00:00:00 2001 From: sunguangming Date: Mon, 14 Apr 2025 08:55:01 +0000 Subject: [PATCH 003/136] * [task#141578,done,0.5h] add table. --- db/update21.7.sql | 14 ++++++++++++++ db/zentao.sql | 16 ++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 db/update21.7.sql diff --git a/db/update21.7.sql b/db/update21.7.sql new file mode 100644 index 0000000000..85ba529011 --- /dev/null +++ b/db/update21.7.sql @@ -0,0 +1,14 @@ +CREATE TABLE IF NOT EXISTS `zt_deliverable` ( + `id` int(8) NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL, + `module` varchar(30) NULL, + `method` varchar(30) NULL, + `model` text NULL, + `type` enum('doc','file') NULL DEFAULT 'file', + `desc` text NULL, + `files` varchar(255) NULL, + `createdBy` varchar(30) NULL, + `createdDate` date NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/db/zentao.sql b/db/zentao.sql index 6c5c2d765a..1591d0e5e7 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -578,6 +578,22 @@ CREATE TABLE IF NOT EXISTS `zt_screen` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +-- DROP TABLE IF EXISTS `zt_deliverable`; +CREATE TABLE IF NOT EXISTS `zt_deliverable` ( + `id` int(8) NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL, + `module` varchar(30) NULL, + `method` varchar(30) NULL, + `model` text NULL, + `type` enum('doc','file') NULL DEFAULT 'file', + `desc` text NULL, + `files` varchar(255) NULL, + `createdBy` varchar(30) NULL, + `createdDate` date NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + -- DROP TABLE IF EXISTS `zt_dimension`; CREATE TABLE IF NOT EXISTS `zt_dimension` ( `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, From 3d933c7a6275dd3c724c3718075e6ca63fcf04dd Mon Sep 17 00:00:00 2001 From: sunguangming Date: Mon, 14 Apr 2025 09:17:08 +0000 Subject: [PATCH 004/136] * [task#141578,done,0.5h] modify sql, add deliverable menu. --- db/update21.7.sql | 2 +- db/zentao.sql | 2 +- module/admin/lang/menu.php | 3 ++- module/common/lang/common.php | 1 + module/common/lang/de.php | 1 + module/common/lang/en.php | 1 + module/common/lang/fr.php | 1 + module/common/lang/zh-cn.php | 1 + 8 files changed, 9 insertions(+), 3 deletions(-) diff --git a/db/update21.7.sql b/db/update21.7.sql index 85ba529011..10c07292f6 100644 --- a/db/update21.7.sql +++ b/db/update21.7.sql @@ -3,7 +3,7 @@ CREATE TABLE IF NOT EXISTS `zt_deliverable` ( `name` varchar(255) NOT NULL, `module` varchar(30) NULL, `method` varchar(30) NULL, - `model` text NULL, + `model` varchar(255) NULL, `type` enum('doc','file') NULL DEFAULT 'file', `desc` text NULL, `files` varchar(255) NULL, diff --git a/db/zentao.sql b/db/zentao.sql index 1591d0e5e7..3521246e68 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -584,7 +584,7 @@ CREATE TABLE IF NOT EXISTS `zt_deliverable` ( `name` varchar(255) NOT NULL, `module` varchar(30) NULL, `method` varchar(30) NULL, - `model` text NULL, + `model` varchar(255) NULL, `type` enum('doc','file') NULL DEFAULT 'file', `desc` text NULL, `files` varchar(255) NULL, diff --git a/module/admin/lang/menu.php b/module/admin/lang/menu.php index cef8ec25a5..34b97cbad5 100644 --- a/module/admin/lang/menu.php +++ b/module/admin/lang/menu.php @@ -74,7 +74,7 @@ $lang->admin->menuList->company['menuOrder']['5'] = 'dept'; $lang->admin->menuList->company['menuOrder']['10'] = 'browseUser'; $lang->admin->menuList->company['menuOrder']['15'] = 'group'; -$lang->admin->menuList->model['subMenu']['common'] = array('link' => "{$lang->globalSetting}|custom|required|module=project", 'subModule' => 'custom,subject,holiday,stage', 'exclude' => 'stage-browse,stage-plusbrowse,stage-create,stage-edit,stage-batchcreate'); +$lang->admin->menuList->model['subMenu']['common'] = array('link' => "{$lang->globalSetting}|custom|required|module=project", 'subModule' => 'custom,subject,holiday,stage,deliverable', 'exclude' => 'stage-browse,stage-plusbrowse,stage-create,stage-edit,stage-batchcreate'); $lang->admin->menuList->model['subMenu']['scrum'] = array('link' => "{$lang->scrumModel}|auditcl|scrumbrowse|", 'subModule' => 'auditcl'); $lang->admin->menuList->model['subMenu']['waterfall'] = array('link' => "{$lang->waterfallModel}|stage|browse|", 'subModule' => 'stage', 'exclude' => 'stage-settype,stage-plusbrowse'); $lang->admin->menuList->model['subMenu']['agileplus'] = array('link' => "{$lang->agilePlusModel}|auditcl|agileplusbrowse|", 'subModule' => 'auditcl'); @@ -88,6 +88,7 @@ $lang->admin->menuList->model['menuOrder']['25'] = 'waterfallplus'; $lang->admin->menuList->model['tabMenu']['common']['project'] = array('link' => "{$lang->project->common}|custom|required|module=project", 'alias' => 'set,project', 'exclude' => 'custom-required', 'links' => array('custom|set|module=project&field=unitList')); if(helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['common']['stage'] = array('link' => "{$lang->stage->type}|stage|settype|", 'subModule' => 'stage'); +$lang->admin->menuList->model['tabMenu']['common']['deliverable'] = array('link' => "{$lang->deliverable->common}|deliverable|browse|"); $lang->admin->menuList->model['tabMenu']['common']['build'] = array('link' => "{$lang->build->common}|custom|required|module=build", 'alias' => 'set', 'exclude' => 'custom'); $lang->admin->menuList->model['tabMenu']['common']['flow'] = array('link' => "{$lang->custom->flow}|custom|flow|", 'divider' => true); diff --git a/module/common/lang/common.php b/module/common/lang/common.php index 01677fd34a..96fc51023e 100644 --- a/module/common/lang/common.php +++ b/module/common/lang/common.php @@ -105,6 +105,7 @@ $lang->ops = new stdclass(); $lang->domain = new stdclass(); $lang->service = new stdclass(); $lang->deployment = new stdclass(); +$lang->deliverable = new stdclass(); $lang->metric = new stdclass(); $lang->ai = new stdclass(); diff --git a/module/common/lang/de.php b/module/common/lang/de.php index 46ff6aea75..7fe6806238 100644 --- a/module/common/lang/de.php +++ b/module/common/lang/de.php @@ -320,6 +320,7 @@ $lang->projectqa->common = 'QA'; $lang->holidayseason->common = 'Holiday'; $lang->codereview->common = 'Review'; $lang->repocode->common = 'Code'; +$lang->deliverable->common = 'Deliverable'; $lang->personnel->common = 'Member'; $lang->personnel->invest = 'Investment'; diff --git a/module/common/lang/en.php b/module/common/lang/en.php index d15451b81a..cc24154a4e 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -320,6 +320,7 @@ $lang->projectqa->common = 'QA'; $lang->holidayseason->common = 'Holiday'; $lang->codereview->common = 'Review'; $lang->repocode->common = 'Code'; +$lang->deliverable->common = 'Deliverable'; $lang->personnel->common = 'Member'; $lang->personnel->invest = 'Investment'; diff --git a/module/common/lang/fr.php b/module/common/lang/fr.php index 1a85fd6b83..137b3f08dc 100644 --- a/module/common/lang/fr.php +++ b/module/common/lang/fr.php @@ -320,6 +320,7 @@ $lang->projectqa->common = 'QA'; $lang->holidayseason->common = 'Holiday'; $lang->codereview->common = 'Review'; $lang->repocode->common = 'Code'; +$lang->deliverable->common = 'Deliverable'; $lang->personnel->common = 'Member'; $lang->personnel->invest = 'Investment'; diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index 22bd919f27..53f86f4665 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -320,6 +320,7 @@ $lang->projectqa->common = '测试'; $lang->holidayseason->common = '节假日'; $lang->codereview->common = '问题'; $lang->repocode->common = '代码'; +$lang->deliverable->common = '交付物'; $lang->personnel->common = '人员'; $lang->personnel->invest = '投入人员'; From 68b33617107dced9a699d17b9177ee03e89696e2 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 15 Apr 2025 00:48:57 +0000 Subject: [PATCH 005/136] * [task#141577,done,0.2h] add deliverable menu group. --- module/admin/config.php | 2 +- module/admin/lang/menu.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/module/admin/config.php b/module/admin/config.php index 48b6d8c167..f205582b85 100755 --- a/module/admin/config.php +++ b/module/admin/config.php @@ -8,7 +8,7 @@ if(!isset($config->safe->weak)) $config->safe->weak = '123456,password,12345,123 $config->admin->menuGroup['system'] = array('custom|mode', 'backup', 'cron', 'action|trash', 'admin|xuanxuan', 'setting|xuanxuan', 'admin|license', 'admin|checkweak', 'admin|resetpwdsetting', 'admin|safe', 'cache|setting', 'custom|timezone', 'search|buildindex', 'admin|tableengine', 'ldap', 'custom|libreoffice', 'conference', 'watermark', 'client', 'system|browsebackup', 'system|restorebackup'); $config->admin->menuGroup['company'] = array('dept', 'company', 'user', 'group', 'tutorial'); $config->admin->menuGroup['switch'] = array('admin|setmodule'); -$config->admin->menuGroup['model'] = array('auditcl', 'stage', 'design', 'cmcl', 'reviewcl', 'custom|required', 'custom|set', 'custom|flow', 'custom|code', 'custom|percent','custom|estimate', 'custom|hours', 'subject', 'process', 'activity', 'zoutput', 'classify', 'holiday', 'reviewsetting', 'custom|project'); +$config->admin->menuGroup['model'] = array('auditcl', 'stage', 'deliverable', 'design', 'cmcl', 'reviewcl', 'custom|required', 'custom|set', 'custom|flow', 'custom|code', 'custom|percent','custom|estimate', 'custom|hours', 'subject', 'process', 'activity', 'zoutput', 'classify', 'holiday', 'reviewsetting', 'custom|project'); $config->admin->menuGroup['feature'] = array('custom|set', 'custom|product', 'custom|execution', 'custom|required', 'custom|kanban', 'measurement', 'meetingroom', 'custom|browsestoryconcept', 'custom|kanban', 'sqlbuilder', 'report', 'custom|limittaskdate', 'measurement'); $config->admin->menuGroup['template'] = array('custom|set', 'baseline'); $config->admin->menuGroup['message'] = array('mail', 'webhook', 'sms', 'message'); diff --git a/module/admin/lang/menu.php b/module/admin/lang/menu.php index 34b97cbad5..f28086586d 100644 --- a/module/admin/lang/menu.php +++ b/module/admin/lang/menu.php @@ -99,6 +99,7 @@ if(helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu'] $lang->admin->menuList->model['tabMenu']['menuOrder']['common']['5'] = 'project'; if(helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['menuOrder']['common']['7'] = 'stage'; $lang->admin->menuList->model['tabMenu']['menuOrder']['common']['10'] = 'build'; +$lang->admin->menuList->model['tabMenu']['menuOrder']['common']['15'] = 'deliverable'; $lang->admin->menuList->model['tabMenu']['menuOrder']['common']['35'] = 'flow'; $lang->admin->menuList->model['tabMenu']['menuOrder']['common']['40'] = 'percent'; $lang->admin->menuList->model['tabMenu']['menuOrder']['common']['45'] = 'hours'; From f0e316f3524e6bc2d776bb7b72d476d694bfd282 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 15 Apr 2025 05:50:13 +0000 Subject: [PATCH 006/136] * Init deliverable. --- config/zentaopms.php | 1 + module/deliverable/config.php | 2 ++ module/deliverable/config/dtable.php | 40 +++++++++++++++++++++++++++ module/deliverable/control.php | 30 ++++++++++++++++++++ module/deliverable/lang/zh-cn.php | 13 +++++++++ module/deliverable/model.php | 9 ++++++ module/deliverable/ui/browse.html.php | 23 +++++++++++++++ module/deliverable/ui/create.html.php | 7 +++++ 8 files changed, 125 insertions(+) create mode 100644 module/deliverable/config.php create mode 100644 module/deliverable/config/dtable.php create mode 100644 module/deliverable/control.php create mode 100644 module/deliverable/lang/zh-cn.php create mode 100644 module/deliverable/model.php create mode 100644 module/deliverable/ui/browse.html.php create mode 100644 module/deliverable/ui/create.html.php diff --git a/config/zentaopms.php b/config/zentaopms.php index 7f6d012c62..ec28663e04 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -429,6 +429,7 @@ define('TABLE_ACL', '`' . $config->db->prefix . 'acl`'); define('TABLE_DESIGN', '`' . $config->db->prefix . 'design`'); define('TABLE_DESIGNSPEC', '`' . $config->db->prefix . 'designspec`'); +define('TABLE_DELIVERABLE', '`' . $config->db->prefix . 'deliverable`'); define('TABLE_DOCLIB', '`' . $config->db->prefix . 'doclib`'); define('TABLE_DOC', '`' . $config->db->prefix . 'doc`'); define('TABLE_DOCBLOCK', '`' . $config->db->prefix . 'docblock`'); diff --git a/module/deliverable/config.php b/module/deliverable/config.php new file mode 100644 index 0000000000..60b7323d66 --- /dev/null +++ b/module/deliverable/config.php @@ -0,0 +1,2 @@ +deliverable = new stdclass(); diff --git a/module/deliverable/config/dtable.php b/module/deliverable/config/dtable.php new file mode 100644 index 0000000000..6e4a197bf4 --- /dev/null +++ b/module/deliverable/config/dtable.php @@ -0,0 +1,40 @@ +deliverable->dtable = new stdclass(); + +$config->deliverable->dtable->fieldList['id']['title'] = $lang->idAB; +$config->deliverable->dtable->fieldList['id']['name'] = 'id'; +$config->deliverable->dtable->fieldList['id']['type'] = 'checkID'; +$config->deliverable->dtable->fieldList['id']['sortType'] = 'desc'; +$config->deliverable->dtable->fieldList['id']['checkbox'] = true; +$config->deliverable->dtable->fieldList['id']['width'] = '80'; +$config->deliverable->dtable->fieldList['id']['required'] = true; + +$config->deliverable->dtable->fieldList['name']['title'] = $lang->deliverable->name; +$config->deliverable->dtable->fieldList['name']['name'] = 'name'; +$config->deliverable->dtable->fieldList['name']['type'] = 'title'; +$config->deliverable->dtable->fieldList['name']['sortType'] = true; + +$config->deliverable->dtable->fieldList['module']['title'] = $lang->deliverable->module; +$config->deliverable->dtable->fieldList['module']['name'] = 'module'; +$config->deliverable->dtable->fieldList['module']['type'] = 'category'; +$config->deliverable->dtable->fieldList['module']['sortType'] = true; + +$config->deliverable->dtable->fieldList['method']['title'] = $lang->deliverable->method; +$config->deliverable->dtable->fieldList['method']['name'] = 'method'; +$config->deliverable->dtable->fieldList['method']['type'] = 'category'; +$config->deliverable->dtable->fieldList['method']['sortType'] = true; + +$config->deliverable->dtable->fieldList['model']['title'] = $lang->deliverable->model; +$config->deliverable->dtable->fieldList['model']['name'] = 'model'; +$config->deliverable->dtable->fieldList['model']['type'] = 'text'; +$config->deliverable->dtable->fieldList['model']['sortType'] = true; + +$config->deliverable->dtable->fieldList['createdBy']['title'] = $lang->deliverable->createdBy; +$config->deliverable->dtable->fieldList['createdBy']['name'] = 'createdBy'; +$config->deliverable->dtable->fieldList['createdBy']['type'] = 'user'; +$config->deliverable->dtable->fieldList['createdBy']['sortType'] = true; + +$config->deliverable->dtable->fieldList['createdDate']['title'] = $lang->deliverable->createdDate; +$config->deliverable->dtable->fieldList['createdDate']['name'] = 'createdDate'; +$config->deliverable->dtable->fieldList['createdDate']['type'] = 'date'; +$config->deliverable->dtable->fieldList['createdDate']['sortType'] = true; diff --git a/module/deliverable/control.php b/module/deliverable/control.php new file mode 100644 index 0000000000..c769828010 --- /dev/null +++ b/module/deliverable/control.php @@ -0,0 +1,30 @@ +view->deliverables = array(); + $this->view->title = $this->lang->deliverable->common; + $this->display(); + } + + /** + * 创建交付物。 + * Create deliverable. + * + * @access public + * @return void + */ + public function create() + { + $this->view->title = $this->lang->deliverable->create; + $this->display(); + } +} diff --git a/module/deliverable/lang/zh-cn.php b/module/deliverable/lang/zh-cn.php new file mode 100644 index 0000000000..1c951cf57f --- /dev/null +++ b/module/deliverable/lang/zh-cn.php @@ -0,0 +1,13 @@ +deliverable->name = '名称'; +$lang->deliverable->desc = '描述'; +$lang->deliverable->module = '适用对象'; +$lang->deliverable->method = '动作'; +$lang->deliverable->model = '适用范围'; +$lang->deliverable->createdBy = '创建人'; +$lang->deliverable->createdDate = '创建时间'; + +$lang->deliverable->create = '创建'; +$lang->deliverable->edit = '编辑'; +$lang->deliverable->delete = '删除'; +$lang->deliverable->view = '详情'; diff --git a/module/deliverable/model.php b/module/deliverable/model.php new file mode 100644 index 0000000000..c88079e3f6 --- /dev/null +++ b/module/deliverable/model.php @@ -0,0 +1,9 @@ +dao->select('*')->from(TABLE_DELIVERABLE)->fetchAll(); + return $deliverables; + } +} diff --git a/module/deliverable/ui/browse.html.php b/module/deliverable/ui/browse.html.php new file mode 100644 index 0000000000..b0b51d4fa9 --- /dev/null +++ b/module/deliverable/ui/browse.html.php @@ -0,0 +1,23 @@ + 'plus', + 'class' => 'primary', + 'text' => $lang->deliverable->create, + 'data-app' => $app->tab, + 'url' => createLink('deliverable', 'create') + ))) : null, +); + +$cols = $config->deliverable->dtable->fieldList; +dtable +( + set::cols($cols), + set::data($deliverables) +); diff --git a/module/deliverable/ui/create.html.php b/module/deliverable/ui/create.html.php new file mode 100644 index 0000000000..bbb073c399 --- /dev/null +++ b/module/deliverable/ui/create.html.php @@ -0,0 +1,7 @@ + Date: Tue, 15 Apr 2025 08:03:22 +0000 Subject: [PATCH 007/136] * [task#141578,done,2h] add css and dtable. --- module/deliverable/config/dtable.php | 1 + module/deliverable/css/create.ui.css | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 module/deliverable/css/create.ui.css diff --git a/module/deliverable/config/dtable.php b/module/deliverable/config/dtable.php index 6e4a197bf4..8ecddf487e 100644 --- a/module/deliverable/config/dtable.php +++ b/module/deliverable/config/dtable.php @@ -1,4 +1,5 @@ deliverable->dtable = new stdclass(); $config->deliverable->dtable->fieldList['id']['title'] = $lang->idAB; diff --git a/module/deliverable/css/create.ui.css b/module/deliverable/css/create.ui.css new file mode 100644 index 0000000000..1a00c1bdae --- /dev/null +++ b/module/deliverable/css/create.ui.css @@ -0,0 +1,7 @@ +.template-group { + width: 48%; +} + +.template-or { + width: 4%; +} From abd66617345f1cfaad611984cd4d12dbb8e2ebf2 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 15 Apr 2025 08:03:45 +0000 Subject: [PATCH 008/136] * [tsak#141578,doing,0.5h] add page and lang. --- module/deliverable/lang/zh-cn.php | 5 +- module/deliverable/ui/create.html.php | 78 +++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/module/deliverable/lang/zh-cn.php b/module/deliverable/lang/zh-cn.php index 1c951cf57f..6140d78b8a 100644 --- a/module/deliverable/lang/zh-cn.php +++ b/module/deliverable/lang/zh-cn.php @@ -6,8 +6,11 @@ $lang->deliverable->method = '动作'; $lang->deliverable->model = '适用范围'; $lang->deliverable->createdBy = '创建人'; $lang->deliverable->createdDate = '创建时间'; +$lang->deliverable->template = '引用模板'; +$lang->deliverable->files = '上传模板'; +$lang->deliverable->or = '或'; -$lang->deliverable->create = '创建'; +$lang->deliverable->create = '添加交付物'; $lang->deliverable->edit = '编辑'; $lang->deliverable->delete = '删除'; $lang->deliverable->view = '详情'; diff --git a/module/deliverable/ui/create.html.php b/module/deliverable/ui/create.html.php index bbb073c399..4b52fa39fd 100644 --- a/module/deliverable/ui/create.html.php +++ b/module/deliverable/ui/create.html.php @@ -3,5 +3,83 @@ namespace zin; formPanel ( + set::title($lang->deliverable->create), + set::grid(true), + set::layout('grid'), + formGroup + ( + set::width('1/2'), + set::label($lang->deliverable->name), + set::name('name') + ), + formGroup(set::width('1/2')), + formGroup + ( + set::width('1/3'), + set::label($lang->deliverable->module), + picker + ( + set::name('module'), + set::items(array()) + ) + ), + formGroup + ( + set::width('1/6'), + set::label($lang->deliverable->method), + picker + ( + set::name('method'), + set::items(array()) + ) + ), + formGroup(set::width('1/2')), + formGroup + ( + set::width('1/2'), + set::label($lang->deliverable->model), + picker + ( + set::name('model'), + set::multiple(true), + set::items(array()) + ) + ), + formGroup + ( + set::width('full'), + set::label($lang->deliverable->desc), + editor + ( + set::name('desc') + ) + ), + formGroup + ( + setClass('template-group'), + set::label($lang->deliverable->template), + picker + ( + set::name('template'), + set::items(array()) + ), + ), + formGroup + ( + setClass('template-or'), + set::label(''), + inputGroup + ( + $lang->deliverable->or + ) + ), + formGroup + ( + setClass('template-group'), + set::label($lang->deliverable->files), + fileinput( + set::name('files'), + ) + ), ); From 89c736e5de9754daf9509a90433dc8d66ec82139 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 15 Apr 2025 08:18:50 +0000 Subject: [PATCH 009/136] * Trim comma. --- module/deliverable/ui/create.html.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/module/deliverable/ui/create.html.php b/module/deliverable/ui/create.html.php index 4b52fa39fd..8aa7f678c4 100644 --- a/module/deliverable/ui/create.html.php +++ b/module/deliverable/ui/create.html.php @@ -62,8 +62,7 @@ formPanel ( set::name('template'), set::items(array()) - ), - + ) ), formGroup ( @@ -78,8 +77,9 @@ formPanel ( setClass('template-group'), set::label($lang->deliverable->files), - fileinput( - set::name('files'), + fileinput + ( + set::name('files') ) - ), + ) ); From cc092787f59a5009fcf9052ac0745bc484a8f8ea Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 00:59:28 +0000 Subject: [PATCH 010/136] * [task#141578,doing,0.5h] add modellist. --- module/deliverable/control.php | 3 ++- module/deliverable/lang/zh-cn.php | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/module/deliverable/control.php b/module/deliverable/control.php index c769828010..f9442013d8 100644 --- a/module/deliverable/control.php +++ b/module/deliverable/control.php @@ -24,7 +24,8 @@ class deliverable extends control */ public function create() { - $this->view->title = $this->lang->deliverable->create; + $this->view->title = $this->lang->deliverable->create; + $this->view->modelList = $this->deliverable->buildModelList(); $this->display(); } } diff --git a/module/deliverable/lang/zh-cn.php b/module/deliverable/lang/zh-cn.php index 6140d78b8a..36f120ce19 100644 --- a/module/deliverable/lang/zh-cn.php +++ b/module/deliverable/lang/zh-cn.php @@ -14,3 +14,8 @@ $lang->deliverable->create = '添加交付物'; $lang->deliverable->edit = '编辑'; $lang->deliverable->delete = '删除'; $lang->deliverable->view = '详情'; + +$lang->deliverable->modelList['product_waterfall'] = '产品型瀑布项目'; +$lang->deliverable->modelList['project_waterfall'] = '项目型瀑布项目'; +$lang->deliverable->modelList['product_scrum'] = '产品型敏捷项目'; +$lang->deliverable->modelList['project_scrum'] = '项目型敏捷项目'; \ No newline at end of file From e00f5d3183e58b57220f673507065df885f2572a Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 00:59:43 +0000 Subject: [PATCH 011/136] * [task#141578,doing,1h] build model list. --- module/deliverable/model.php | 42 +++++++++++++++++++++++++++ module/deliverable/ui/create.html.php | 25 ++-------------- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/module/deliverable/model.php b/module/deliverable/model.php index c88079e3f6..4f4bec0052 100644 --- a/module/deliverable/model.php +++ b/module/deliverable/model.php @@ -1,9 +1,51 @@ dao->select('*')->from(TABLE_DELIVERABLE)->fetchAll(); return $deliverables; } + + /** + * 构造交付物适用范围列表。 + * Build deliverable model list. + * + * @access public + * @return array + */ + public function buildModelList() + { + $this->app->loadLang('stage'); + $this->app->loadLang('execution'); + $modelList = $this->lang->deliverable->modelList; + $stageList = $this->lang->stage->typeList; + $lifeTimeList = $this->lang->execution->lifeTimeList; + foreach($modelList as $key => $value) + { + if(strpos($key, 'waterfall') !== false) + { + foreach($stageList as $stageKey => $stageValue) + { + $modelList[$key . '_' . $stageKey] = $value . '/' . $stageValue . $this->lang->execution->typeList['stage']; + } + } + elseif(strpos($key, 'scrum') !== false) + { + foreach($lifeTimeList as $lifeTimeKey => $lifeTimeValue) + { + $modelList[$key . '_' . $lifeTimeKey] = $value . '/' . $lifeTimeValue . $this->lang->execution->typeList['sprint']; + } + } + } + + return $modelList; + } } diff --git a/module/deliverable/ui/create.html.php b/module/deliverable/ui/create.html.php index 8aa7f678c4..a4838c92aa 100644 --- a/module/deliverable/ui/create.html.php +++ b/module/deliverable/ui/create.html.php @@ -42,7 +42,7 @@ formPanel ( set::name('model'), set::multiple(true), - set::items(array()) + set::items($modelList) ) ), formGroup @@ -56,28 +56,9 @@ formPanel ), formGroup ( - setClass('template-group'), - set::label($lang->deliverable->template), - picker - ( - set::name('template'), - set::items(array()) - ) - ), - formGroup - ( - setClass('template-or'), - set::label(''), - inputGroup - ( - $lang->deliverable->or - ) - ), - formGroup - ( - setClass('template-group'), + set::width('full'), set::label($lang->deliverable->files), - fileinput + fileselector ( set::name('files') ) From 0251acdde6babcad14cd420621eed9007b9add00 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 02:02:40 +0000 Subject: [PATCH 012/136] * [task#141578,doing,0.5h] add deliverable js. --- module/deliverable/js/create.ui.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 module/deliverable/js/create.ui.js diff --git a/module/deliverable/js/create.ui.js b/module/deliverable/js/create.ui.js new file mode 100644 index 0000000000..e024a2f2d0 --- /dev/null +++ b/module/deliverable/js/create.ui.js @@ -0,0 +1,22 @@ +window.changeModule = function(e) +{ + const module = e.target.value; + const url = $.createLink('deliverable', 'ajaxGetModelList', `type=${module}`); + + if(module == 'execution') + { + $('[name="method"]').zui('picker').$.setValue('close'); + $('[name="method"]').zui('picker').render({disabled: true}); + } + else + { + $('[name="method"]').zui('picker').$.setValue(''); + $('[name="method"]').zui('picker').render({disabled: false}); + } + + $.getJSON(url, function(data) + { + $('[name="model"]').zui('picker').render({items: data}); + $('[name="model"]').zui('picker').$.setValue(''); + }); +} From f29708da3f098095d3c2c0df7198bde20bc086b8 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 02:07:04 +0000 Subject: [PATCH 013/136] * [task#141578,doing,0.5h] add action config for deliverable. --- config/zentaopms.php | 1 + module/action/config.php | 1 + module/action/lang/de.php | 2 ++ module/action/lang/en.php | 2 ++ module/action/lang/fr.php | 2 ++ module/action/lang/zh-cn.php | 2 ++ 6 files changed, 10 insertions(+) diff --git a/config/zentaopms.php b/config/zentaopms.php index ec28663e04..97041891c9 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -673,6 +673,7 @@ $config->objectTables['demand'] = TABLE_DEMAND; $config->objectTables['demandpool'] = TABLE_DEMANDPOOL; $config->objectTables['demandspec'] = TABLE_DEMANDSPEC; $config->objectTables['demandreview'] = TABLE_DEMANDREVIEW; +$config->objectTables['deliverable'] = TABLE_DELIVERABLE; $config->objectTables['todo'] = TABLE_TODO; $config->objectTables['custom'] = TABLE_LANG; $config->objectTables['branch'] = TABLE_BRANCH; diff --git a/module/action/config.php b/module/action/config.php index 9899981166..1c26be3a42 100755 --- a/module/action/config.php +++ b/module/action/config.php @@ -71,6 +71,7 @@ $config->action->objectNameFields['prompt'] = 'name'; $config->action->objectNameFields['miniprogram'] = 'name'; $config->action->objectNameFields['holiday'] = 'name'; $config->action->objectNameFields['system'] = 'name'; +$config->action->objectNameFields['deliverable'] = 'name'; $config->action->commonImgSize = 870; diff --git a/module/action/lang/de.php b/module/action/lang/de.php index cadc771a32..5939c7544e 100644 --- a/module/action/lang/de.php +++ b/module/action/lang/de.php @@ -190,6 +190,7 @@ $lang->action->objectTypes['board'] = 'Board'; $lang->action->objectTypes['boardspace'] = 'Board Space'; $lang->action->objectTypes['productline'] = 'Product Line'; $lang->action->objectTypes['system'] = $lang->product->system; +$lang->action->objectTypes['deliverable'] = 'Deliverable'; /* Used to describe operation history. */ $lang->action->desc = new stdclass(); @@ -943,6 +944,7 @@ $lang->action->label->instance = 'Application|instance|view|id=%s'; $lang->action->label->prompt = 'Prompt|ai|promptview|id=%s'; $lang->action->label->miniprogram = 'Mini Program|aiapp|browseminiprogram|id=%s'; $lang->action->label->holiday = 'Holiday|holiday|browse|'; +$lang->action->label->deliverable = 'Deliverable|deliverable|view|id=%s'; /* Object type. */ $lang->action->search = new stdclass(); diff --git a/module/action/lang/en.php b/module/action/lang/en.php index cd5c994806..511d0a5bab 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -190,6 +190,7 @@ $lang->action->objectTypes['board'] = 'Board'; $lang->action->objectTypes['boardspace'] = 'Board Space'; $lang->action->objectTypes['productline'] = 'Product Line'; $lang->action->objectTypes['system'] = $lang->product->system; +$lang->action->objectTypes['deliverable'] = 'Deliverable'; /* Used to describe operation history. */ $lang->action->desc = new stdclass(); @@ -943,6 +944,7 @@ $lang->action->label->instance = 'Application|instance|view|id=%s'; $lang->action->label->prompt = 'Prompt|ai|promptview|id=%s'; $lang->action->label->miniprogram = 'Mini Program|aiapp|browseminiprogram|id=%s'; $lang->action->label->holiday = 'Holiday|holiday|browse|'; +$lang->action->label->deliverable = 'Deliverable|deliverable|view|id=%s'; /* Object type. */ $lang->action->search = new stdclass(); diff --git a/module/action/lang/fr.php b/module/action/lang/fr.php index 9e71e04c6f..cad7d377f7 100644 --- a/module/action/lang/fr.php +++ b/module/action/lang/fr.php @@ -190,6 +190,7 @@ $lang->action->objectTypes['board'] = 'Board'; $lang->action->objectTypes['boardspace'] = 'Board Space'; $lang->action->objectTypes['productline'] = 'Product Line'; $lang->action->objectTypes['system'] = $lang->product->system; +$lang->action->objectTypes['deliverable'] = 'Deliverable'; /* Used to describe operation history. */ $lang->action->desc = new stdclass(); @@ -943,6 +944,7 @@ $lang->action->label->instance = 'Application|instance|view|id=%s'; $lang->action->label->prompt = 'Prompt|ai|promptview|id=%s'; $lang->action->label->miniprogram = 'Mini Program|aiapp|browseminiprogram|id=%s'; $lang->action->label->holiday = 'Holiday|holiday|browse|'; +$lang->action->label->deliverable = 'Deliverable|deliverable|view|id=%s'; /* Object type. */ $lang->action->search = new stdclass(); diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index 13bb508f14..b7b2c21f90 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -190,6 +190,7 @@ $lang->action->objectTypes['board'] = '白板'; $lang->action->objectTypes['boardspace'] = '白板空间'; $lang->action->objectTypes['productline'] = '产品线'; $lang->action->objectTypes['system'] = $lang->product->system; +$lang->action->objectTypes['deliverable'] = '交付物'; /* 用来描述操作历史记录。*/ $lang->action->desc = new stdclass(); @@ -943,6 +944,7 @@ $lang->action->label->instance = '服务|instance|view|id=%s'; $lang->action->label->prompt = '提词|ai|promptview|id=%s'; $lang->action->label->miniprogram = '小程序|aiapp|browseminiprogram|id=%s'; $lang->action->label->holiday = '节假日|holiday|browse|'; +$lang->action->label->deliverable = '交付物|deliverable|view|id=%s'; /* Object type. */ $lang->action->search = new stdclass(); From be912d5aa50129d39b64ac4e64299b4db60faf3d Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 02:08:20 +0000 Subject: [PATCH 014/136] * [task#141578,doing,0.5h] add form config. --- module/deliverable/config/form.php | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 module/deliverable/config/form.php diff --git a/module/deliverable/config/form.php b/module/deliverable/config/form.php new file mode 100644 index 0000000000..6b9813982c --- /dev/null +++ b/module/deliverable/config/form.php @@ -0,0 +1,8 @@ +deliverable->form = new stdclass(); +$config->deliverable->form->create = array(); +$config->deliverable->form->create['name'] = array('type' => 'string', 'required' => true); +$config->deliverable->form->create['module'] = array('type' => 'string', 'required' => true); +$config->deliverable->form->create['method'] = array('type' => 'string', 'required' => true); +$config->deliverable->form->create['model'] = array('type' => 'string', 'required' => true); +$config->deliverable->form->create['desc'] = array('type' => 'text', 'required' => false, 'control' => 'editor'); \ No newline at end of file From d350da361ca4515fabe6fbe555ef0b8128cc0c76 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 02:08:57 +0000 Subject: [PATCH 015/136] * Add required fields for deliverable. --- module/deliverable/config.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/module/deliverable/config.php b/module/deliverable/config.php index 60b7323d66..2428d9aa63 100644 --- a/module/deliverable/config.php +++ b/module/deliverable/config.php @@ -1,2 +1,6 @@ deliverable = new stdclass(); +$config->deliverable->create = new stdclass(); +$config->deliverable->edit = new stdclass(); +$config->deliverable->create->requiredFields = 'name,module,method,model'; +$config->deliverable->edit->requiredFields = 'name,module,method,model'; From 81ae731992917161f399bfb272276cf5f08ee5eb Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 02:09:13 +0000 Subject: [PATCH 016/136] * [task#141578,doing,1h] add create & ajax get model list. --- module/deliverable/control.php | 40 ++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/module/deliverable/control.php b/module/deliverable/control.php index f9442013d8..c11c729e55 100644 --- a/module/deliverable/control.php +++ b/module/deliverable/control.php @@ -24,8 +24,44 @@ class deliverable extends control */ public function create() { + if($_POST) + { + $files = $this->loadModel('file')->getUpload(); + if(empty($files[0]['title'])) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->error->notempty, $this->lang->deliverable->files))); + + $deliverable = form::data($this->config->deliverable->form->create) + ->add('createdBy', $this->app->user->account) + ->add('createdDate', helper::today()) + ->get(); + + $this->deliverable->create($deliverable); + + if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + return $this->sendSuccess(array('load' => inlink('browse'))); + } + $this->view->title = $this->lang->deliverable->create; - $this->view->modelList = $this->deliverable->buildModelList(); + $this->view->modelList = $this->deliverable->buildModelList('all'); $this->display(); } -} + + /** + * Ajax获取交付物适用范围列表。 + * Ajax get deliverable model list. + * + * @param string $type execution|project + * @access public + * @return void + */ + public function ajaxGetModelList($type = 'execution') + { + $items = array(); + $modelList = $this->deliverable->buildModelList($type); + foreach($modelList as $key => $value) + { + $items[] = array('value' => $key, 'text' => $value); + } + + return print(json_encode($items)); + } +} \ No newline at end of file From 39aeffa60d644c379de99735220b179a0af95196 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 02:09:45 +0000 Subject: [PATCH 017/136] * [task#141578,doing,0.5h] add build model list func. --- module/deliverable/model.php | 58 ++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/module/deliverable/model.php b/module/deliverable/model.php index 4f4bec0052..8e63957c7c 100644 --- a/module/deliverable/model.php +++ b/module/deliverable/model.php @@ -14,34 +14,66 @@ class deliverableModel extends model return $deliverables; } + /** + * 创建交付物。 + * Create deliverable. + * + * @param object $deliverable + * @access public + * @return bool + */ + public function create($deliverable) + { + $this->dao->insert(TABLE_DELIVERABLE)->data($deliverable)->exec(); + $deliverableID = $this->dao->lastInsertID(); + + $files = $this->loadModel('file')->saveUpload('deliverable', $deliverableID); + if(!empty($files)) + { + $fileIdList = implode(',', array_keys($files)); + $this->dao->update(TABLE_DELIVERABLE)->set('files')->eq($fileIdList)->where('id')->eq($deliverableID)->exec(); + } + + $this->loadModel('action')->create('deliverable', $deliverableID, 'opened'); + + return !dao::isError(); + } + /** * 构造交付物适用范围列表。 * Build deliverable model list. * + * @param string $type all|project|execution * @access public * @return array */ - public function buildModelList() + public function buildModelList($type = 'all') { $this->app->loadLang('stage'); $this->app->loadLang('execution'); - $modelList = $this->lang->deliverable->modelList; - $stageList = $this->lang->stage->typeList; - $lifeTimeList = $this->lang->execution->lifeTimeList; - foreach($modelList as $key => $value) + + $modelList = array(); + + if($type == 'all' || $type == 'project') $modelList = $this->lang->deliverable->modelList; + if($type == 'all' || $type == 'execution') { - if(strpos($key, 'waterfall') !== false) + $stageList = $this->lang->stage->typeList; + $lifeTimeList = $this->lang->execution->lifeTimeList; + foreach($this->lang->deliverable->modelList as $key => $value) { - foreach($stageList as $stageKey => $stageValue) + if(strpos($key, 'waterfall') !== false) { - $modelList[$key . '_' . $stageKey] = $value . '/' . $stageValue . $this->lang->execution->typeList['stage']; + foreach($stageList as $stageKey => $stageValue) + { + $modelList[$key . '_' . $stageKey] = $value . '/' . $stageValue . $this->lang->execution->typeList['stage']; + } } - } - elseif(strpos($key, 'scrum') !== false) - { - foreach($lifeTimeList as $lifeTimeKey => $lifeTimeValue) + elseif(strpos($key, 'scrum') !== false) { - $modelList[$key . '_' . $lifeTimeKey] = $value . '/' . $lifeTimeValue . $this->lang->execution->typeList['sprint']; + foreach($lifeTimeList as $lifeTimeKey => $lifeTimeValue) + { + $modelList[$key . '_' . $lifeTimeKey] = $value . '/' . $lifeTimeValue . $this->lang->execution->typeList['sprint']; + } } } } From b83c84d8f95cf42865784d575d519e444bf067de Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 02:10:10 +0000 Subject: [PATCH 018/136] * [task#141578,doing,1h] add page. --- module/deliverable/lang/zh-cn.php | 14 ++++++++++---- module/deliverable/ui/create.html.php | 7 ++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/module/deliverable/lang/zh-cn.php b/module/deliverable/lang/zh-cn.php index 36f120ce19..a38165ee1f 100644 --- a/module/deliverable/lang/zh-cn.php +++ b/module/deliverable/lang/zh-cn.php @@ -10,10 +10,16 @@ $lang->deliverable->template = '引用模板'; $lang->deliverable->files = '上传模板'; $lang->deliverable->or = '或'; -$lang->deliverable->create = '添加交付物'; -$lang->deliverable->edit = '编辑'; -$lang->deliverable->delete = '删除'; -$lang->deliverable->view = '详情'; +$lang->deliverable->create = '添加交付物'; +$lang->deliverable->edit = '编辑交付物'; +$lang->deliverable->delete = '删除交付物'; +$lang->deliverable->view = '交付物详情'; + +$lang->deliverable->moduleList['project'] = '项目'; +$lang->deliverable->moduleList['execution'] = '执行'; + +$lang->deliverable->methodList['create'] = '创建'; +$lang->deliverable->methodList['close'] = '关闭'; $lang->deliverable->modelList['product_waterfall'] = '产品型瀑布项目'; $lang->deliverable->modelList['project_waterfall'] = '项目型瀑布项目'; diff --git a/module/deliverable/ui/create.html.php b/module/deliverable/ui/create.html.php index a4838c92aa..8e51cc1869 100644 --- a/module/deliverable/ui/create.html.php +++ b/module/deliverable/ui/create.html.php @@ -19,8 +19,9 @@ formPanel set::label($lang->deliverable->module), picker ( + on::change('changeModule'), set::name('module'), - set::items(array()) + set::items($lang->deliverable->moduleList) ) ), formGroup @@ -30,7 +31,7 @@ formPanel picker ( set::name('method'), - set::items(array()) + set::items($lang->deliverable->methodList) ) ), formGroup(set::width('1/2')), @@ -41,7 +42,6 @@ formPanel picker ( set::name('model'), - set::multiple(true), set::items($modelList) ) ), @@ -58,6 +58,7 @@ formPanel ( set::width('full'), set::label($lang->deliverable->files), + set::required(true), fileselector ( set::name('files') From 9a540f70e98096a23422eb5515a0bae8253d7e48 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 02:11:07 +0000 Subject: [PATCH 019/136] * [misc] modify field type. --- module/deliverable/config/form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/deliverable/config/form.php b/module/deliverable/config/form.php index 6b9813982c..c0e478857a 100644 --- a/module/deliverable/config/form.php +++ b/module/deliverable/config/form.php @@ -5,4 +5,4 @@ $config->deliverable->form->create['name'] = array('type' => 'string', 'requir $config->deliverable->form->create['module'] = array('type' => 'string', 'required' => true); $config->deliverable->form->create['method'] = array('type' => 'string', 'required' => true); $config->deliverable->form->create['model'] = array('type' => 'string', 'required' => true); -$config->deliverable->form->create['desc'] = array('type' => 'text', 'required' => false, 'control' => 'editor'); \ No newline at end of file +$config->deliverable->form->create['desc'] = array('type' => 'string', 'required' => false, 'control' => 'editor'); From 902df320d733c9b9c48ace802171ae78256110f0 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 02:14:14 +0000 Subject: [PATCH 020/136] * [misc] check dao error. --- module/deliverable/model.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/deliverable/model.php b/module/deliverable/model.php index 8e63957c7c..f2600e03da 100644 --- a/module/deliverable/model.php +++ b/module/deliverable/model.php @@ -25,6 +25,8 @@ class deliverableModel extends model public function create($deliverable) { $this->dao->insert(TABLE_DELIVERABLE)->data($deliverable)->exec(); + if(dao::isError()) return false; + $deliverableID = $this->dao->lastInsertID(); $files = $this->loadModel('file')->saveUpload('deliverable', $deliverableID); From 41f2987c4619fdbe0caa1b842a61c959c6acb3b7 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 02:23:27 +0000 Subject: [PATCH 021/136] * [task#141578,done,0.2h] finish task. --- module/admin/lang/menu.php | 2 +- module/deliverable/control.php | 2 +- module/deliverable/ui/create.html.php | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/module/admin/lang/menu.php b/module/admin/lang/menu.php index f28086586d..52ff82963b 100644 --- a/module/admin/lang/menu.php +++ b/module/admin/lang/menu.php @@ -88,7 +88,7 @@ $lang->admin->menuList->model['menuOrder']['25'] = 'waterfallplus'; $lang->admin->menuList->model['tabMenu']['common']['project'] = array('link' => "{$lang->project->common}|custom|required|module=project", 'alias' => 'set,project', 'exclude' => 'custom-required', 'links' => array('custom|set|module=project&field=unitList')); if(helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['common']['stage'] = array('link' => "{$lang->stage->type}|stage|settype|", 'subModule' => 'stage'); -$lang->admin->menuList->model['tabMenu']['common']['deliverable'] = array('link' => "{$lang->deliverable->common}|deliverable|browse|"); +$lang->admin->menuList->model['tabMenu']['common']['deliverable'] = array('link' => "{$lang->deliverable->common}|deliverable|browse|", 'subModule' => 'deliverable'); $lang->admin->menuList->model['tabMenu']['common']['build'] = array('link' => "{$lang->build->common}|custom|required|module=build", 'alias' => 'set', 'exclude' => 'custom'); $lang->admin->menuList->model['tabMenu']['common']['flow'] = array('link' => "{$lang->custom->flow}|custom|flow|", 'divider' => true); diff --git a/module/deliverable/control.php b/module/deliverable/control.php index c11c729e55..b6719783d5 100644 --- a/module/deliverable/control.php +++ b/module/deliverable/control.php @@ -41,7 +41,7 @@ class deliverable extends control } $this->view->title = $this->lang->deliverable->create; - $this->view->modelList = $this->deliverable->buildModelList('all'); + $this->view->modelList = $this->deliverable->buildModelList('project'); $this->display(); } diff --git a/module/deliverable/ui/create.html.php b/module/deliverable/ui/create.html.php index 8e51cc1869..10a25c1454 100644 --- a/module/deliverable/ui/create.html.php +++ b/module/deliverable/ui/create.html.php @@ -21,6 +21,7 @@ formPanel ( on::change('changeModule'), set::name('module'), + set::required(true), set::items($lang->deliverable->moduleList) ) ), @@ -31,6 +32,7 @@ formPanel picker ( set::name('method'), + set::required(true), set::items($lang->deliverable->methodList) ) ), From 0cfee68b4aaa4e2d5f902a915c5677f2113d46aa Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 06:58:19 +0000 Subject: [PATCH 022/136] * [task#141579,doing,0.5h] add rowspan js. --- module/deliverable/js/browse.ui.js | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 module/deliverable/js/browse.ui.js diff --git a/module/deliverable/js/browse.ui.js b/module/deliverable/js/browse.ui.js new file mode 100644 index 0000000000..db705efa35 --- /dev/null +++ b/module/deliverable/js/browse.ui.js @@ -0,0 +1,7 @@ +window.getCellSpan = function(cell) +{ + if(['id', 'name', 'module', 'method', 'createdBy', 'createdDate', 'actions'].includes(cell.col.name) && cell.row.data.rowspan) + { + return {rowSpan: cell.row.data.rowspan}; + } +} From 598dd9c641f35bd6fbcd9d05fdd155dc8a1f06a0 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 06:59:04 +0000 Subject: [PATCH 023/136] * [task#141579,doing,1h] add action list. --- module/deliverable/config.php | 13 +++++++++++++ module/deliverable/config/dtable.php | 13 ++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/module/deliverable/config.php b/module/deliverable/config.php index 2428d9aa63..54c7257949 100644 --- a/module/deliverable/config.php +++ b/module/deliverable/config.php @@ -1,6 +1,19 @@ deliverable = new stdclass(); $config->deliverable->create = new stdclass(); $config->deliverable->edit = new stdclass(); $config->deliverable->create->requiredFields = 'name,module,method,model'; $config->deliverable->edit->requiredFields = 'name,module,method,model'; + +$config->deliverable->actionList = array(); +$config->deliverable->actionList['edit']['icon'] = 'edit'; +$config->deliverable->actionList['edit']['text'] = $lang->deliverable->edit; +$config->deliverable->actionList['edit']['hint'] = $lang->deliverable->edit; +$config->deliverable->actionList['edit']['url'] = array('module' => 'deliverable', 'method' => 'edit', 'params' => 'id={id}'); + +$config->deliverable->actionList['delete']['icon'] = 'trash'; +$config->deliverable->actionList['delete']['text'] = $lang->deliverable->delete; +$config->deliverable->actionList['delete']['hint'] = $lang->deliverable->delete; +$config->deliverable->actionList['delete']['url'] = array('module' => 'deliverable', 'method' => 'delete', 'params' => 'id={id}'); +$config->deliverable->actionList['delete']['data-confirm'] = $lang->deliverable->confirmDelete; \ No newline at end of file diff --git a/module/deliverable/config/dtable.php b/module/deliverable/config/dtable.php index 8ecddf487e..3cb51c25cc 100644 --- a/module/deliverable/config/dtable.php +++ b/module/deliverable/config/dtable.php @@ -5,7 +5,7 @@ $config->deliverable->dtable = new stdclass(); $config->deliverable->dtable->fieldList['id']['title'] = $lang->idAB; $config->deliverable->dtable->fieldList['id']['name'] = 'id'; $config->deliverable->dtable->fieldList['id']['type'] = 'checkID'; -$config->deliverable->dtable->fieldList['id']['sortType'] = 'desc'; +$config->deliverable->dtable->fieldList['id']['sortType'] = true; $config->deliverable->dtable->fieldList['id']['checkbox'] = true; $config->deliverable->dtable->fieldList['id']['width'] = '80'; $config->deliverable->dtable->fieldList['id']['required'] = true; @@ -13,16 +13,20 @@ $config->deliverable->dtable->fieldList['id']['required'] = true; $config->deliverable->dtable->fieldList['name']['title'] = $lang->deliverable->name; $config->deliverable->dtable->fieldList['name']['name'] = 'name'; $config->deliverable->dtable->fieldList['name']['type'] = 'title'; +$config->deliverable->dtable->fieldList['name']['fixed'] = 'left'; +$config->deliverable->dtable->fieldList['name']['link'] = helper::createLink('deliverable', 'view', 'id={id}'); $config->deliverable->dtable->fieldList['name']['sortType'] = true; $config->deliverable->dtable->fieldList['module']['title'] = $lang->deliverable->module; $config->deliverable->dtable->fieldList['module']['name'] = 'module'; $config->deliverable->dtable->fieldList['module']['type'] = 'category'; +$config->deliverable->dtable->fieldList['module']['map'] = $lang->deliverable->moduleList; $config->deliverable->dtable->fieldList['module']['sortType'] = true; $config->deliverable->dtable->fieldList['method']['title'] = $lang->deliverable->method; $config->deliverable->dtable->fieldList['method']['name'] = 'method'; $config->deliverable->dtable->fieldList['method']['type'] = 'category'; +$config->deliverable->dtable->fieldList['method']['map'] = $lang->deliverable->methodList; $config->deliverable->dtable->fieldList['method']['sortType'] = true; $config->deliverable->dtable->fieldList['model']['title'] = $lang->deliverable->model; @@ -39,3 +43,10 @@ $config->deliverable->dtable->fieldList['createdDate']['title'] = $lang->deli $config->deliverable->dtable->fieldList['createdDate']['name'] = 'createdDate'; $config->deliverable->dtable->fieldList['createdDate']['type'] = 'date'; $config->deliverable->dtable->fieldList['createdDate']['sortType'] = true; + +$config->deliverable->dtable->fieldList['actions']['title'] = $lang->actions; +$config->deliverable->dtable->fieldList['actions']['type'] = 'actions'; +$config->deliverable->dtable->fieldList['actions']['fixed'] = 'right'; +$config->deliverable->dtable->fieldList['actions']['list'] = $config->deliverable->actionList; +$config->deliverable->dtable->fieldList['actions']['menu'] = array('edit', 'delete'); +$config->deliverable->dtable->fieldList['actions']['sortType'] = false; \ No newline at end of file From 2735122f10cc41f576f0e733cbf2e547fc23e26c Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 06:59:38 +0000 Subject: [PATCH 024/136] * [task#141579,doing,0.5h] add config/lang. --- module/deliverable/config/form.php | 4 ++-- module/deliverable/lang/zh-cn.php | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/module/deliverable/config/form.php b/module/deliverable/config/form.php index c0e478857a..17aaf7f49a 100644 --- a/module/deliverable/config/form.php +++ b/module/deliverable/config/form.php @@ -4,5 +4,5 @@ $config->deliverable->form->create = array(); $config->deliverable->form->create['name'] = array('type' => 'string', 'required' => true); $config->deliverable->form->create['module'] = array('type' => 'string', 'required' => true); $config->deliverable->form->create['method'] = array('type' => 'string', 'required' => true); -$config->deliverable->form->create['model'] = array('type' => 'string', 'required' => true); -$config->deliverable->form->create['desc'] = array('type' => 'string', 'required' => false, 'control' => 'editor'); +$config->deliverable->form->create['model'] = array('type' => 'array', 'required' => true, 'filter' => 'join'); +$config->deliverable->form->create['desc'] = array('type' => 'string', 'required' => false, 'control' => 'editor'); \ No newline at end of file diff --git a/module/deliverable/lang/zh-cn.php b/module/deliverable/lang/zh-cn.php index a38165ee1f..aeae035177 100644 --- a/module/deliverable/lang/zh-cn.php +++ b/module/deliverable/lang/zh-cn.php @@ -24,4 +24,7 @@ $lang->deliverable->methodList['close'] = '关闭'; $lang->deliverable->modelList['product_waterfall'] = '产品型瀑布项目'; $lang->deliverable->modelList['project_waterfall'] = '项目型瀑布项目'; $lang->deliverable->modelList['product_scrum'] = '产品型敏捷项目'; -$lang->deliverable->modelList['project_scrum'] = '项目型敏捷项目'; \ No newline at end of file +$lang->deliverable->modelList['project_scrum'] = '项目型敏捷项目'; + +$lang->deliverable->confirmDelete = '确定删除该交付物吗?'; +$lang->deliverable->summary = '本页共有%s个交付物'; \ No newline at end of file From 0f60570d9f76de31d74be66c75191b0aaa5bfa19 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 07:00:07 +0000 Subject: [PATCH 025/136] * [task#141579,doing,0.2h] add browse method. --- module/deliverable/control.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/module/deliverable/control.php b/module/deliverable/control.php index b6719783d5..e479341d6f 100644 --- a/module/deliverable/control.php +++ b/module/deliverable/control.php @@ -8,10 +8,20 @@ class deliverable extends control * @access public * @return void */ - public function browse() + public function browse($browseType = '', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 0, $pageID = 1) { - $this->view->deliverables = array(); + $this->app->loadClass('pager', true); + $pager = new pager($recTotal, $recPerPage, $pageID); + + $queryID = $browseType == 'bysearch' ? (int)$param : 0; + $this->view->title = $this->lang->deliverable->common; + $this->view->deliverables = $this->deliverable->getList($browseType, $queryID, $orderBy, $pager); + $this->view->orderBy = $orderBy; + $this->view->pager = $pager; + $this->view->browseType = $browseType; + $this->view->param = $param; + $this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted|noletter'); $this->display(); } From 89f4ac990fab7fa590d6498b8ca71f1ac3485da7 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 07:00:32 +0000 Subject: [PATCH 026/136] * [task#141579,doing,0.5h] add get list. --- module/deliverable/model.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/module/deliverable/model.php b/module/deliverable/model.php index f2600e03da..0062d4e089 100644 --- a/module/deliverable/model.php +++ b/module/deliverable/model.php @@ -5,13 +5,20 @@ class deliverableModel extends model * 获取交付物列表。 * Get deliverable list. * + * @param string $browseType + * @param int $queryID + * @param string $orderBy + * @param object $pager * @access public * @return array */ - public function getList() + public function getList($browseType = '', $queryID = 0, $orderBy = 'id_desc', $pager = null) { - $deliverables = $this->dao->select('*')->from(TABLE_DELIVERABLE)->fetchAll(); - return $deliverables; + return $this->dao->select('*')->from(TABLE_DELIVERABLE) + ->where('deleted')->eq(0) + ->orderBy($orderBy) + ->page($pager) + ->fetchAll('id', false); } /** From 2f3ceccb5c0777a45895c58b26be0b399d005029 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 07:00:43 +0000 Subject: [PATCH 027/136] * [task#141579,doing,1h] add browse html. --- module/deliverable/ui/browse.html.php | 38 ++++++++++++++++++++++++++- module/deliverable/ui/create.html.php | 1 + 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/module/deliverable/ui/browse.html.php b/module/deliverable/ui/browse.html.php index b0b51d4fa9..a44ff59d4b 100644 --- a/module/deliverable/ui/browse.html.php +++ b/module/deliverable/ui/browse.html.php @@ -16,8 +16,44 @@ toolbar ); $cols = $config->deliverable->dtable->fieldList; +$modelList = $this->deliverable->buildModelList('all'); + +$summary = sprintf($lang->deliverable->summary, count($deliverables)); +$tableData = initTableData($deliverables, $cols, $this->deliverable); +$data = array(); +foreach($tableData as $key => $row) +{ + if($row->model) + { + $models = explode(',', $row->model); + foreach($models as $model) + { + $row->model = $modelList[$model]; + $row->rowspan = count($models); + $data[] = clone $row; + } + } + else + { + $data[] = $row; + } +} + dtable ( set::cols($cols), - set::data($deliverables) + set::data($data), + set::userMap($users), + set::orderBy($orderBy), + set::plugins(array('cellspan')), + set::checkable(false), + set::sortLink(createLink('deliverable', 'browse', "browseType=$browseType¶m={$param}&orderBy={name}_{sortType}&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}")), + set::getCellSpan(jsRaw('window.getCellSpan')), + set::footer(array($summary, 'flex', 'pager')), + set::footPager(usePager(array + ( + 'recTotal' => $pager->recTotal, + 'recPerPage' => $pager->recPerPage, + 'linkCreator' => helper::createLink('deliverable', 'browse', "browseType=$browseType¶m={$param}&orderBy=$orderBy&recTotal={$pager->recTotal}&recPerPage={recPerPage}&page={page}") + ))) ); diff --git a/module/deliverable/ui/create.html.php b/module/deliverable/ui/create.html.php index 10a25c1454..a888e08f74 100644 --- a/module/deliverable/ui/create.html.php +++ b/module/deliverable/ui/create.html.php @@ -44,6 +44,7 @@ formPanel picker ( set::name('model'), + set::multiple(true), set::items($modelList) ) ), From 18ea19e38d344f1297c9185d318b302c0fd6b53f Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 07:02:45 +0000 Subject: [PATCH 028/136] * [misc] add en lang. --- module/deliverable/lang/de.php | 30 ++++++++++++++++++++++++++++++ module/deliverable/lang/en.php | 30 ++++++++++++++++++++++++++++++ module/deliverable/lang/fr.php | 30 ++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 module/deliverable/lang/de.php create mode 100644 module/deliverable/lang/en.php create mode 100644 module/deliverable/lang/fr.php diff --git a/module/deliverable/lang/de.php b/module/deliverable/lang/de.php new file mode 100644 index 0000000000..f39913b3dc --- /dev/null +++ b/module/deliverable/lang/de.php @@ -0,0 +1,30 @@ +deliverable->name = 'Name'; +$lang->deliverable->desc = 'Description'; +$lang->deliverable->module = 'Applicable Object'; +$lang->deliverable->method = 'Action'; +$lang->deliverable->model = 'Applicable Scope'; +$lang->deliverable->createdBy = 'Created By'; +$lang->deliverable->createdDate = 'Created Date'; +$lang->deliverable->template = 'Reference Template'; +$lang->deliverable->files = 'Upload Template'; +$lang->deliverable->or = 'OR'; + +$lang->deliverable->create = 'Add Deliverable'; +$lang->deliverable->edit = 'Edit Deliverable'; +$lang->deliverable->delete = 'Delete Deliverable'; +$lang->deliverable->view = 'Deliverable Details'; + +$lang->deliverable->moduleList['project'] = 'Project'; +$lang->deliverable->moduleList['execution'] = 'Execution'; + +$lang->deliverable->methodList['create'] = 'Create'; +$lang->deliverable->methodList['close'] = 'Close'; + +$lang->deliverable->modelList['product_waterfall'] = 'Product Waterfall'; +$lang->deliverable->modelList['project_waterfall'] = 'Project Waterfall'; +$lang->deliverable->modelList['product_scrum'] = 'Product Scrum'; +$lang->deliverable->modelList['project_scrum'] = 'Project Scrum'; + +$lang->deliverable->confirmDelete = 'Are you sure to delete this deliverable?'; +$lang->deliverable->summary = 'There are %s deliverables on this page'; \ No newline at end of file diff --git a/module/deliverable/lang/en.php b/module/deliverable/lang/en.php new file mode 100644 index 0000000000..f39913b3dc --- /dev/null +++ b/module/deliverable/lang/en.php @@ -0,0 +1,30 @@ +deliverable->name = 'Name'; +$lang->deliverable->desc = 'Description'; +$lang->deliverable->module = 'Applicable Object'; +$lang->deliverable->method = 'Action'; +$lang->deliverable->model = 'Applicable Scope'; +$lang->deliverable->createdBy = 'Created By'; +$lang->deliverable->createdDate = 'Created Date'; +$lang->deliverable->template = 'Reference Template'; +$lang->deliverable->files = 'Upload Template'; +$lang->deliverable->or = 'OR'; + +$lang->deliverable->create = 'Add Deliverable'; +$lang->deliverable->edit = 'Edit Deliverable'; +$lang->deliverable->delete = 'Delete Deliverable'; +$lang->deliverable->view = 'Deliverable Details'; + +$lang->deliverable->moduleList['project'] = 'Project'; +$lang->deliverable->moduleList['execution'] = 'Execution'; + +$lang->deliverable->methodList['create'] = 'Create'; +$lang->deliverable->methodList['close'] = 'Close'; + +$lang->deliverable->modelList['product_waterfall'] = 'Product Waterfall'; +$lang->deliverable->modelList['project_waterfall'] = 'Project Waterfall'; +$lang->deliverable->modelList['product_scrum'] = 'Product Scrum'; +$lang->deliverable->modelList['project_scrum'] = 'Project Scrum'; + +$lang->deliverable->confirmDelete = 'Are you sure to delete this deliverable?'; +$lang->deliverable->summary = 'There are %s deliverables on this page'; \ No newline at end of file diff --git a/module/deliverable/lang/fr.php b/module/deliverable/lang/fr.php new file mode 100644 index 0000000000..f39913b3dc --- /dev/null +++ b/module/deliverable/lang/fr.php @@ -0,0 +1,30 @@ +deliverable->name = 'Name'; +$lang->deliverable->desc = 'Description'; +$lang->deliverable->module = 'Applicable Object'; +$lang->deliverable->method = 'Action'; +$lang->deliverable->model = 'Applicable Scope'; +$lang->deliverable->createdBy = 'Created By'; +$lang->deliverable->createdDate = 'Created Date'; +$lang->deliverable->template = 'Reference Template'; +$lang->deliverable->files = 'Upload Template'; +$lang->deliverable->or = 'OR'; + +$lang->deliverable->create = 'Add Deliverable'; +$lang->deliverable->edit = 'Edit Deliverable'; +$lang->deliverable->delete = 'Delete Deliverable'; +$lang->deliverable->view = 'Deliverable Details'; + +$lang->deliverable->moduleList['project'] = 'Project'; +$lang->deliverable->moduleList['execution'] = 'Execution'; + +$lang->deliverable->methodList['create'] = 'Create'; +$lang->deliverable->methodList['close'] = 'Close'; + +$lang->deliverable->modelList['product_waterfall'] = 'Product Waterfall'; +$lang->deliverable->modelList['project_waterfall'] = 'Project Waterfall'; +$lang->deliverable->modelList['product_scrum'] = 'Product Scrum'; +$lang->deliverable->modelList['project_scrum'] = 'Project Scrum'; + +$lang->deliverable->confirmDelete = 'Are you sure to delete this deliverable?'; +$lang->deliverable->summary = 'There are %s deliverables on this page'; \ No newline at end of file From fa36a8397b7ea4ab8e608f3da17efa6fed6f0c1d Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 07:18:31 +0000 Subject: [PATCH 029/136] * [misc] add param define. --- module/deliverable/control.php | 10 ++++++++-- module/deliverable/model.php | 8 ++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/module/deliverable/control.php b/module/deliverable/control.php index e479341d6f..3b5b08ad97 100644 --- a/module/deliverable/control.php +++ b/module/deliverable/control.php @@ -5,10 +5,16 @@ class deliverable extends control * 交付物列表。 * Browse deliverables. * + * @param string $browseType + * @param int $param + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID * @access public * @return void */ - public function browse($browseType = '', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 0, $pageID = 1) + public function browse(string $browseType = '', int $param = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 0, int $pageID = 1) { $this->app->loadClass('pager', true); $pager = new pager($recTotal, $recPerPage, $pageID); @@ -63,7 +69,7 @@ class deliverable extends control * @access public * @return void */ - public function ajaxGetModelList($type = 'execution') + public function ajaxGetModelList(string $type = 'execution') { $items = array(); $modelList = $this->deliverable->buildModelList($type); diff --git a/module/deliverable/model.php b/module/deliverable/model.php index 0062d4e089..370a923b2e 100644 --- a/module/deliverable/model.php +++ b/module/deliverable/model.php @@ -12,7 +12,7 @@ class deliverableModel extends model * @access public * @return array */ - public function getList($browseType = '', $queryID = 0, $orderBy = 'id_desc', $pager = null) + public function getList(string $browseType = '', int $queryID = 0, string $orderBy = 'id_desc', object $pager = null) { return $this->dao->select('*')->from(TABLE_DELIVERABLE) ->where('deleted')->eq(0) @@ -29,7 +29,7 @@ class deliverableModel extends model * @access public * @return bool */ - public function create($deliverable) + public function create(object $deliverable) { $this->dao->insert(TABLE_DELIVERABLE)->data($deliverable)->exec(); if(dao::isError()) return false; @@ -56,7 +56,7 @@ class deliverableModel extends model * @access public * @return array */ - public function buildModelList($type = 'all') + public function buildModelList(string $type = 'all') { $this->app->loadLang('stage'); $this->app->loadLang('execution'); @@ -89,4 +89,4 @@ class deliverableModel extends model return $modelList; } -} +} \ No newline at end of file From b9f9d7b68544f5ae124add81d0a25d8baf13e1b6 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 07:19:24 +0000 Subject: [PATCH 030/136] * [misc] add return define. --- module/deliverable/model.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/module/deliverable/model.php b/module/deliverable/model.php index 370a923b2e..015f9f548a 100644 --- a/module/deliverable/model.php +++ b/module/deliverable/model.php @@ -12,7 +12,7 @@ class deliverableModel extends model * @access public * @return array */ - public function getList(string $browseType = '', int $queryID = 0, string $orderBy = 'id_desc', object $pager = null) + public function getList(string $browseType = '', int $queryID = 0, string $orderBy = 'id_desc', object $pager = null): array { return $this->dao->select('*')->from(TABLE_DELIVERABLE) ->where('deleted')->eq(0) @@ -29,7 +29,7 @@ class deliverableModel extends model * @access public * @return bool */ - public function create(object $deliverable) + public function create(object $deliverable): bool { $this->dao->insert(TABLE_DELIVERABLE)->data($deliverable)->exec(); if(dao::isError()) return false; @@ -56,7 +56,7 @@ class deliverableModel extends model * @access public * @return array */ - public function buildModelList(string $type = 'all') + public function buildModelList(string $type = 'all'): array { $this->app->loadLang('stage'); $this->app->loadLang('execution'); From 0ba870ae15e638f36a7fb39e78d4fa1e35791ce2 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 07:27:24 +0000 Subject: [PATCH 031/136] * [misc] remove code. --- module/deliverable/config.php | 19 ------ module/deliverable/config/dtable.php | 52 --------------- module/deliverable/config/form.php | 8 --- module/deliverable/control.php | 83 ------------------------ module/deliverable/css/create.ui.css | 7 -- module/deliverable/js/browse.ui.js | 7 -- module/deliverable/js/create.ui.js | 22 ------- module/deliverable/lang/de.php | 30 --------- module/deliverable/lang/en.php | 30 --------- module/deliverable/lang/fr.php | 30 --------- module/deliverable/lang/zh-cn.php | 30 --------- module/deliverable/model.php | 92 --------------------------- module/deliverable/ui/browse.html.php | 59 ----------------- module/deliverable/ui/create.html.php | 70 -------------------- 14 files changed, 539 deletions(-) delete mode 100644 module/deliverable/config.php delete mode 100644 module/deliverable/config/dtable.php delete mode 100644 module/deliverable/config/form.php delete mode 100644 module/deliverable/control.php delete mode 100644 module/deliverable/css/create.ui.css delete mode 100644 module/deliverable/js/browse.ui.js delete mode 100644 module/deliverable/js/create.ui.js delete mode 100644 module/deliverable/lang/de.php delete mode 100644 module/deliverable/lang/en.php delete mode 100644 module/deliverable/lang/fr.php delete mode 100644 module/deliverable/lang/zh-cn.php delete mode 100644 module/deliverable/model.php delete mode 100644 module/deliverable/ui/browse.html.php delete mode 100644 module/deliverable/ui/create.html.php diff --git a/module/deliverable/config.php b/module/deliverable/config.php deleted file mode 100644 index 54c7257949..0000000000 --- a/module/deliverable/config.php +++ /dev/null @@ -1,19 +0,0 @@ -deliverable = new stdclass(); -$config->deliverable->create = new stdclass(); -$config->deliverable->edit = new stdclass(); -$config->deliverable->create->requiredFields = 'name,module,method,model'; -$config->deliverable->edit->requiredFields = 'name,module,method,model'; - -$config->deliverable->actionList = array(); -$config->deliverable->actionList['edit']['icon'] = 'edit'; -$config->deliverable->actionList['edit']['text'] = $lang->deliverable->edit; -$config->deliverable->actionList['edit']['hint'] = $lang->deliverable->edit; -$config->deliverable->actionList['edit']['url'] = array('module' => 'deliverable', 'method' => 'edit', 'params' => 'id={id}'); - -$config->deliverable->actionList['delete']['icon'] = 'trash'; -$config->deliverable->actionList['delete']['text'] = $lang->deliverable->delete; -$config->deliverable->actionList['delete']['hint'] = $lang->deliverable->delete; -$config->deliverable->actionList['delete']['url'] = array('module' => 'deliverable', 'method' => 'delete', 'params' => 'id={id}'); -$config->deliverable->actionList['delete']['data-confirm'] = $lang->deliverable->confirmDelete; \ No newline at end of file diff --git a/module/deliverable/config/dtable.php b/module/deliverable/config/dtable.php deleted file mode 100644 index 3cb51c25cc..0000000000 --- a/module/deliverable/config/dtable.php +++ /dev/null @@ -1,52 +0,0 @@ -deliverable->dtable = new stdclass(); - -$config->deliverable->dtable->fieldList['id']['title'] = $lang->idAB; -$config->deliverable->dtable->fieldList['id']['name'] = 'id'; -$config->deliverable->dtable->fieldList['id']['type'] = 'checkID'; -$config->deliverable->dtable->fieldList['id']['sortType'] = true; -$config->deliverable->dtable->fieldList['id']['checkbox'] = true; -$config->deliverable->dtable->fieldList['id']['width'] = '80'; -$config->deliverable->dtable->fieldList['id']['required'] = true; - -$config->deliverable->dtable->fieldList['name']['title'] = $lang->deliverable->name; -$config->deliverable->dtable->fieldList['name']['name'] = 'name'; -$config->deliverable->dtable->fieldList['name']['type'] = 'title'; -$config->deliverable->dtable->fieldList['name']['fixed'] = 'left'; -$config->deliverable->dtable->fieldList['name']['link'] = helper::createLink('deliverable', 'view', 'id={id}'); -$config->deliverable->dtable->fieldList['name']['sortType'] = true; - -$config->deliverable->dtable->fieldList['module']['title'] = $lang->deliverable->module; -$config->deliverable->dtable->fieldList['module']['name'] = 'module'; -$config->deliverable->dtable->fieldList['module']['type'] = 'category'; -$config->deliverable->dtable->fieldList['module']['map'] = $lang->deliverable->moduleList; -$config->deliverable->dtable->fieldList['module']['sortType'] = true; - -$config->deliverable->dtable->fieldList['method']['title'] = $lang->deliverable->method; -$config->deliverable->dtable->fieldList['method']['name'] = 'method'; -$config->deliverable->dtable->fieldList['method']['type'] = 'category'; -$config->deliverable->dtable->fieldList['method']['map'] = $lang->deliverable->methodList; -$config->deliverable->dtable->fieldList['method']['sortType'] = true; - -$config->deliverable->dtable->fieldList['model']['title'] = $lang->deliverable->model; -$config->deliverable->dtable->fieldList['model']['name'] = 'model'; -$config->deliverable->dtable->fieldList['model']['type'] = 'text'; -$config->deliverable->dtable->fieldList['model']['sortType'] = true; - -$config->deliverable->dtable->fieldList['createdBy']['title'] = $lang->deliverable->createdBy; -$config->deliverable->dtable->fieldList['createdBy']['name'] = 'createdBy'; -$config->deliverable->dtable->fieldList['createdBy']['type'] = 'user'; -$config->deliverable->dtable->fieldList['createdBy']['sortType'] = true; - -$config->deliverable->dtable->fieldList['createdDate']['title'] = $lang->deliverable->createdDate; -$config->deliverable->dtable->fieldList['createdDate']['name'] = 'createdDate'; -$config->deliverable->dtable->fieldList['createdDate']['type'] = 'date'; -$config->deliverable->dtable->fieldList['createdDate']['sortType'] = true; - -$config->deliverable->dtable->fieldList['actions']['title'] = $lang->actions; -$config->deliverable->dtable->fieldList['actions']['type'] = 'actions'; -$config->deliverable->dtable->fieldList['actions']['fixed'] = 'right'; -$config->deliverable->dtable->fieldList['actions']['list'] = $config->deliverable->actionList; -$config->deliverable->dtable->fieldList['actions']['menu'] = array('edit', 'delete'); -$config->deliverable->dtable->fieldList['actions']['sortType'] = false; \ No newline at end of file diff --git a/module/deliverable/config/form.php b/module/deliverable/config/form.php deleted file mode 100644 index 17aaf7f49a..0000000000 --- a/module/deliverable/config/form.php +++ /dev/null @@ -1,8 +0,0 @@ -deliverable->form = new stdclass(); -$config->deliverable->form->create = array(); -$config->deliverable->form->create['name'] = array('type' => 'string', 'required' => true); -$config->deliverable->form->create['module'] = array('type' => 'string', 'required' => true); -$config->deliverable->form->create['method'] = array('type' => 'string', 'required' => true); -$config->deliverable->form->create['model'] = array('type' => 'array', 'required' => true, 'filter' => 'join'); -$config->deliverable->form->create['desc'] = array('type' => 'string', 'required' => false, 'control' => 'editor'); \ No newline at end of file diff --git a/module/deliverable/control.php b/module/deliverable/control.php deleted file mode 100644 index 3b5b08ad97..0000000000 --- a/module/deliverable/control.php +++ /dev/null @@ -1,83 +0,0 @@ -app->loadClass('pager', true); - $pager = new pager($recTotal, $recPerPage, $pageID); - - $queryID = $browseType == 'bysearch' ? (int)$param : 0; - - $this->view->title = $this->lang->deliverable->common; - $this->view->deliverables = $this->deliverable->getList($browseType, $queryID, $orderBy, $pager); - $this->view->orderBy = $orderBy; - $this->view->pager = $pager; - $this->view->browseType = $browseType; - $this->view->param = $param; - $this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted|noletter'); - $this->display(); - } - - /** - * 创建交付物。 - * Create deliverable. - * - * @access public - * @return void - */ - public function create() - { - if($_POST) - { - $files = $this->loadModel('file')->getUpload(); - if(empty($files[0]['title'])) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->error->notempty, $this->lang->deliverable->files))); - - $deliverable = form::data($this->config->deliverable->form->create) - ->add('createdBy', $this->app->user->account) - ->add('createdDate', helper::today()) - ->get(); - - $this->deliverable->create($deliverable); - - if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); - return $this->sendSuccess(array('load' => inlink('browse'))); - } - - $this->view->title = $this->lang->deliverable->create; - $this->view->modelList = $this->deliverable->buildModelList('project'); - $this->display(); - } - - /** - * Ajax获取交付物适用范围列表。 - * Ajax get deliverable model list. - * - * @param string $type execution|project - * @access public - * @return void - */ - public function ajaxGetModelList(string $type = 'execution') - { - $items = array(); - $modelList = $this->deliverable->buildModelList($type); - foreach($modelList as $key => $value) - { - $items[] = array('value' => $key, 'text' => $value); - } - - return print(json_encode($items)); - } -} \ No newline at end of file diff --git a/module/deliverable/css/create.ui.css b/module/deliverable/css/create.ui.css deleted file mode 100644 index 1a00c1bdae..0000000000 --- a/module/deliverable/css/create.ui.css +++ /dev/null @@ -1,7 +0,0 @@ -.template-group { - width: 48%; -} - -.template-or { - width: 4%; -} diff --git a/module/deliverable/js/browse.ui.js b/module/deliverable/js/browse.ui.js deleted file mode 100644 index db705efa35..0000000000 --- a/module/deliverable/js/browse.ui.js +++ /dev/null @@ -1,7 +0,0 @@ -window.getCellSpan = function(cell) -{ - if(['id', 'name', 'module', 'method', 'createdBy', 'createdDate', 'actions'].includes(cell.col.name) && cell.row.data.rowspan) - { - return {rowSpan: cell.row.data.rowspan}; - } -} diff --git a/module/deliverable/js/create.ui.js b/module/deliverable/js/create.ui.js deleted file mode 100644 index e024a2f2d0..0000000000 --- a/module/deliverable/js/create.ui.js +++ /dev/null @@ -1,22 +0,0 @@ -window.changeModule = function(e) -{ - const module = e.target.value; - const url = $.createLink('deliverable', 'ajaxGetModelList', `type=${module}`); - - if(module == 'execution') - { - $('[name="method"]').zui('picker').$.setValue('close'); - $('[name="method"]').zui('picker').render({disabled: true}); - } - else - { - $('[name="method"]').zui('picker').$.setValue(''); - $('[name="method"]').zui('picker').render({disabled: false}); - } - - $.getJSON(url, function(data) - { - $('[name="model"]').zui('picker').render({items: data}); - $('[name="model"]').zui('picker').$.setValue(''); - }); -} diff --git a/module/deliverable/lang/de.php b/module/deliverable/lang/de.php deleted file mode 100644 index f39913b3dc..0000000000 --- a/module/deliverable/lang/de.php +++ /dev/null @@ -1,30 +0,0 @@ -deliverable->name = 'Name'; -$lang->deliverable->desc = 'Description'; -$lang->deliverable->module = 'Applicable Object'; -$lang->deliverable->method = 'Action'; -$lang->deliverable->model = 'Applicable Scope'; -$lang->deliverable->createdBy = 'Created By'; -$lang->deliverable->createdDate = 'Created Date'; -$lang->deliverable->template = 'Reference Template'; -$lang->deliverable->files = 'Upload Template'; -$lang->deliverable->or = 'OR'; - -$lang->deliverable->create = 'Add Deliverable'; -$lang->deliverable->edit = 'Edit Deliverable'; -$lang->deliverable->delete = 'Delete Deliverable'; -$lang->deliverable->view = 'Deliverable Details'; - -$lang->deliverable->moduleList['project'] = 'Project'; -$lang->deliverable->moduleList['execution'] = 'Execution'; - -$lang->deliverable->methodList['create'] = 'Create'; -$lang->deliverable->methodList['close'] = 'Close'; - -$lang->deliverable->modelList['product_waterfall'] = 'Product Waterfall'; -$lang->deliverable->modelList['project_waterfall'] = 'Project Waterfall'; -$lang->deliverable->modelList['product_scrum'] = 'Product Scrum'; -$lang->deliverable->modelList['project_scrum'] = 'Project Scrum'; - -$lang->deliverable->confirmDelete = 'Are you sure to delete this deliverable?'; -$lang->deliverable->summary = 'There are %s deliverables on this page'; \ No newline at end of file diff --git a/module/deliverable/lang/en.php b/module/deliverable/lang/en.php deleted file mode 100644 index f39913b3dc..0000000000 --- a/module/deliverable/lang/en.php +++ /dev/null @@ -1,30 +0,0 @@ -deliverable->name = 'Name'; -$lang->deliverable->desc = 'Description'; -$lang->deliverable->module = 'Applicable Object'; -$lang->deliverable->method = 'Action'; -$lang->deliverable->model = 'Applicable Scope'; -$lang->deliverable->createdBy = 'Created By'; -$lang->deliverable->createdDate = 'Created Date'; -$lang->deliverable->template = 'Reference Template'; -$lang->deliverable->files = 'Upload Template'; -$lang->deliverable->or = 'OR'; - -$lang->deliverable->create = 'Add Deliverable'; -$lang->deliverable->edit = 'Edit Deliverable'; -$lang->deliverable->delete = 'Delete Deliverable'; -$lang->deliverable->view = 'Deliverable Details'; - -$lang->deliverable->moduleList['project'] = 'Project'; -$lang->deliverable->moduleList['execution'] = 'Execution'; - -$lang->deliverable->methodList['create'] = 'Create'; -$lang->deliverable->methodList['close'] = 'Close'; - -$lang->deliverable->modelList['product_waterfall'] = 'Product Waterfall'; -$lang->deliverable->modelList['project_waterfall'] = 'Project Waterfall'; -$lang->deliverable->modelList['product_scrum'] = 'Product Scrum'; -$lang->deliverable->modelList['project_scrum'] = 'Project Scrum'; - -$lang->deliverable->confirmDelete = 'Are you sure to delete this deliverable?'; -$lang->deliverable->summary = 'There are %s deliverables on this page'; \ No newline at end of file diff --git a/module/deliverable/lang/fr.php b/module/deliverable/lang/fr.php deleted file mode 100644 index f39913b3dc..0000000000 --- a/module/deliverable/lang/fr.php +++ /dev/null @@ -1,30 +0,0 @@ -deliverable->name = 'Name'; -$lang->deliverable->desc = 'Description'; -$lang->deliverable->module = 'Applicable Object'; -$lang->deliverable->method = 'Action'; -$lang->deliverable->model = 'Applicable Scope'; -$lang->deliverable->createdBy = 'Created By'; -$lang->deliverable->createdDate = 'Created Date'; -$lang->deliverable->template = 'Reference Template'; -$lang->deliverable->files = 'Upload Template'; -$lang->deliverable->or = 'OR'; - -$lang->deliverable->create = 'Add Deliverable'; -$lang->deliverable->edit = 'Edit Deliverable'; -$lang->deliverable->delete = 'Delete Deliverable'; -$lang->deliverable->view = 'Deliverable Details'; - -$lang->deliverable->moduleList['project'] = 'Project'; -$lang->deliverable->moduleList['execution'] = 'Execution'; - -$lang->deliverable->methodList['create'] = 'Create'; -$lang->deliverable->methodList['close'] = 'Close'; - -$lang->deliverable->modelList['product_waterfall'] = 'Product Waterfall'; -$lang->deliverable->modelList['project_waterfall'] = 'Project Waterfall'; -$lang->deliverable->modelList['product_scrum'] = 'Product Scrum'; -$lang->deliverable->modelList['project_scrum'] = 'Project Scrum'; - -$lang->deliverable->confirmDelete = 'Are you sure to delete this deliverable?'; -$lang->deliverable->summary = 'There are %s deliverables on this page'; \ No newline at end of file diff --git a/module/deliverable/lang/zh-cn.php b/module/deliverable/lang/zh-cn.php deleted file mode 100644 index aeae035177..0000000000 --- a/module/deliverable/lang/zh-cn.php +++ /dev/null @@ -1,30 +0,0 @@ -deliverable->name = '名称'; -$lang->deliverable->desc = '描述'; -$lang->deliverable->module = '适用对象'; -$lang->deliverable->method = '动作'; -$lang->deliverable->model = '适用范围'; -$lang->deliverable->createdBy = '创建人'; -$lang->deliverable->createdDate = '创建时间'; -$lang->deliverable->template = '引用模板'; -$lang->deliverable->files = '上传模板'; -$lang->deliverable->or = '或'; - -$lang->deliverable->create = '添加交付物'; -$lang->deliverable->edit = '编辑交付物'; -$lang->deliverable->delete = '删除交付物'; -$lang->deliverable->view = '交付物详情'; - -$lang->deliverable->moduleList['project'] = '项目'; -$lang->deliverable->moduleList['execution'] = '执行'; - -$lang->deliverable->methodList['create'] = '创建'; -$lang->deliverable->methodList['close'] = '关闭'; - -$lang->deliverable->modelList['product_waterfall'] = '产品型瀑布项目'; -$lang->deliverable->modelList['project_waterfall'] = '项目型瀑布项目'; -$lang->deliverable->modelList['product_scrum'] = '产品型敏捷项目'; -$lang->deliverable->modelList['project_scrum'] = '项目型敏捷项目'; - -$lang->deliverable->confirmDelete = '确定删除该交付物吗?'; -$lang->deliverable->summary = '本页共有%s个交付物'; \ No newline at end of file diff --git a/module/deliverable/model.php b/module/deliverable/model.php deleted file mode 100644 index 015f9f548a..0000000000 --- a/module/deliverable/model.php +++ /dev/null @@ -1,92 +0,0 @@ -dao->select('*')->from(TABLE_DELIVERABLE) - ->where('deleted')->eq(0) - ->orderBy($orderBy) - ->page($pager) - ->fetchAll('id', false); - } - - /** - * 创建交付物。 - * Create deliverable. - * - * @param object $deliverable - * @access public - * @return bool - */ - public function create(object $deliverable): bool - { - $this->dao->insert(TABLE_DELIVERABLE)->data($deliverable)->exec(); - if(dao::isError()) return false; - - $deliverableID = $this->dao->lastInsertID(); - - $files = $this->loadModel('file')->saveUpload('deliverable', $deliverableID); - if(!empty($files)) - { - $fileIdList = implode(',', array_keys($files)); - $this->dao->update(TABLE_DELIVERABLE)->set('files')->eq($fileIdList)->where('id')->eq($deliverableID)->exec(); - } - - $this->loadModel('action')->create('deliverable', $deliverableID, 'opened'); - - return !dao::isError(); - } - - /** - * 构造交付物适用范围列表。 - * Build deliverable model list. - * - * @param string $type all|project|execution - * @access public - * @return array - */ - public function buildModelList(string $type = 'all'): array - { - $this->app->loadLang('stage'); - $this->app->loadLang('execution'); - - $modelList = array(); - - if($type == 'all' || $type == 'project') $modelList = $this->lang->deliverable->modelList; - if($type == 'all' || $type == 'execution') - { - $stageList = $this->lang->stage->typeList; - $lifeTimeList = $this->lang->execution->lifeTimeList; - foreach($this->lang->deliverable->modelList as $key => $value) - { - if(strpos($key, 'waterfall') !== false) - { - foreach($stageList as $stageKey => $stageValue) - { - $modelList[$key . '_' . $stageKey] = $value . '/' . $stageValue . $this->lang->execution->typeList['stage']; - } - } - elseif(strpos($key, 'scrum') !== false) - { - foreach($lifeTimeList as $lifeTimeKey => $lifeTimeValue) - { - $modelList[$key . '_' . $lifeTimeKey] = $value . '/' . $lifeTimeValue . $this->lang->execution->typeList['sprint']; - } - } - } - } - - return $modelList; - } -} \ No newline at end of file diff --git a/module/deliverable/ui/browse.html.php b/module/deliverable/ui/browse.html.php deleted file mode 100644 index a44ff59d4b..0000000000 --- a/module/deliverable/ui/browse.html.php +++ /dev/null @@ -1,59 +0,0 @@ - 'plus', - 'class' => 'primary', - 'text' => $lang->deliverable->create, - 'data-app' => $app->tab, - 'url' => createLink('deliverable', 'create') - ))) : null, -); - -$cols = $config->deliverable->dtable->fieldList; -$modelList = $this->deliverable->buildModelList('all'); - -$summary = sprintf($lang->deliverable->summary, count($deliverables)); -$tableData = initTableData($deliverables, $cols, $this->deliverable); -$data = array(); -foreach($tableData as $key => $row) -{ - if($row->model) - { - $models = explode(',', $row->model); - foreach($models as $model) - { - $row->model = $modelList[$model]; - $row->rowspan = count($models); - $data[] = clone $row; - } - } - else - { - $data[] = $row; - } -} - -dtable -( - set::cols($cols), - set::data($data), - set::userMap($users), - set::orderBy($orderBy), - set::plugins(array('cellspan')), - set::checkable(false), - set::sortLink(createLink('deliverable', 'browse', "browseType=$browseType¶m={$param}&orderBy={name}_{sortType}&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}")), - set::getCellSpan(jsRaw('window.getCellSpan')), - set::footer(array($summary, 'flex', 'pager')), - set::footPager(usePager(array - ( - 'recTotal' => $pager->recTotal, - 'recPerPage' => $pager->recPerPage, - 'linkCreator' => helper::createLink('deliverable', 'browse', "browseType=$browseType¶m={$param}&orderBy=$orderBy&recTotal={$pager->recTotal}&recPerPage={recPerPage}&page={page}") - ))) -); diff --git a/module/deliverable/ui/create.html.php b/module/deliverable/ui/create.html.php deleted file mode 100644 index a888e08f74..0000000000 --- a/module/deliverable/ui/create.html.php +++ /dev/null @@ -1,70 +0,0 @@ -deliverable->create), - set::grid(true), - set::layout('grid'), - formGroup - ( - set::width('1/2'), - set::label($lang->deliverable->name), - set::name('name') - ), - formGroup(set::width('1/2')), - formGroup - ( - set::width('1/3'), - set::label($lang->deliverable->module), - picker - ( - on::change('changeModule'), - set::name('module'), - set::required(true), - set::items($lang->deliverable->moduleList) - ) - ), - formGroup - ( - set::width('1/6'), - set::label($lang->deliverable->method), - picker - ( - set::name('method'), - set::required(true), - set::items($lang->deliverable->methodList) - ) - ), - formGroup(set::width('1/2')), - formGroup - ( - set::width('1/2'), - set::label($lang->deliverable->model), - picker - ( - set::name('model'), - set::multiple(true), - set::items($modelList) - ) - ), - formGroup - ( - set::width('full'), - set::label($lang->deliverable->desc), - editor - ( - set::name('desc') - ) - ), - formGroup - ( - set::width('full'), - set::label($lang->deliverable->files), - set::required(true), - fileselector - ( - set::name('files') - ) - ) -); From 3a3f87c0f3d4efcb4fcc05c29b64c775abfc6e6e Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 16 Apr 2025 07:41:04 +0000 Subject: [PATCH 032/136] * [misc] hide deliverable menu in max/ipd. --- module/admin/lang/menu.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/module/admin/lang/menu.php b/module/admin/lang/menu.php index 52ff82963b..88350fb893 100644 --- a/module/admin/lang/menu.php +++ b/module/admin/lang/menu.php @@ -88,7 +88,7 @@ $lang->admin->menuList->model['menuOrder']['25'] = 'waterfallplus'; $lang->admin->menuList->model['tabMenu']['common']['project'] = array('link' => "{$lang->project->common}|custom|required|module=project", 'alias' => 'set,project', 'exclude' => 'custom-required', 'links' => array('custom|set|module=project&field=unitList')); if(helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['common']['stage'] = array('link' => "{$lang->stage->type}|stage|settype|", 'subModule' => 'stage'); -$lang->admin->menuList->model['tabMenu']['common']['deliverable'] = array('link' => "{$lang->deliverable->common}|deliverable|browse|", 'subModule' => 'deliverable'); +if($config->edition == 'max' or $config->edition == 'ipd') $lang->admin->menuList->model['tabMenu']['common']['deliverable'] = array('link' => "{$lang->deliverable->common}|deliverable|browse|", 'subModule' => 'deliverable'); $lang->admin->menuList->model['tabMenu']['common']['build'] = array('link' => "{$lang->build->common}|custom|required|module=build", 'alias' => 'set', 'exclude' => 'custom'); $lang->admin->menuList->model['tabMenu']['common']['flow'] = array('link' => "{$lang->custom->flow}|custom|flow|", 'divider' => true); @@ -99,12 +99,15 @@ if(helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu'] $lang->admin->menuList->model['tabMenu']['menuOrder']['common']['5'] = 'project'; if(helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['menuOrder']['common']['7'] = 'stage'; $lang->admin->menuList->model['tabMenu']['menuOrder']['common']['10'] = 'build'; -$lang->admin->menuList->model['tabMenu']['menuOrder']['common']['15'] = 'deliverable'; $lang->admin->menuList->model['tabMenu']['menuOrder']['common']['35'] = 'flow'; $lang->admin->menuList->model['tabMenu']['menuOrder']['common']['40'] = 'percent'; $lang->admin->menuList->model['tabMenu']['menuOrder']['common']['45'] = 'hours'; if(helper::hasFeature('waterfall')) $lang->admin->menuList->model['tabMenu']['menuOrder']['waterfall']['5'] = 'stage'; if(helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['menuOrder']['waterfallplus']['5'] = 'stage'; +if($config->edition == 'max' or $config->edition == 'ipd') +{ + $lang->admin->menuList->model['tabMenu']['menuOrder']['common']['15'] = 'deliverable'; +} $lang->admin->menuList->feature['subMenu']['my'] = array('link' => "{$lang->my->common}|custom|set|module=todo&field=priList", 'exclude' => 'set,required'); $lang->admin->menuList->feature['subMenu']['product'] = array('link' => "{$lang->productCommon}|custom|required|module=product", 'exclude' => 'set,required', 'alias' => 'browsestoryconcept,product'); From 9df22a7d2901672a19a3a74b1b327d3a4e881112 Mon Sep 17 00:00:00 2001 From: wangyuting Date: Thu, 17 Apr 2025 14:15:00 +0800 Subject: [PATCH 033/136] * [task#141584,done,0.1h,0h] Add deliverable column to table workflowgroup. --- db/update21.7.sql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/db/update21.7.sql b/db/update21.7.sql index 10c07292f6..eb2f931bd5 100644 --- a/db/update21.7.sql +++ b/db/update21.7.sql @@ -11,4 +11,6 @@ CREATE TABLE IF NOT EXISTS `zt_deliverable` ( `createdDate` date NULL, `deleted` enum('0','1') NOT NULL DEFAULT '0', PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +ALTER TABLE `zt_workflowgroup` ADD COLUMN `deliverable` text NULL DEFAULT ''; From 3efe7edebc9cabd990ef4debd44e713f9d7084ea Mon Sep 17 00:00:00 2001 From: wangyuting Date: Thu, 17 Apr 2025 14:25:18 +0800 Subject: [PATCH 034/136] * [task#141584,done,0.1h,0h] Fix back btn link error. --- lib/zin/wg/backbtn/v1.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/zin/wg/backbtn/v1.php b/lib/zin/wg/backbtn/v1.php index 5b20fca7ac..2ea51e7215 100644 --- a/lib/zin/wg/backbtn/v1.php +++ b/lib/zin/wg/backbtn/v1.php @@ -96,7 +96,8 @@ class backBtn extends btn 'approvalflow' => 'approvalflow-browse', 'host' => 'host-browse,my-index', 'deploy' => 'deploy-browse', - 'program' => 'program-browse,program-productview' + 'program' => 'program-browse,program-productview', + 'workflowgroup' => 'workflowgroup-project,workflowgroup-deliverable' ); $props = parent::getProps(); From 149beb30cefd3858082aa83ad8dcf5dff5762725 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Thu, 17 Apr 2025 03:02:07 +0000 Subject: [PATCH 035/136] * [misc] add sql. --- db/update21.7.sql | 2 ++ db/zentao.sql | 2 ++ 2 files changed, 4 insertions(+) diff --git a/db/update21.7.sql b/db/update21.7.sql index eb2f931bd5..96cea51ddf 100644 --- a/db/update21.7.sql +++ b/db/update21.7.sql @@ -9,6 +9,8 @@ CREATE TABLE IF NOT EXISTS `zt_deliverable` ( `files` varchar(255) NULL, `createdBy` varchar(30) NULL, `createdDate` date NULL, + `lastEditedBy` varchar(30) NULL, + `lastEditedDate` date NULL, `deleted` enum('0','1') NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/db/zentao.sql b/db/zentao.sql index 3521246e68..81f470ad53 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -590,6 +590,8 @@ CREATE TABLE IF NOT EXISTS `zt_deliverable` ( `files` varchar(255) NULL, `createdBy` varchar(30) NULL, `createdDate` date NULL, + `lastEditedBy` varchar(30) NULL, + `lastEditedDate` date NULL, `deleted` enum('0','1') NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; From ea0781a0b0f8c5f3336eae7fc2c0c599babe4e6b Mon Sep 17 00:00:00 2001 From: sunguangming Date: Thu, 17 Apr 2025 08:12:29 +0000 Subject: [PATCH 036/136] * [bug#61617,done,3h] fix bug. --- module/programplan/js/create.ui.js | 43 +++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/module/programplan/js/create.ui.js b/module/programplan/js/create.ui.js index d2934c648c..e908ef6a5b 100644 --- a/module/programplan/js/create.ui.js +++ b/module/programplan/js/create.ui.js @@ -132,7 +132,7 @@ window.handleRenderRow = function($row, index, data) if($prevLevelRow.attr('data-level') == level - 1) break; $prevLevelRow = $prevLevelRow.prev(); } - if($prevLevelRow.length == 1) $row.attr('data-parent', $prevLevelRow.attr('data-index')); + if($prevLevelRow.length == 1) $row.attr('data-parent', $prevLevelRow.attr('data-gid')); } if($row.find('input[data-name="milestone"]:checked').length == 0) $row.find('input[data-name="milestone"]').eq(1).prop('checked', true); //里程碑默认选择“否”。 @@ -461,3 +461,44 @@ window.onMove = function(event, originEvent) return true; } + +$(function() +{ + window.waitDom('[data-zui-sortable]', function() + { + const $batchForm = $('[data-zui-batchform]').zui('batchForm'); + if(typeof $batchForm != 'undefined') + { + $batchForm._sortable._options.onSort = (e) => { + window.resetRows(); + $batchForm._rows = $batchForm._sortable.toArray().map(Number); + $batchForm.render(); + } + } + }); +}) + +window.resetRows = function() +{ + const $trs = $('.form-batch-table tbody tr'); + + $trs.each(function(index, element) + { + let parent = $(element).attr('data-parent'); + if(parent == -1) return; + + const $parent = $(`tr[data-gid='${parent}']`); + const parentLevel = $parent.attr('data-level'); + + let $nextRow = $parent.next(); + while(true) + { + if($nextRow.length == 0) break; + if($nextRow.attr('data-level') <= parentLevel) break; + + $nextRow = $nextRow.next(); + } + + $nextRow.before($(element)); + }); +} From 2215166d170e3de05c8ef5dbfa3e196c0dc6de2d Mon Sep 17 00:00:00 2001 From: sunguangming Date: Thu, 17 Apr 2025 08:15:17 +0000 Subject: [PATCH 037/136] * [misc] add default ditto. --- module/task/ui/batchedit.html.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/task/ui/batchedit.html.php b/module/task/ui/batchedit.html.php index 706d79eb05..86b24479ba 100644 --- a/module/task/ui/batchedit.html.php +++ b/module/task/ui/batchedit.html.php @@ -146,7 +146,8 @@ formBatchPanel set::control('priPicker'), set::ditto(true), set::items($lang->task->priList), - set::width('110px') + set::width('110px'), + set::defaultDitto('off') ), formBatchItem ( From fad0a545e8da683a28b97c4a006c5ffea1f0f359 Mon Sep 17 00:00:00 2001 From: wangyuting Date: Thu, 17 Apr 2025 16:51:28 +0800 Subject: [PATCH 038/136] * [task#141580,done,0.5h,0h] Add deliverable priv package. --- module/group/lang/de.php | 1 + module/group/lang/en.php | 1 + module/group/lang/fr.php | 1 + module/group/lang/zh-cn.php | 1 + module/group/packagemanager.php | 11 +++++++++++ 5 files changed, 15 insertions(+) diff --git a/module/group/lang/de.php b/module/group/lang/de.php index c5242f8351..14df894aea 100644 --- a/module/group/lang/de.php +++ b/module/group/lang/de.php @@ -488,6 +488,7 @@ $lang->group->package->projectBuild = 'Project Build'; $lang->group->package->importCaseLib = 'Import Case Lib'; $lang->group->package->commonSetting = 'Common Setting'; $lang->group->package->stageSetting = 'Stage Setting'; +$lang->group->package->deliverable = 'Deliverable Setting'; $lang->group->package->classify = 'Classify'; $lang->group->package->cmcl = 'Cmcl'; $lang->group->package->auditcl = 'Auditcl'; diff --git a/module/group/lang/en.php b/module/group/lang/en.php index 0077e8d7b3..be5d540aa4 100644 --- a/module/group/lang/en.php +++ b/module/group/lang/en.php @@ -488,6 +488,7 @@ $lang->group->package->projectBuild = 'Project Build'; $lang->group->package->importCaseLib = 'Import Case Lib'; $lang->group->package->commonSetting = 'Common Setting'; $lang->group->package->stageSetting = 'Stage Setting'; +$lang->group->package->deliverable = 'Deliverable Setting'; $lang->group->package->classify = 'Classify'; $lang->group->package->cmcl = 'Cmcl'; $lang->group->package->auditcl = 'Auditcl'; diff --git a/module/group/lang/fr.php b/module/group/lang/fr.php index 8b10db5e55..e85ec66261 100644 --- a/module/group/lang/fr.php +++ b/module/group/lang/fr.php @@ -488,6 +488,7 @@ $lang->group->package->projectBuild = 'Project Build'; $lang->group->package->importCaseLib = 'Import Case Lib'; $lang->group->package->commonSetting = 'Common Setting'; $lang->group->package->stageSetting = 'Stage Setting'; +$lang->group->package->deliverable = 'Deliverable Setting'; $lang->group->package->classify = 'Classify'; $lang->group->package->cmcl = 'Cmcl'; $lang->group->package->auditcl = 'Auditcl'; diff --git a/module/group/lang/zh-cn.php b/module/group/lang/zh-cn.php index 91b990594b..f17ec55817 100644 --- a/module/group/lang/zh-cn.php +++ b/module/group/lang/zh-cn.php @@ -488,6 +488,7 @@ $lang->group->package->projectBuild = '项目构建'; $lang->group->package->importCaseLib = '导入用例库'; $lang->group->package->commonSetting = '通用配置'; $lang->group->package->stageSetting = '阶段列表设置'; +$lang->group->package->deliverable = '交付物设置'; $lang->group->package->classify = '分类项设置'; $lang->group->package->cmcl = '审计设置'; $lang->group->package->auditcl = 'QA检查项设置'; diff --git a/module/group/packagemanager.php b/module/group/packagemanager.php index cd86ce98f9..1dc6c6e8ef 100644 --- a/module/group/packagemanager.php +++ b/module/group/packagemanager.php @@ -2578,6 +2578,7 @@ $config->group->package->workflowGroup->privs['workflowgroup-setExclusive'] = $config->group->package->workflowGroup->privs['workflowgroup-activateFlow'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd,lite,or', 'order' => 55, 'depend' => array('workflow-browseFlow'), 'recommend' => array()); $config->group->package->workflowGroup->privs['workflowgroup-deactivateFlow'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd,lite,or', 'order' => 60, 'depend' => array('workflow-browseFlow'), 'recommend' => array()); $config->group->package->workflowGroup->privs['workflowgroup-rule'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd,lite,or', 'order' => 65, 'depend' => array('workflow-browseFlow'), 'recommend' => array()); +$config->group->package->workflowGroup->privs['workflowgroup-deliverable'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 70, 'depend' => array('workflow-browseFlow'), 'recommend' => array()); $config->group->package->workflow = new stdclass(); $config->group->package->workflow->order = 5; @@ -2996,6 +2997,16 @@ $config->group->package->stageSetting->privs['stage-edit'] = array('editi $config->group->package->stageSetting->privs['stage-delete'] = array('edition' => 'open,biz,max,ipd', 'vision' => 'rnd', 'order' => 5, 'depend' => array(), 'recommend' => array('stage-create', 'stage-edit')); $config->group->package->stageSetting->privs['stage-plusBrowse'] = array('edition' => 'open,biz,max,ipd', 'vision' => 'rnd', 'order' => 1, 'depend' => array(), 'recommend' => array()); +$config->group->package->deliverable = new stdclass(); +$config->group->package->deliverable->order = 20; +$config->group->package->deliverable->subset = 'modelconfig'; +$config->group->package->deliverable->privs = array(); +$config->group->package->deliverable->privs['deliverable-browse'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array(), 'recommend' => array()); +$config->group->package->deliverable->privs['deliverable-create'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 1, 'depend' => array(), 'recommend' => array()); +$config->group->package->deliverable->privs['deliverable-edit'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 2, 'depend' => array(), 'recommend' => array()); +$config->group->package->deliverable->privs['deliverable-delete'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 3, 'depend' => array(), 'recommend' => array()); +$config->group->package->deliverable->privs['deliverable-view'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 4, 'depend' => array(), 'recommend' => array()); + $config->group->package->classify = new stdclass(); $config->group->package->classify->order = 30; $config->group->package->classify->subset = 'modelconfig'; From 2eb8e02fd953df75874f93b0b5eea3f17109b51e Mon Sep 17 00:00:00 2001 From: sunguangming Date: Fri, 18 Apr 2025 01:38:06 +0000 Subject: [PATCH 039/136] * [misc] change lang. --- module/common/lang/zh-cn.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index 53f86f4665..73225eef14 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -294,7 +294,7 @@ $lang->featureswitch->common = '功能开关'; $lang->importdata->common = '数据导入'; $lang->systemsetting->common = '系统设置'; $lang->staffmanage->common = '人员管理'; -$lang->modelconfig->common = '模型配置'; +$lang->modelconfig->common = '项目模型配置'; $lang->featureconfig->common = '功能配置'; $lang->doctemplate->common = '文档模板'; $lang->notifysetting->common = '通知设置'; From 150c7117c8f9e0c57748970e818a6f6a1b9c9d71 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Fri, 18 Apr 2025 01:44:07 +0000 Subject: [PATCH 040/136] * Merge lint yaml. --- .gitfox/lint.yaml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.gitfox/lint.yaml b/.gitfox/lint.yaml index c56c46eef2..f7fa3278f2 100644 --- a/.gitfox/lint.yaml +++ b/.gitfox/lint.yaml @@ -9,6 +9,14 @@ spec: SONAR_HOST_URL: https://codescan.qc.oop.cc SONAR_TOKEN: ${{ secrets.get("codescan_sonar_token") }} steps: + - name: 预处理 + type: run + spec: + container: + image: hub.zentao.net/ci/alpine:3.19 + script: + - SONAR_PROJECT_KEY=$(echo $CI_REPO_NAME | tr '/' ':') + - echo "export SONAR_PROJECT_KEY=$SONAR_PROJECT_KEY" >> $GITFOX_CUSTOM_ENV - name: 配置scanner type: run spec: @@ -41,7 +49,8 @@ spec: type: run spec: container: - image: hub.zentao.net/app/sonar-scanner-cli:10 + image: hub.zentao.net/ci/sonar-scanner-cli:10 + pull: always script: - echo "run sonar-scanner" - export TASK_ID=$(sonar-scanner -Dsonar.token=${SONAR_TOKEN} | grep -o 'task?id=.*' | cut -d = -f 2) @@ -66,5 +75,5 @@ spec: url: ${GITFOX_BUILD_LINK} users: "0": "liyang" - "1": "{{ .build.author_name}}" + "1": "{{ .GITFOX_COMMIT_AUTHOR}}" name: gitfox-xuanim-plugin From d9fc11f095adcc5faeed2c5427622d9daf16508a Mon Sep 17 00:00:00 2001 From: sunguangming Date: Fri, 18 Apr 2025 05:10:32 +0000 Subject: [PATCH 041/136] * [misc] modify sql. --- db/update21.7.sql | 2 +- db/zentao.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/db/update21.7.sql b/db/update21.7.sql index 96cea51ddf..19f6f5cd43 100644 --- a/db/update21.7.sql +++ b/db/update21.7.sql @@ -3,7 +3,7 @@ CREATE TABLE IF NOT EXISTS `zt_deliverable` ( `name` varchar(255) NOT NULL, `module` varchar(30) NULL, `method` varchar(30) NULL, - `model` varchar(255) NULL, + `model` text NULL, `type` enum('doc','file') NULL DEFAULT 'file', `desc` text NULL, `files` varchar(255) NULL, diff --git a/db/zentao.sql b/db/zentao.sql index 81f470ad53..ce7e7eb4d8 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -584,7 +584,7 @@ CREATE TABLE IF NOT EXISTS `zt_deliverable` ( `name` varchar(255) NOT NULL, `module` varchar(30) NULL, `method` varchar(30) NULL, - `model` varchar(255) NULL, + `model` text NULL, `type` enum('doc','file') NULL DEFAULT 'file', `desc` text NULL, `files` varchar(255) NULL, From 2a9412d02e6d6e5ce71138bf0f395fdd40f636f5 Mon Sep 17 00:00:00 2001 From: wangyuting Date: Fri, 18 Apr 2025 14:45:56 +0800 Subject: [PATCH 042/136] * [task#141580,done,0.2h,0h] Fix back btn link error. --- lib/zin/wg/backbtn/v1.php | 3 ++- module/common/lang/menu.php | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/zin/wg/backbtn/v1.php b/lib/zin/wg/backbtn/v1.php index 2ea51e7215..0f67b0e291 100644 --- a/lib/zin/wg/backbtn/v1.php +++ b/lib/zin/wg/backbtn/v1.php @@ -97,7 +97,8 @@ class backBtn extends btn 'host' => 'host-browse,my-index', 'deploy' => 'deploy-browse', 'program' => 'program-browse,program-productview', - 'workflowgroup' => 'workflowgroup-project,workflowgroup-deliverable' + 'workflowgroup' => 'workflowgroup-project,workflowgroup-deliverable', + 'deliverable' => 'deliverable-browse' ); $props = parent::getProps(); diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php index 8d2217cec7..a409734595 100644 --- a/module/common/lang/menu.php +++ b/module/common/lang/menu.php @@ -783,6 +783,7 @@ $lang->navGroup->extension = 'admin'; $lang->navGroup->action = 'admin'; $lang->navGroup->convert = 'admin'; $lang->navGroup->stage = 'admin'; +$lang->navGroup->deliverable = 'admin'; $lang->navGroup->featureswitch = 'admin'; $lang->navGroup->importdata = 'admin'; $lang->navGroup->systemsetting = 'admin'; From 3e30ef340f2cdc89553dd06299f383b8618ee478 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Fri, 18 Apr 2025 06:51:01 +0000 Subject: [PATCH 043/136] * [unittest] add yaml. --- test/data/deliverable.yaml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 test/data/deliverable.yaml diff --git a/test/data/deliverable.yaml b/test/data/deliverable.yaml new file mode 100644 index 0000000000..ee40d120cc --- /dev/null +++ b/test/data/deliverable.yaml @@ -0,0 +1,34 @@ +title: table zt_deliverable +desc: "交付物" +author: Sun Guangming +version: "1.0" +fields: + - field: id + note: "ID" + range: 1-1000 + - field: name + fields: + - field: name1 + range: '交付物' + - field: name2 + range: 1-1000 + - field: module + range: project,execution + - field: method + range: create,close + - field: model + fields: + - field: model1 + range: product,project + postfix: "_" + - field: model2 + range: waterfall,scrum + postfix: "_" + - field: model3 + range: mix,request,design,dev,qa,release,review + - field: type + range: doc,file + - field: files + range: 1-10 + - field: desc + range: '交付物描述' \ No newline at end of file From 52626b24e71d714f181092ed3685669c46eb8287 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Fri, 18 Apr 2025 07:29:07 +0000 Subject: [PATCH 044/136] * [misc] add nav group. --- module/common/lang/menu.php | 1 + 1 file changed, 1 insertion(+) diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php index a409734595..357083b05b 100644 --- a/module/common/lang/menu.php +++ b/module/common/lang/menu.php @@ -797,6 +797,7 @@ $lang->navGroup->system = 'devops'; $lang->navGroup->serverroom = 'devops'; $lang->navGroup->holiday = 'admin'; $lang->navGroup->cache = 'admin'; +$lang->navGroup->deliverable = 'admin'; $lang->navGroup->aiapp = 'aiapp'; From c15f031d5cc6f2b37c4c510772a00b0e3fd1b814 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Fri, 18 Apr 2025 08:24:26 +0000 Subject: [PATCH 045/136] * [misc] remove unused code. --- module/common/lang/menu.php | 1 - 1 file changed, 1 deletion(-) diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php index 357083b05b..a409734595 100644 --- a/module/common/lang/menu.php +++ b/module/common/lang/menu.php @@ -797,7 +797,6 @@ $lang->navGroup->system = 'devops'; $lang->navGroup->serverroom = 'devops'; $lang->navGroup->holiday = 'admin'; $lang->navGroup->cache = 'admin'; -$lang->navGroup->deliverable = 'admin'; $lang->navGroup->aiapp = 'aiapp'; From 9085d63dbf736ccd5d687bd23512f1c94e0e6e0c Mon Sep 17 00:00:00 2001 From: sunguangming Date: Mon, 21 Apr 2025 07:24:27 +0000 Subject: [PATCH 046/136] * [task#142098,done,1h] finish task. --- module/common/lang/common.php | 3 ++ module/common/lang/de.php | 66 +++++++++++++++++---------------- module/common/lang/en.php | 66 +++++++++++++++++---------------- module/common/lang/fr.php | 66 +++++++++++++++++---------------- module/common/lang/zh-cn.php | 66 +++++++++++++++++---------------- module/group/lang/de.php | 3 ++ module/group/lang/en.php | 3 ++ module/group/lang/fr.php | 3 ++ module/group/lang/zh-cn.php | 2 + module/group/packagemanager.php | 21 +++++++++++ 10 files changed, 171 insertions(+), 128 deletions(-) diff --git a/module/common/lang/common.php b/module/common/lang/common.php index 96fc51023e..1c242060ad 100644 --- a/module/common/lang/common.php +++ b/module/common/lang/common.php @@ -108,6 +108,9 @@ $lang->deployment = new stdclass(); $lang->deliverable = new stdclass(); $lang->metric = new stdclass(); +$lang->projectDeliverable = new stdclass(); +$lang->executionDeliverable = new stdclass(); + $lang->ai = new stdclass(); $lang->aiapp = new stdclass(); diff --git a/module/common/lang/de.php b/module/common/lang/de.php index 7fe6806238..c46dcca65c 100644 --- a/module/common/lang/de.php +++ b/module/common/lang/de.php @@ -289,38 +289,40 @@ $lang->aiapp->common = 'AI'; $lang->product->system = 'Application'; $lang->configure->common = 'Configure'; -$lang->programstakeholder->common = 'Stakeholder'; -$lang->featureswitch->common = 'Features On/Off'; -$lang->importdata->common = 'Import data'; -$lang->systemsetting->common = 'System setting'; -$lang->staffmanage->common = 'User management'; -$lang->modelconfig->common = 'Pattern setting'; -$lang->featureconfig->common = 'Features config'; -$lang->doctemplate->common = 'Doc template'; -$lang->notifysetting->common = 'Notification'; -$lang->bidesign->common = 'BI design'; -$lang->personalsettings->common = 'Personal setting '; -$lang->projectsettings->common = 'Setting'; -$lang->dataaccess->common = 'Data permission'; -$lang->executiongantt->common = 'Gantt chart'; -$lang->executionkanban->common = 'Kanban'; -$lang->executionburn->common = 'Burndown chart'; -$lang->executioncfd->common = 'Cumulative Flow Diagram'; -$lang->executionstory->common = 'Story'; -$lang->executionqa->common = 'QA'; -$lang->executionsettings->common = 'Setting'; -$lang->generalcomment->common = 'Comment'; -$lang->generalping->common = 'Timeout prevention'; -$lang->generaltemplate->common = 'Template'; -$lang->generaleffort->common = 'General log'; -$lang->productsettings->common = 'Product setting'; -$lang->projectreview->common = 'Review'; -$lang->projecttrack->common = 'Matrix'; -$lang->projectqa->common = 'QA'; -$lang->holidayseason->common = 'Holiday'; -$lang->codereview->common = 'Review'; -$lang->repocode->common = 'Code'; -$lang->deliverable->common = 'Deliverable'; +$lang->programstakeholder->common = 'Stakeholder'; +$lang->featureswitch->common = 'Features On/Off'; +$lang->importdata->common = 'Import data'; +$lang->systemsetting->common = 'System setting'; +$lang->staffmanage->common = 'User management'; +$lang->modelconfig->common = 'Pattern setting'; +$lang->featureconfig->common = 'Features config'; +$lang->doctemplate->common = 'Doc template'; +$lang->notifysetting->common = 'Notification'; +$lang->bidesign->common = 'BI design'; +$lang->personalsettings->common = 'Personal setting '; +$lang->projectsettings->common = 'Setting'; +$lang->dataaccess->common = 'Data permission'; +$lang->executiongantt->common = 'Gantt chart'; +$lang->executionkanban->common = 'Kanban'; +$lang->executionburn->common = 'Burndown chart'; +$lang->executioncfd->common = 'Cumulative Flow Diagram'; +$lang->executionstory->common = 'Story'; +$lang->executionqa->common = 'QA'; +$lang->executionsettings->common = 'Setting'; +$lang->generalcomment->common = 'Comment'; +$lang->generalping->common = 'Timeout prevention'; +$lang->generaltemplate->common = 'Template'; +$lang->generaleffort->common = 'General log'; +$lang->productsettings->common = 'Product setting'; +$lang->projectreview->common = 'Review'; +$lang->projecttrack->common = 'Matrix'; +$lang->projectqa->common = 'QA'; +$lang->holidayseason->common = 'Holiday'; +$lang->codereview->common = 'Review'; +$lang->repocode->common = 'Code'; +$lang->deliverable->common = 'Deliverable'; +$lang->projectDeliverable->common = 'Project Deliverable'; +$lang->executionDeliverable->common = 'Execution Deliverable'; $lang->personnel->common = 'Member'; $lang->personnel->invest = 'Investment'; diff --git a/module/common/lang/en.php b/module/common/lang/en.php index cc24154a4e..2008ab8507 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -289,38 +289,40 @@ $lang->aiapp->common = 'AI'; $lang->product->system = 'Application'; $lang->configure->common = 'Configure'; -$lang->programstakeholder->common = 'Stakeholder'; -$lang->featureswitch->common = 'Features On/Off'; -$lang->importdata->common = 'Import data'; -$lang->systemsetting->common = 'System setting'; -$lang->staffmanage->common = 'User management'; -$lang->modelconfig->common = 'Pattern setting'; -$lang->featureconfig->common = 'Features config'; -$lang->doctemplate->common = 'Doc template'; -$lang->notifysetting->common = 'Notification'; -$lang->bidesign->common = 'BI design'; -$lang->personalsettings->common = 'Personal setting '; -$lang->projectsettings->common = 'Setting'; -$lang->dataaccess->common = 'Data permission'; -$lang->executiongantt->common = 'Gantt chart'; -$lang->executionkanban->common = 'Kanban'; -$lang->executionburn->common = 'Burndown chart'; -$lang->executioncfd->common = 'Cumulative Flow Diagram'; -$lang->executionstory->common = 'Story'; -$lang->executionqa->common = 'QA'; -$lang->executionsettings->common = 'Setting'; -$lang->generalcomment->common = 'Comment'; -$lang->generalping->common = 'Timeout prevention'; -$lang->generaltemplate->common = 'Template'; -$lang->generaleffort->common = 'General log'; -$lang->productsettings->common = 'Product setting'; -$lang->projectreview->common = 'Review'; -$lang->projecttrack->common = 'Matrix'; -$lang->projectqa->common = 'QA'; -$lang->holidayseason->common = 'Holiday'; -$lang->codereview->common = 'Review'; -$lang->repocode->common = 'Code'; -$lang->deliverable->common = 'Deliverable'; +$lang->programstakeholder->common = 'Stakeholder'; +$lang->featureswitch->common = 'Features On/Off'; +$lang->importdata->common = 'Import data'; +$lang->systemsetting->common = 'System setting'; +$lang->staffmanage->common = 'User management'; +$lang->modelconfig->common = 'Pattern setting'; +$lang->featureconfig->common = 'Features config'; +$lang->doctemplate->common = 'Doc template'; +$lang->notifysetting->common = 'Notification'; +$lang->bidesign->common = 'BI design'; +$lang->personalsettings->common = 'Personal setting '; +$lang->projectsettings->common = 'Setting'; +$lang->dataaccess->common = 'Data permission'; +$lang->executiongantt->common = 'Gantt chart'; +$lang->executionkanban->common = 'Kanban'; +$lang->executionburn->common = 'Burndown chart'; +$lang->executioncfd->common = 'Cumulative Flow Diagram'; +$lang->executionstory->common = 'Story'; +$lang->executionqa->common = 'QA'; +$lang->executionsettings->common = 'Setting'; +$lang->generalcomment->common = 'Comment'; +$lang->generalping->common = 'Timeout prevention'; +$lang->generaltemplate->common = 'Template'; +$lang->generaleffort->common = 'General log'; +$lang->productsettings->common = 'Product setting'; +$lang->projectreview->common = 'Review'; +$lang->projecttrack->common = 'Matrix'; +$lang->projectqa->common = 'QA'; +$lang->holidayseason->common = 'Holiday'; +$lang->codereview->common = 'Review'; +$lang->repocode->common = 'Code'; +$lang->deliverable->common = 'Deliverable'; +$lang->projectDeliverable->common = 'Project Deliverable'; +$lang->executionDeliverable->common = 'Execution Deliverable'; $lang->personnel->common = 'Member'; $lang->personnel->invest = 'Investment'; diff --git a/module/common/lang/fr.php b/module/common/lang/fr.php index 137b3f08dc..fe0936db33 100644 --- a/module/common/lang/fr.php +++ b/module/common/lang/fr.php @@ -289,38 +289,40 @@ $lang->aiapp->common = 'AI'; $lang->product->system = 'Application'; $lang->configure->common = 'Configure'; -$lang->programstakeholder->common = 'Stakeholder'; -$lang->featureswitch->common = 'Features On/Off'; -$lang->importdata->common = 'Import data'; -$lang->systemsetting->common = 'System setting'; -$lang->staffmanage->common = 'User management'; -$lang->modelconfig->common = 'Pattern setting'; -$lang->featureconfig->common = 'Features config'; -$lang->doctemplate->common = 'Doc template'; -$lang->notifysetting->common = 'Notification'; -$lang->bidesign->common = 'BI design'; -$lang->personalsettings->common = 'Personal setting '; -$lang->projectsettings->common = 'Setting'; -$lang->dataaccess->common = 'Data permission'; -$lang->executiongantt->common = 'Gantt chart'; -$lang->executionkanban->common = 'Kanban'; -$lang->executionburn->common = 'Burndown chart'; -$lang->executioncfd->common = 'Cumulative Flow Diagram'; -$lang->executionstory->common = 'Story'; -$lang->executionqa->common = 'QA'; -$lang->executionsettings->common = 'Setting'; -$lang->generalcomment->common = 'Comment'; -$lang->generalping->common = 'Timeout prevention'; -$lang->generaltemplate->common = 'Template'; -$lang->generaleffort->common = 'General log'; -$lang->productsettings->common = 'Product setting'; -$lang->projectreview->common = 'Review'; -$lang->projecttrack->common = 'Matrix'; -$lang->projectqa->common = 'QA'; -$lang->holidayseason->common = 'Holiday'; -$lang->codereview->common = 'Review'; -$lang->repocode->common = 'Code'; -$lang->deliverable->common = 'Deliverable'; +$lang->programstakeholder->common = 'Stakeholder'; +$lang->featureswitch->common = 'Features On/Off'; +$lang->importdata->common = 'Import data'; +$lang->systemsetting->common = 'System setting'; +$lang->staffmanage->common = 'User management'; +$lang->modelconfig->common = 'Pattern setting'; +$lang->featureconfig->common = 'Features config'; +$lang->doctemplate->common = 'Doc template'; +$lang->notifysetting->common = 'Notification'; +$lang->bidesign->common = 'BI design'; +$lang->personalsettings->common = 'Personal setting '; +$lang->projectsettings->common = 'Setting'; +$lang->dataaccess->common = 'Data permission'; +$lang->executiongantt->common = 'Gantt chart'; +$lang->executionkanban->common = 'Kanban'; +$lang->executionburn->common = 'Burndown chart'; +$lang->executioncfd->common = 'Cumulative Flow Diagram'; +$lang->executionstory->common = 'Story'; +$lang->executionqa->common = 'QA'; +$lang->executionsettings->common = 'Setting'; +$lang->generalcomment->common = 'Comment'; +$lang->generalping->common = 'Timeout prevention'; +$lang->generaltemplate->common = 'Template'; +$lang->generaleffort->common = 'General log'; +$lang->productsettings->common = 'Product setting'; +$lang->projectreview->common = 'Review'; +$lang->projecttrack->common = 'Matrix'; +$lang->projectqa->common = 'QA'; +$lang->holidayseason->common = 'Holiday'; +$lang->codereview->common = 'Review'; +$lang->repocode->common = 'Code'; +$lang->deliverable->common = 'Deliverable'; +$lang->projectDeliverable->common = 'Project Deliverable'; +$lang->executionDeliverable->common = 'Execution Deliverable'; $lang->personnel->common = 'Member'; $lang->personnel->invest = 'Investment'; diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index 73225eef14..c6b088a140 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -289,38 +289,40 @@ $lang->aiapp->common = 'AI'; $lang->product->system = '应用'; $lang->configure->common = '配置'; -$lang->programstakeholder->common = '干系人'; -$lang->featureswitch->common = '功能开关'; -$lang->importdata->common = '数据导入'; -$lang->systemsetting->common = '系统设置'; -$lang->staffmanage->common = '人员管理'; -$lang->modelconfig->common = '项目模型配置'; -$lang->featureconfig->common = '功能配置'; -$lang->doctemplate->common = '文档模板'; -$lang->notifysetting->common = '通知设置'; -$lang->bidesign->common = 'BI设计'; -$lang->personalsettings->common = '个人设置'; -$lang->projectsettings->common = '设置'; -$lang->dataaccess->common = '数据权限'; -$lang->executiongantt->common = '甘特图'; -$lang->executionkanban->common = '看板'; -$lang->executionburn->common = '燃尽图'; -$lang->executioncfd->common = '累积流图'; -$lang->executionstory->common = '研发需求'; -$lang->executionqa->common = '测试'; -$lang->executionsettings->common = '设置'; -$lang->generalcomment->common = '备注'; -$lang->generalping->common = '防超时'; -$lang->generaltemplate->common = '模板'; -$lang->generaleffort->common = '通用日志'; -$lang->productsettings->common = '产品设置'; -$lang->projectreview->common = '评审'; -$lang->projecttrack->common = '矩阵'; -$lang->projectqa->common = '测试'; -$lang->holidayseason->common = '节假日'; -$lang->codereview->common = '问题'; -$lang->repocode->common = '代码'; -$lang->deliverable->common = '交付物'; +$lang->programstakeholder->common = '干系人'; +$lang->featureswitch->common = '功能开关'; +$lang->importdata->common = '数据导入'; +$lang->systemsetting->common = '系统设置'; +$lang->staffmanage->common = '人员管理'; +$lang->modelconfig->common = '项目模型配置'; +$lang->featureconfig->common = '功能配置'; +$lang->doctemplate->common = '文档模板'; +$lang->notifysetting->common = '通知设置'; +$lang->bidesign->common = 'BI设计'; +$lang->personalsettings->common = '个人设置'; +$lang->projectsettings->common = '设置'; +$lang->dataaccess->common = '数据权限'; +$lang->executiongantt->common = '甘特图'; +$lang->executionkanban->common = '看板'; +$lang->executionburn->common = '燃尽图'; +$lang->executioncfd->common = '累积流图'; +$lang->executionstory->common = '研发需求'; +$lang->executionqa->common = '测试'; +$lang->executionsettings->common = '设置'; +$lang->generalcomment->common = '备注'; +$lang->generalping->common = '防超时'; +$lang->generaltemplate->common = '模板'; +$lang->generaleffort->common = '通用日志'; +$lang->productsettings->common = '产品设置'; +$lang->projectreview->common = '评审'; +$lang->projecttrack->common = '矩阵'; +$lang->projectqa->common = '测试'; +$lang->holidayseason->common = '节假日'; +$lang->codereview->common = '问题'; +$lang->repocode->common = '代码'; +$lang->deliverable->common = '交付物'; +$lang->projectDeliverable->common = '项目交付物'; +$lang->executionDeliverable->common = '执行交付物'; $lang->personnel->common = '人员'; $lang->personnel->invest = '投入人员'; diff --git a/module/group/lang/de.php b/module/group/lang/de.php index 14df894aea..895d7e089e 100644 --- a/module/group/lang/de.php +++ b/module/group/lang/de.php @@ -621,5 +621,8 @@ $lang->group->package->application = 'Manage Application'; $lang->group->package->component = 'Component'; $lang->group->package->browseRule = 'Browse Rule'; $lang->group->package->manageRule = 'Manage Rule'; +$lang->group->package->deliverable = 'Deliverable'; +$lang->group->package->executiondeliverable = 'Project Deliverable'; +$lang->group->package->projectdeliverable = 'Execution Deliverable'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/en.php b/module/group/lang/en.php index be5d540aa4..fa362f010b 100644 --- a/module/group/lang/en.php +++ b/module/group/lang/en.php @@ -621,5 +621,8 @@ $lang->group->package->application = 'Manage Application'; $lang->group->package->component = 'Component'; $lang->group->package->browseRule = 'Browse Rule'; $lang->group->package->manageRule = 'Manage Rule'; +$lang->group->package->deliverable = 'Deliverable'; +$lang->group->package->executiondeliverable = 'Project Deliverable'; +$lang->group->package->projectdeliverable = 'Execution Deliverable'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/fr.php b/module/group/lang/fr.php index e85ec66261..7abff4e670 100644 --- a/module/group/lang/fr.php +++ b/module/group/lang/fr.php @@ -621,5 +621,8 @@ $lang->group->package->application = 'Manage Application'; $lang->group->package->component = 'Component'; $lang->group->package->browseRule = 'Browse Rule'; $lang->group->package->manageRule = 'Manage Rule'; +$lang->group->package->deliverable = 'Deliverable'; +$lang->group->package->executiondeliverable = 'Project Deliverable'; +$lang->group->package->projectdeliverable = 'Execution Deliverable'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/zh-cn.php b/module/group/lang/zh-cn.php index f17ec55817..8bf467691a 100644 --- a/module/group/lang/zh-cn.php +++ b/module/group/lang/zh-cn.php @@ -621,5 +621,7 @@ $lang->group->package->application = '管理应用'; $lang->group->package->component = '组件'; $lang->group->package->browseRule = '浏览规则'; $lang->group->package->manageRule = '创建维护规则'; +$lang->group->package->executiondeliverable = '交付物'; +$lang->group->package->projectdeliverable = '交付物'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/packagemanager.php b/module/group/packagemanager.php index 1dc6c6e8ef..3f9c902885 100644 --- a/module/group/packagemanager.php +++ b/module/group/packagemanager.php @@ -65,6 +65,10 @@ $config->group->subset->project = new stdclass(); $config->group->subset->project->order = 170; $config->group->subset->project->nav = 'project'; +$config->group->subset->projectDeliverable = new stdclass(); +$config->group->subset->projectDeliverable->order = 171; +$config->group->subset->projectDeliverable->nav = 'project'; + $config->group->subset->projectplan = new stdclass(); $config->group->subset->projectplan->order = 180; $config->group->subset->projectplan->nav = 'project'; @@ -153,6 +157,10 @@ $config->group->subset->execution = new stdclass(); $config->group->subset->execution->order = 530; $config->group->subset->execution->nav = 'execution'; +$config->group->subset->executionDeliverable = new stdclass(); +$config->group->subset->executionDeliverable->order = 531; +$config->group->subset->executionDeliverable->nav = 'execution'; + $config->group->subset->task = new stdclass(); $config->group->subset->task->order = 540; $config->group->subset->task->nav = 'execution'; @@ -1047,6 +1055,12 @@ $config->group->package->projectWhitelist->privs['project-whitelist'] = ar $config->group->package->projectWhitelist->privs['project-addWhitelist'] = array('edition' => 'open,biz,max,ipd', 'vision' => 'rnd,lite', 'order' => 110, 'depend' => array('project-whitelist'), 'recommend' => array('project-unbindWhitelist')); $config->group->package->projectWhitelist->privs['project-unbindWhitelist'] = array('edition' => 'open,biz,max,ipd', 'vision' => 'rnd,lite', 'order' => 115, 'depend' => array('project-whitelist'), 'recommend' => array('project-addWhitelist')); +$config->group->package->projectDeliverable = new stdclass(); +$config->group->package->projectDeliverable->order = 5; +$config->group->package->projectDeliverable->subset = 'projectDeliverable'; +$config->group->package->projectDeliverable->privs = array(); +$config->group->package->projectDeliverable->privs['project-deliverable'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 10, 'depend' => array(), 'recommend' => array()); + $config->group->package->browseExecution = new stdclass(); $config->group->package->browseExecution->order = 5; $config->group->package->browseExecution->subset = 'execution'; @@ -1094,6 +1108,13 @@ $config->group->package->executionWhitelist->privs['execution-whitelist'] $config->group->package->executionWhitelist->privs['execution-addWhitelist'] = array('edition' => 'open,biz,max,ipd', 'vision' => 'rnd,lite', 'order' => 245, 'depend' => array('execution-whitelist'), 'recommend' => array('execution-unbindWhitelist')); $config->group->package->executionWhitelist->privs['execution-unbindWhitelist'] = array('edition' => 'open,biz,max,ipd', 'vision' => 'rnd,lite', 'order' => 250, 'depend' => array('execution-whitelist'), 'recommend' => array('execution-addWhitelist')); +$config->group->package->executionDeliverable = new stdclass(); +$config->group->package->executionDeliverable->order = 5; +$config->group->package->executionDeliverable->subset = 'executionDeliverable'; +$config->group->package->executionDeliverable->nav = 'execution'; +$config->group->package->executionDeliverable->privs = array(); +$config->group->package->executionDeliverable->privs['execution-deliverable'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 10, 'depend' => array(), 'recommend' => array()); + $config->group->package->gantt = new stdclass(); $config->group->package->gantt->order = 5; $config->group->package->gantt->subset = 'executionview'; From 070b77cf83f3ed105c6bdca4fd2b7ffe62a406c6 Mon Sep 17 00:00:00 2001 From: liyang Date: Mon, 21 Apr 2025 15:30:13 +0800 Subject: [PATCH 047/136] + [ci] fix lint pipeline. --- .gitfox/lint.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitfox/lint.yaml b/.gitfox/lint.yaml index f7fa3278f2..3b53ef8764 100644 --- a/.gitfox/lint.yaml +++ b/.gitfox/lint.yaml @@ -15,7 +15,7 @@ spec: container: image: hub.zentao.net/ci/alpine:3.19 script: - - SONAR_PROJECT_KEY=$(echo $CI_REPO_NAME | tr '/' ':') + - SONAR_PROJECT_KEY=$(echo $CI_REPO_NAME-$GITFOX_COMMIT_AUTHOR | tr '/' ':') - echo "export SONAR_PROJECT_KEY=$SONAR_PROJECT_KEY" >> $GITFOX_CUSTOM_ENV - name: 配置scanner type: run @@ -23,10 +23,10 @@ spec: container: image: hub.zentao.net/ci/git:2.45.2 script: - - git diff --name-only --diff-filter=d ${GITFOX_COMMIT_AFTER} ${GITFOX_COMMIT_BEFORE} | tee .changes + - git diff --name-only --diff-filter=d ${GITFOX_COMMIT_AFTER}${GITFOX_COMMIT_BEFORE} | tee .changes - | cat > sonar-project.properties < Date: Mon, 21 Apr 2025 07:41:50 +0000 Subject: [PATCH 048/136] * [task#142096,done,0.5h] finish task. --- module/group/packagemanager.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/module/group/packagemanager.php b/module/group/packagemanager.php index 3f9c902885..4c7ea4633f 100644 --- a/module/group/packagemanager.php +++ b/module/group/packagemanager.php @@ -3023,10 +3023,10 @@ $config->group->package->deliverable->order = 20; $config->group->package->deliverable->subset = 'modelconfig'; $config->group->package->deliverable->privs = array(); $config->group->package->deliverable->privs['deliverable-browse'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array(), 'recommend' => array()); -$config->group->package->deliverable->privs['deliverable-create'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 1, 'depend' => array(), 'recommend' => array()); -$config->group->package->deliverable->privs['deliverable-edit'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 2, 'depend' => array(), 'recommend' => array()); -$config->group->package->deliverable->privs['deliverable-delete'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 3, 'depend' => array(), 'recommend' => array()); -$config->group->package->deliverable->privs['deliverable-view'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 4, 'depend' => array(), 'recommend' => array()); +$config->group->package->deliverable->privs['deliverable-create'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 1, 'depend' => array('deliverable-browse'), 'recommend' => array()); +$config->group->package->deliverable->privs['deliverable-edit'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 2, 'depend' => array('deliverable-browse'), 'recommend' => array('deliverable-view', 'deliverable-browse')); +$config->group->package->deliverable->privs['deliverable-delete'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 3, 'depend' => array('deliverable-browse'), 'recommend' => array('deliverable-view', 'deliverable-browse')); +$config->group->package->deliverable->privs['deliverable-view'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 4, 'depend' => array('deliverable-browse'), 'recommend' => array()); $config->group->package->classify = new stdclass(); $config->group->package->classify->order = 30; From 7c791c07062c86178273d70ae2f2a7f20675de10 Mon Sep 17 00:00:00 2001 From: liyang Date: Tue, 22 Apr 2025 11:13:20 +0800 Subject: [PATCH 049/136] + [pipeline] fix unit test pipeline. --- .gitfox/unittestforcommitid.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitfox/unittestforcommitid.yaml b/.gitfox/unittestforcommitid.yaml index 12f108a6e2..b4fa664c76 100644 --- a/.gitfox/unittestforcommitid.yaml +++ b/.gitfox/unittestforcommitid.yaml @@ -26,8 +26,6 @@ spec: - docker buildx build --pull --push --platform linux/amd64 --build-arg VERSION=${ZENTAO_VERSION} --build-arg MIRROR=true -t hub.qc.oop.cc/zentao-ztf:${GITFOX_BUILD_NUMBER}-${GITFOX_COMMIT} -f misc/ci/Dockerfile.test . - name: unit test type: run - when: | - build.target == "main" spec: envs: MYSQL_INTERNAL: "true" From 0443d4e6e350c6357c7760cbfb3719359ad895a1 Mon Sep 17 00:00:00 2001 From: liyang Date: Tue, 22 Apr 2025 11:22:01 +0800 Subject: [PATCH 050/136] + [pipeline] fix unit test pipeline. --- .gitfox/unittestforcommitid.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitfox/unittestforcommitid.yaml b/.gitfox/unittestforcommitid.yaml index b4fa664c76..12f108a6e2 100644 --- a/.gitfox/unittestforcommitid.yaml +++ b/.gitfox/unittestforcommitid.yaml @@ -26,6 +26,8 @@ spec: - docker buildx build --pull --push --platform linux/amd64 --build-arg VERSION=${ZENTAO_VERSION} --build-arg MIRROR=true -t hub.qc.oop.cc/zentao-ztf:${GITFOX_BUILD_NUMBER}-${GITFOX_COMMIT} -f misc/ci/Dockerfile.test . - name: unit test type: run + when: | + build.target == "main" spec: envs: MYSQL_INTERNAL: "true" From b9b60bef510cf4190254a3184a565a78a66c8837 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 22 Apr 2025 00:47:11 +0000 Subject: [PATCH 051/136] * [misc] modify deliverable lang. --- module/group/lang/de.php | 5 ++--- module/group/lang/en.php | 5 ++--- module/group/lang/fr.php | 5 ++--- module/group/lang/zh-cn.php | 4 ++-- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/module/group/lang/de.php b/module/group/lang/de.php index 895d7e089e..8c14b1a702 100644 --- a/module/group/lang/de.php +++ b/module/group/lang/de.php @@ -621,8 +621,7 @@ $lang->group->package->application = 'Manage Application'; $lang->group->package->component = 'Component'; $lang->group->package->browseRule = 'Browse Rule'; $lang->group->package->manageRule = 'Manage Rule'; -$lang->group->package->deliverable = 'Deliverable'; -$lang->group->package->executiondeliverable = 'Project Deliverable'; -$lang->group->package->projectdeliverable = 'Execution Deliverable'; +$lang->group->package->executionDeliverable = 'Execution Deliverable'; +$lang->group->package->projectDeliverable = 'Project Deliverable'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/en.php b/module/group/lang/en.php index fa362f010b..2d6cb05ddb 100644 --- a/module/group/lang/en.php +++ b/module/group/lang/en.php @@ -621,8 +621,7 @@ $lang->group->package->application = 'Manage Application'; $lang->group->package->component = 'Component'; $lang->group->package->browseRule = 'Browse Rule'; $lang->group->package->manageRule = 'Manage Rule'; -$lang->group->package->deliverable = 'Deliverable'; -$lang->group->package->executiondeliverable = 'Project Deliverable'; -$lang->group->package->projectdeliverable = 'Execution Deliverable'; +$lang->group->package->executionDeliverable = 'Execution Deliverable'; +$lang->group->package->projectDeliverable = 'Project Deliverable'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/fr.php b/module/group/lang/fr.php index 7abff4e670..035195166c 100644 --- a/module/group/lang/fr.php +++ b/module/group/lang/fr.php @@ -621,8 +621,7 @@ $lang->group->package->application = 'Manage Application'; $lang->group->package->component = 'Component'; $lang->group->package->browseRule = 'Browse Rule'; $lang->group->package->manageRule = 'Manage Rule'; -$lang->group->package->deliverable = 'Deliverable'; -$lang->group->package->executiondeliverable = 'Project Deliverable'; -$lang->group->package->projectdeliverable = 'Execution Deliverable'; +$lang->group->package->executionDeliverable = 'Execution Deliverable'; +$lang->group->package->projectDeliverable = 'Project Deliverable'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/zh-cn.php b/module/group/lang/zh-cn.php index 8bf467691a..8bc71a8b77 100644 --- a/module/group/lang/zh-cn.php +++ b/module/group/lang/zh-cn.php @@ -621,7 +621,7 @@ $lang->group->package->application = '管理应用'; $lang->group->package->component = '组件'; $lang->group->package->browseRule = '浏览规则'; $lang->group->package->manageRule = '创建维护规则'; -$lang->group->package->executiondeliverable = '交付物'; -$lang->group->package->projectdeliverable = '交付物'; +$lang->group->package->executionDeliverable = '交付物'; +$lang->group->package->projectDeliverable = '交付物'; include (dirname(__FILE__) . '/resource.php'); From 6bfed6d519a837b5c024d64e95a25c91b6447f0e Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 22 Apr 2025 00:52:37 +0000 Subject: [PATCH 052/136] * [misc] code for priv package. --- module/group/packagemanager.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/group/packagemanager.php b/module/group/packagemanager.php index 4c7ea4633f..2b4f06e5d8 100644 --- a/module/group/packagemanager.php +++ b/module/group/packagemanager.php @@ -2586,7 +2586,7 @@ $config->group->package->workflowGroup = new stdclass(); $config->group->package->workflowGroup->order = 65; $config->group->package->workflowGroup->subset = 'workflow'; $config->group->package->workflowGroup->privs = array(); -$config->group->package->workflowGroup->privs['workflowgroup-product'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd,lite,or', 'order' => 5, 'depend' => array('workflow-browseFlow'), 'recommend' => array()); +$config->group->package->workflowGroup->privs['workflowgroup-product'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd,lite,or', 'order' => 5, 'depend' => array('workflow-browseFlow'), 'recommend' => array()); $config->group->package->workflowGroup->privs['workflowgroup-project'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd,lite,or', 'order' => 10, 'depend' => array('workflow-browseFlow'), 'recommend' => array()); $config->group->package->workflowGroup->privs['workflowgroup-create'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd,lite,or', 'order' => 15, 'depend' => array('workflow-browseFlow'), 'recommend' => array()); $config->group->package->workflowGroup->privs['workflowgroup-edit'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd,lite,or', 'order' => 20, 'depend' => array('workflow-browseFlow'), 'recommend' => array()); @@ -2599,7 +2599,7 @@ $config->group->package->workflowGroup->privs['workflowgroup-setExclusive'] = $config->group->package->workflowGroup->privs['workflowgroup-activateFlow'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd,lite,or', 'order' => 55, 'depend' => array('workflow-browseFlow'), 'recommend' => array()); $config->group->package->workflowGroup->privs['workflowgroup-deactivateFlow'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd,lite,or', 'order' => 60, 'depend' => array('workflow-browseFlow'), 'recommend' => array()); $config->group->package->workflowGroup->privs['workflowgroup-rule'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd,lite,or', 'order' => 65, 'depend' => array('workflow-browseFlow'), 'recommend' => array()); -$config->group->package->workflowGroup->privs['workflowgroup-deliverable'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 70, 'depend' => array('workflow-browseFlow'), 'recommend' => array()); +$config->group->package->workflowGroup->privs['workflowgroup-deliverable'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 70, 'depend' => array('workflowgroup-project'), 'recommend' => array()); $config->group->package->workflow = new stdclass(); $config->group->package->workflow->order = 5; From a1c4a850abcd6b46e1515ef319ecaab19e32c159 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 22 Apr 2025 02:53:36 +0000 Subject: [PATCH 053/136] * [task#142092,done,0.5h] add kanban menu. --- module/execution/tao.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/module/execution/tao.php b/module/execution/tao.php index 984290a0fd..279ea9f8a3 100644 --- a/module/execution/tao.php +++ b/module/execution/tao.php @@ -467,6 +467,11 @@ class executionTao extends executionModel $this->lang->execution->menu->kanban = array('link' => "{$this->lang->kanban->common}|execution|kanban|executionID=%s", 'subModule' => 'task', 'alias' => 'importtask'); $this->lang->execution->menu->CFD = array('link' => "{$this->lang->execution->CFD}|execution|cfd|executionID=%s"); $this->lang->execution->menu->build = array('link' => "{$this->lang->build->common}|execution|build|executionID=%s", 'alias' => 'bug', 'subModule' => 'projectbuild,build,bug'); + if(in_array($this->config->edition, array('max', 'ipd'))) + { + $this->lang->execution->menu->deliverable = array('link' => "{$this->lang->deliverable->common}|execution|deliverable|executionID=%s"); + $this->lang->execution->menuOrder[57] = 'deliverable'; + } $this->lang->execution->menu->settings = array('link' => "{$this->lang->settings}|execution|view|executionID=%s", 'subModule' => 'personnel', 'alias' => 'edit,manageproducts,team,whitelist,addwhitelist,managemembers', 'class' => 'dropdown dropdown-hover'); $this->lang->execution->dividerMenu = ''; From b2d793d3ae58aba675d398ecb9532a93f4319503 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 22 Apr 2025 03:01:58 +0000 Subject: [PATCH 054/136] * [unitest] add unit test. --- module/execution/test/tao/setkanbanmenu.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/module/execution/test/tao/setkanbanmenu.php b/module/execution/test/tao/setkanbanmenu.php index 782884b17c..d5499a2938 100644 --- a/module/execution/test/tao/setkanbanmenu.php +++ b/module/execution/test/tao/setkanbanmenu.php @@ -11,7 +11,17 @@ title=测试executionModel->setKanbanMenu(); timeout=0 cid=1 +- 测试替换看板执行的二级菜单第kanban条的link属性 @看板|execution|kanban|executionID=%s +- 查看交付物菜单第deliverable条的link属性 @交付物|execution|deliverable|executionID=%s +- 查看构建菜单第build条的link属性 @构建|execution|build|executionID=%s +- 查看累积流图菜单第CFD条的link属性 @累积流图|execution|cfd|executionID=%s +- 查看设置菜单第settings条的link属性 @设置|execution|view|executionID=%s + */ $executionTester = new executionTest(); -r($executionTester->setKanbanMenuTest()) && p('kanban:link') && e('看板|execution|kanban|executionID=%s'); // 测试替换看板执行的二级菜单 +r($executionTester->setKanbanMenuTest()) && p('kanban:link') && e('看板|execution|kanban|executionID=%s'); // 测试替换看板执行的二级菜单 +r($executionTester->setKanbanMenuTest()) && p('deliverable:link') && e('交付物|execution|deliverable|executionID=%s'); // 查看交付物菜单 +r($executionTester->setKanbanMenuTest()) && p('build:link') && e('构建|execution|build|executionID=%s'); // 查看构建菜单 +r($executionTester->setKanbanMenuTest()) && p('CFD:link') && e('累积流图|execution|cfd|executionID=%s'); // 查看累积流图菜单 +r($executionTester->setKanbanMenuTest()) && p('settings:link') && e('设置|execution|view|executionID=%s'); // 查看设置菜单 \ No newline at end of file From ee1bc3d4fcd3bac63689c182fe0f23118ec5156f Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 22 Apr 2025 03:05:28 +0000 Subject: [PATCH 055/136] * [bug] fix api bug. --- api/v1/entries/testresults.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v1/entries/testresults.php b/api/v1/entries/testresults.php index a915d33511..cc570e834b 100644 --- a/api/v1/entries/testresults.php +++ b/api/v1/entries/testresults.php @@ -84,7 +84,7 @@ class testresultsEntry extends entry $reals[$stepID] = $step->real; } $this->setPost('result', $results); - $this->setPost('reals', $reals); + $this->setPost('real', $reals); } $control->runCase($runID, $caseID, $version); From 922de3cc2fd12a400583a7026923c02c187c9e05 Mon Sep 17 00:00:00 2001 From: wangyuting Date: Tue, 22 Apr 2025 14:56:16 +0800 Subject: [PATCH 056/136] * [task#142095,doing,3h,5h] Add deliverable wg. --- lib/zin/func.php | 1 + lib/zin/wg/deliverable/js/v1.js | 37 ++++++++++++++++++++ lib/zin/wg/deliverable/v1.php | 61 +++++++++++++++++++++++++++++++++ module/doc/lang/de.php | 3 ++ module/doc/lang/en.php | 3 ++ module/doc/lang/fr.php | 3 ++ module/doc/lang/zh-cn.php | 3 ++ module/doc/model.php | 2 ++ 8 files changed, 113 insertions(+) create mode 100644 lib/zin/wg/deliverable/js/v1.js create mode 100644 lib/zin/wg/deliverable/v1.php diff --git a/lib/zin/func.php b/lib/zin/func.php index 9ad3894d70..ddd853660e 100644 --- a/lib/zin/func.php +++ b/lib/zin/func.php @@ -248,6 +248,7 @@ function pivotConfig(): pivotConfig {return createWg('pivotConfig', func_get_arg function iconPicker(): iconPicker {return createWg('iconPicker', func_get_args());} function relatedObjectList(): relatedObjectList {return createWg('relatedObjectList', func_get_args());} function taskAssignedTo(): taskAssignedTo {return createWg('taskAssignedTo', func_get_args());} +function deliverable(): deliverable {return createWg('deliverable', func_get_args());} if(is_dir(__DIR__ . DS . 'wg' . DS . 'schedule')) { diff --git a/lib/zin/wg/deliverable/js/v1.js b/lib/zin/wg/deliverable/js/v1.js new file mode 100644 index 0000000000..4dac0784d9 --- /dev/null +++ b/lib/zin/wg/deliverable/js/v1.js @@ -0,0 +1,37 @@ +/** + * 获取附件的操作按钮。 + * Get file actions. + */ +window.getFileActions = function(file, deliverable) +{ + let actions = []; + actions[0] = {icon: 'download', key: 'download'}; + actions[1] = {icon: 'edit', key: 'edit'}; + actions[2] = {icon: 'trash', key: 'delete'}; + return actions; +} + +/** + * 获取文档的操作按钮。 + * Get file actions. + */ +window.getDocActions = function(doc, deliverable) +{ + let actions = []; + actions[0] = {icon: 'eye', key: 'view'}; + actions[1] = {icon: 'edit', key: 'edit'}; + actions[2] = {icon: 'trash', key: 'delete'}; + return actions; +} + +/** + * 获取交付物的操作按钮。 + * Get deliverable actions. + */ +window.getDeliverableActions = function(deliverable) +{ + let actions = []; + actions[0] = {text: addFile, icon: 'file', key: 'selectFile'}; + actions[1] = {text: downloadTemplate, icon: 'download', key: 'downloadTemplate'}; + return actions; +} diff --git a/lib/zin/wg/deliverable/v1.php b/lib/zin/wg/deliverable/v1.php new file mode 100644 index 0000000000..99bdf23e8f --- /dev/null +++ b/lib/zin/wg/deliverable/v1.php @@ -0,0 +1,61 @@ +loadLang('doc'); + $app->loadLang('file'); + jsVar('addFile', $lang->doc->addFile); + jsVar('downloadTemplate', $lang->doc->downloadTemplate); + jsVar('deleteItem', $lang->delete); + + return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js'); + } + + /** + * 构建组件。 + * Build. + * + * @access protected + * @return zui + */ + protected function build(): zui + { + global $lang, $app; + $app->loadLang('doc'); + $app->loadLang('file'); + + return zui::deliverableList + ( + set::items($this->prop('items')), + set::docPicker(array('placeholder' => $lang->doc->selectDoc, 'items' => helper::createLink('doc', 'ajaxGetMineDocs', 'keyword={search}'))), + set::getFileActions(jsRaw('window.getFileActions')), + set::getDocActions(jsRaw('window.getDocActions')), + set::getEmptyActions(jsRaw('window.getDeliverableActions')) + ); + } +} diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 152c8969c8..fc5a5eede0 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -253,6 +253,8 @@ $lang->doc->uploadFormat = 'Upload Format'; $lang->doc->editedList = 'File editor'; $lang->doc->moveTo = 'Move to'; $lang->doc->notSupportExport = 'This document does not support export'; +$lang->doc->downloadTemplate = 'Download Template'; +$lang->doc->addFile = 'Add File'; $lang->doc->preview = 'Preview'; $lang->doc->insertTitle = 'Insert %s list'; @@ -439,6 +441,7 @@ $lang->doc->noCollectedDoc = 'Sie haben kein Dokument gesammelt.'; $lang->doc->errorEmptyLib = 'No data in document library.'; $lang->doc->confirmUpdateContent = 'You have a document that is not saved from last time. Do you want to continue editing it?'; $lang->doc->selectLibType = 'Please select a type of doc library.'; +$lang->doc->selectDoc = 'Please select a doc'; $lang->doc->noLibreOffice = 'You does not have access to office conversion settings!'; $lang->doc->errorParentChapter = 'The parent chapter cannot be its own chapter or sub chapter!'; $lang->doc->errorOthersCreated = 'There are documents created by others in this library. You cannot move it.'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index a471aa702b..fc4629880d 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -253,6 +253,8 @@ $lang->doc->uploadFormat = 'Upload Format'; $lang->doc->editedList = 'File editor'; $lang->doc->moveTo = 'Move to'; $lang->doc->notSupportExport = 'This document does not support export'; +$lang->doc->downloadTemplate = 'Download Template'; +$lang->doc->addFile = 'Add File'; $lang->doc->preview = 'Preview'; $lang->doc->insertTitle = 'Insert %s list'; @@ -439,6 +441,7 @@ $lang->doc->noCollectedDoc = 'You have not favorited any documents. $lang->doc->errorEmptyLib = 'No data in document library.'; $lang->doc->confirmUpdateContent = 'You have a document that is not saved from last time. Do you want to continue editing it?'; $lang->doc->selectLibType = 'Please select a type of doc library.'; +$lang->doc->selectDoc = 'Please select a doc'; $lang->doc->noLibreOffice = 'You does not have access to office conversion settings!'; $lang->doc->errorParentChapter = 'The parent chapter cannot be its own chapter or sub chapter!'; $lang->doc->errorOthersCreated = 'There are documents created by others in this library. You cannot move it.'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 75f3f69311..c193f1236d 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -253,6 +253,8 @@ $lang->doc->uploadFormat = 'Upload Format'; $lang->doc->editedList = 'File editor'; $lang->doc->moveTo = 'Move to'; $lang->doc->notSupportExport = 'This document does not support export'; +$lang->doc->downloadTemplate = 'Download Template'; +$lang->doc->addFile = 'Add File'; $lang->doc->preview = 'Preview'; $lang->doc->insertTitle = 'Insert %s list'; @@ -439,6 +441,7 @@ $lang->doc->noCollectedDoc = "Vous avez aucun document dans vos fav $lang->doc->errorEmptyLib = 'No data in document library.'; $lang->doc->confirmUpdateContent = 'You have a document that is not saved from last time. Do you want to continue editing it?'; $lang->doc->selectLibType = 'Please select a type of doc library.'; +$lang->doc->selectDoc = 'Please select a doc'; $lang->doc->noLibreOffice = 'You does not have access to office conversion settings!'; $lang->doc->errorParentChapter = 'The parent chapter cannot be its own chapter or sub chapter!'; $lang->doc->errorOthersCreated = 'There are documents created by others in this library. You cannot move it.'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 865ff290a0..12bdf2ca11 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -253,6 +253,8 @@ $lang->doc->uploadFormat = '上传格式'; $lang->doc->editedList = '文档编辑者'; $lang->doc->moveTo = '移动至'; $lang->doc->notSupportExport = '(此文档暂不支持导出)'; +$lang->doc->downloadTemplate = '下载模板'; +$lang->doc->addFile = '提交文件'; $lang->doc->preview = '预览'; $lang->doc->insertTitle = '插入%s列表'; @@ -439,6 +441,7 @@ $lang->doc->noCollectedDoc = '您还没有收藏任何文档。'; $lang->doc->errorEmptyLib = '文档库暂无数据。'; $lang->doc->confirmUpdateContent = '检查到您有未保存的文档内容,是否继续编辑?'; $lang->doc->selectLibType = '请选择文档库类型'; +$lang->doc->selectDoc = '请选择文档'; $lang->doc->noLibreOffice = '您还没有office转换设置访问权限!'; $lang->doc->errorParentChapter = '父章节不能是自身章节及子章节!'; $lang->doc->errorOthersCreated = '该库下其他人创建的文档暂不支持移动,是否确认移动?'; diff --git a/module/doc/model.php b/module/doc/model.php index 621aedf2f0..f51fdc75eb 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -966,6 +966,8 @@ class docModel extends model ->beginIF(in_array($browseType, array('all', 'bysearch')))->andWhere("(t1.status = 'normal' or (t1.status = 'draft' and t1.addedBy='{$this->app->user->account}'))")->fi() ->beginIF($browseType == 'draft')->andWhere('t1.status')->eq('draft')->andWhere('t1.addedBy')->eq($this->app->user->account)->fi() ->beginIF($browseType == 'bysearch')->andWhere($query)->fi() + ->beginIF($browseType == 'bykeyword')->andWhere('t1.status')->eq('normal')->fi() + ->beginIF($browseType == 'bykeyword' && $query)->andWhere('t1.title')->like("%$query%")->fi() ->beginIF(!empty($hasPrivDocIdList))->andWhere('t1.id')->in($hasPrivDocIdList)->fi() ->orderBy($orderBy) ->page($pager, 't1.id') From e7c45dcd860ddbf8fc57cb09148884ec7c97bfe3 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 22 Apr 2025 07:27:34 +0000 Subject: [PATCH 057/136] * [misc] hide deliverable menu in ipd. --- module/project/tao.php | 1 + 1 file changed, 1 insertion(+) diff --git a/module/project/tao.php b/module/project/tao.php index b941368228..3ba79f722f 100755 --- a/module/project/tao.php +++ b/module/project/tao.php @@ -1050,6 +1050,7 @@ class projectTao extends projectModel include $this->app->getModulePath('', 'execution') . 'lang/' . $this->app->getClientLang() . '.php'; + if($projectModel == 'ipd') unset($lang->waterfall->menu->other['dropMenu']->deliverable); $lang->execution->typeList['sprint'] = $executionCommonLang; } elseif($projectModel == 'kanban') From b8d0d8e739cb769e31790971f0f1561523cfd35e Mon Sep 17 00:00:00 2001 From: wangyuting Date: Tue, 22 Apr 2025 16:30:47 +0800 Subject: [PATCH 058/136] * [task#142095,doing,2h,2h] Optimize deliverable wg. --- lib/zin/wg/deliverable/js/v1.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/zin/wg/deliverable/js/v1.js b/lib/zin/wg/deliverable/js/v1.js index 4dac0784d9..94da238bc6 100644 --- a/lib/zin/wg/deliverable/js/v1.js +++ b/lib/zin/wg/deliverable/js/v1.js @@ -5,9 +5,8 @@ window.getFileActions = function(file, deliverable) { let actions = []; - actions[0] = {icon: 'download', key: 'download'}; - actions[1] = {icon: 'edit', key: 'edit'}; - actions[2] = {icon: 'trash', key: 'delete'}; + actions[0] = {icon: 'edit', key: 'rename'}; + actions[1] = {icon: 'trash', key: 'delete'}; return actions; } @@ -18,8 +17,8 @@ window.getFileActions = function(file, deliverable) window.getDocActions = function(doc, deliverable) { let actions = []; - actions[0] = {icon: 'eye', key: 'view'}; - actions[1] = {icon: 'edit', key: 'edit'}; + actions[0] = {icon: 'eye', key: 'view', url: $.createLink('doc', 'view', 'docID=' + doc.id)}; + actions[1] = {icon: 'edit', key: 'rename'}; actions[2] = {icon: 'trash', key: 'delete'}; return actions; } @@ -31,7 +30,7 @@ window.getDocActions = function(doc, deliverable) window.getDeliverableActions = function(deliverable) { let actions = []; - actions[0] = {text: addFile, icon: 'file', key: 'selectFile'}; - actions[1] = {text: downloadTemplate, icon: 'download', key: 'downloadTemplate'}; + actions[0] = {text: addFile, icon: 'file', key: 'selectFile'}; + if(deliverable.template > 0) actions[1] = {text: downloadTemplate, icon: 'download', key: 'downloadTemplate'}; return actions; } From 405fb38760312090bf3361b0c1507e850858dfae Mon Sep 17 00:00:00 2001 From: wangyuting Date: Tue, 22 Apr 2025 16:51:27 +0800 Subject: [PATCH 059/136] * Optimize code. --- lib/zin/wg/deliverable/js/v1.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/zin/wg/deliverable/js/v1.js b/lib/zin/wg/deliverable/js/v1.js index 94da238bc6..37fc55329e 100644 --- a/lib/zin/wg/deliverable/js/v1.js +++ b/lib/zin/wg/deliverable/js/v1.js @@ -5,8 +5,8 @@ window.getFileActions = function(file, deliverable) { let actions = []; - actions[0] = {icon: 'edit', key: 'rename'}; - actions[1] = {icon: 'trash', key: 'delete'}; + actions[0] = {icon: 'edit', key: 'rename'}; + actions[1] = {icon: 'trash', key: 'delete'}; return actions; } From 528d019b44912287ccfe86da8aad8f5cc2e93b0e Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 23 Apr 2025 00:52:01 +0000 Subject: [PATCH 060/136] * [task#142079,done,1h] code for task. --- db/update21.7.sql | 1 + db/zentao.sql | 1 + module/project/config/form.php | 7 ++++--- module/project/lang/de.php | 4 ++++ module/project/lang/en.php | 4 ++++ module/project/lang/fr.php | 4 ++++ module/project/lang/zh-cn.php | 4 ++++ module/project/ui/common.field.php | 3 ++- module/project/ui/edit.field.php | 3 ++- 9 files changed, 26 insertions(+), 5 deletions(-) diff --git a/db/update21.7.sql b/db/update21.7.sql index 19f6f5cd43..45f40ed443 100644 --- a/db/update21.7.sql +++ b/db/update21.7.sql @@ -16,3 +16,4 @@ CREATE TABLE IF NOT EXISTS `zt_deliverable` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ALTER TABLE `zt_workflowgroup` ADD COLUMN `deliverable` text NULL DEFAULT ''; +ALTER TABLE `zt_project` ADD `taskDateLimit` varchar(30) NOT NULL DEFAULT 'auto' AFTER `linkType`; \ No newline at end of file diff --git a/db/zentao.sql b/db/zentao.sql index ce7e7eb4d8..25e0548094 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -1608,6 +1608,7 @@ CREATE TABLE IF NOT EXISTS `zt_project` ( `parallel` mediumint(9) NOT NULL DEFAULT '0', `enabled` enum('on','off') NOT NULL DEFAULT 'on', `linkType` varchar(30) NOT NULL DEFAULT 'plan', + `taskDateLimit` varchar(30) NOT NULL DEFAULT 'auto', `colWidth` smallint(6) NOT NULL DEFAULT '264', `minColWidth` smallint(6) NOT NULL DEFAULT '200', `maxColWidth` smallint(6) NOT NULL DEFAULT '384', diff --git a/module/project/config/form.php b/module/project/config/form.php index 552dff39b9..09569b5b0d 100755 --- a/module/project/config/form.php +++ b/module/project/config/form.php @@ -32,9 +32,10 @@ $config->project->form->create['vision'] = array('type' => 'string', 'requir if(isset($this->config->setCode) && $this->config->setCode == 1) $config->project->form->create['code'] = array('type' => 'string', 'required' => false, 'filter' => 'trim'); $config->project->form->edit = $config->project->form->create; -$config->project->form->edit['products'] = array('type' => 'array', 'required' => false, 'default' => array()); -$config->project->form->edit['branch'] = array('type' => 'array', 'required' => false, 'default' => array()); -$config->project->form->edit['plans'] = array('type' => 'array', 'required' => false, 'default' => array()); +$config->project->form->edit['products'] = array('type' => 'array', 'required' => false, 'default' => array()); +$config->project->form->edit['branch'] = array('type' => 'array', 'required' => false, 'default' => array()); +$config->project->form->edit['plans'] = array('type' => 'array', 'required' => false, 'default' => array()); +$config->project->form->edit['taskDateLimit'] = array('type' => 'string', 'required' => false, 'default' => array()); unset($config->project->form->edit['hasProduct']); unset($config->project->form->edit['stageBy']); unset($config->project->form->edit['multiple']); diff --git a/module/project/lang/de.php b/module/project/lang/de.php index 6df33fa2d7..5b45c36755 100644 --- a/module/project/lang/de.php +++ b/module/project/lang/de.php @@ -218,6 +218,7 @@ $lang->project->plan = 'Plan'; $lang->project->createKanban = 'Create Kanban'; $lang->project->kanban = 'Kanban'; $lang->project->moreActions = 'More Actions'; +$lang->project->taskDateLimit = 'Task Date Limit'; /* Project Category. */ $lang->project->projectTypeList = array(); @@ -362,6 +363,9 @@ $lang->project->featureBar['group']['all'] = 'All Groups'; $lang->project->aclList['open'] = "Open (accessible with {$lang->projectCommon} view permissions)"; $lang->project->aclList['private'] = "Private (For the {$lang->projectCommon} leader, team members and stakeholders only)"; +$lang->project->taskDateLimitList['limit'] = "Limit the task date (the task start and end date must be within the parent task's date range)"; +$lang->project->taskDateLimitList['auto'] = "Auto extend the parent task date (the parent task will be automatically extended according to the task start and end date)"; + $lang->project->multipleList['1'] = 'Yes'; $lang->project->multipleList['0'] = 'No'; diff --git a/module/project/lang/en.php b/module/project/lang/en.php index 6df33fa2d7..5b45c36755 100644 --- a/module/project/lang/en.php +++ b/module/project/lang/en.php @@ -218,6 +218,7 @@ $lang->project->plan = 'Plan'; $lang->project->createKanban = 'Create Kanban'; $lang->project->kanban = 'Kanban'; $lang->project->moreActions = 'More Actions'; +$lang->project->taskDateLimit = 'Task Date Limit'; /* Project Category. */ $lang->project->projectTypeList = array(); @@ -362,6 +363,9 @@ $lang->project->featureBar['group']['all'] = 'All Groups'; $lang->project->aclList['open'] = "Open (accessible with {$lang->projectCommon} view permissions)"; $lang->project->aclList['private'] = "Private (For the {$lang->projectCommon} leader, team members and stakeholders only)"; +$lang->project->taskDateLimitList['limit'] = "Limit the task date (the task start and end date must be within the parent task's date range)"; +$lang->project->taskDateLimitList['auto'] = "Auto extend the parent task date (the parent task will be automatically extended according to the task start and end date)"; + $lang->project->multipleList['1'] = 'Yes'; $lang->project->multipleList['0'] = 'No'; diff --git a/module/project/lang/fr.php b/module/project/lang/fr.php index 6df33fa2d7..5b45c36755 100644 --- a/module/project/lang/fr.php +++ b/module/project/lang/fr.php @@ -218,6 +218,7 @@ $lang->project->plan = 'Plan'; $lang->project->createKanban = 'Create Kanban'; $lang->project->kanban = 'Kanban'; $lang->project->moreActions = 'More Actions'; +$lang->project->taskDateLimit = 'Task Date Limit'; /* Project Category. */ $lang->project->projectTypeList = array(); @@ -362,6 +363,9 @@ $lang->project->featureBar['group']['all'] = 'All Groups'; $lang->project->aclList['open'] = "Open (accessible with {$lang->projectCommon} view permissions)"; $lang->project->aclList['private'] = "Private (For the {$lang->projectCommon} leader, team members and stakeholders only)"; +$lang->project->taskDateLimitList['limit'] = "Limit the task date (the task start and end date must be within the parent task's date range)"; +$lang->project->taskDateLimitList['auto'] = "Auto extend the parent task date (the parent task will be automatically extended according to the task start and end date)"; + $lang->project->multipleList['1'] = 'Yes'; $lang->project->multipleList['0'] = 'No'; diff --git a/module/project/lang/zh-cn.php b/module/project/lang/zh-cn.php index 2d02dbd4d6..ac702b6f51 100644 --- a/module/project/lang/zh-cn.php +++ b/module/project/lang/zh-cn.php @@ -218,6 +218,7 @@ $lang->project->plan = '所属计划'; $lang->project->createKanban = '添加看板'; $lang->project->kanban = '项目看板'; $lang->project->moreActions = '更多操作'; +$lang->project->taskDateLimit = '任务时间限制'; /* Project Category. */ $lang->project->projectTypeList = array(); @@ -362,6 +363,9 @@ $lang->project->featureBar['group']['all'] = '浏览分组'; $lang->project->aclList['open'] = "公开 (有{$lang->projectCommon}视图权限即可访问)"; $lang->project->aclList['private'] = "私有 (只有{$lang->projectCommon}负责人、团队成员和干系人可访问)"; +$lang->project->taskDateLimitList['limit'] = "限制子任务时间(子任务起止时间必须在父任务的范围内)"; +$lang->project->taskDateLimitList['auto'] = "自动延长父任务时间(父任务根据子任务的起止时间自动延长)"; + $lang->project->multipleList['1'] = '是'; $lang->project->multipleList['0'] = '否'; diff --git a/module/project/ui/common.field.php b/module/project/ui/common.field.php index edb655bd7d..c57605e440 100644 --- a/module/project/ui/common.field.php +++ b/module/project/ui/common.field.php @@ -140,4 +140,5 @@ foreach($lang->story->typeList as $key => $text) $storyTypeList[] = array('text' => $text, 'value' => $key, 'disabled' => $disabled); } -$fields->field('storyType')->control(array('control' => 'checkBox', 'items' => $storyTypeList, 'name' => 'storyType[]')); +$fields->field('taskDateLimit')->control(array('control' => 'radioList', 'items' => $lang->project->taskDateLimitList, 'name' => 'taskDateLimit')); +$fields->field('storyType')->control(array('control' => 'checkBox', 'items' => $storyTypeList, 'name' => 'storyType[]')); \ No newline at end of file diff --git a/module/project/ui/edit.field.php b/module/project/ui/edit.field.php index eca3c1a67a..86785a8fa2 100644 --- a/module/project/ui/edit.field.php +++ b/module/project/ui/edit.field.php @@ -21,4 +21,5 @@ if(strpos($config->project->edit->requiredFields, 'budget') === false) $fields-> $fields->field('budget')->value(data('project.budget') !== null && data('project.budget') == 0 ? '' : data('project.budget')); $fields->field('acl')->control(array('control' => 'aclBox', 'aclItems' => data('project.parent') ? $lang->project->subAclList : $lang->project->aclList, 'aclValue' => data('project.acl'), 'whitelistLabel' => $lang->project->whitelist, 'userValue' => data('project.whitelist'))); -$fields->field('storyType')->width('full')->value(data('project.storyType')); +$fields->field('taskDateLimit')->width('full')->value(data('project.taskDateLimit')); +$fields->field('storyType')->width('full')->value(data('project.storyType')); \ No newline at end of file From 4be086900f26b7c692eb37d8680fc7fff424c39f Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 23 Apr 2025 01:05:22 +0000 Subject: [PATCH 061/136] * [misc] hide taskDateLimit in create. --- module/project/ui/create.field.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/project/ui/create.field.php b/module/project/ui/create.field.php index 4f36dc7bfd..349d20df25 100644 --- a/module/project/ui/create.field.php +++ b/module/project/ui/create.field.php @@ -60,6 +60,8 @@ $fields->field('acl') $fields->field('auth')->foldable()->value($copyProject ? data('copyProject.auth') : 'extend'); +$fields->field('taskDateLimit')->hidden(true)->value('auto'); + $storyType = in_array($model, array('waterfall', 'waterfallplus', 'ipd')) ? 'story,requirement' : 'story'; if($copyProject) $storyType = data('copyProject.storyType'); $fields->field('storyType')->foldable()->value($storyType); From 32e26b20182b2ff03406bd75e88ac52b14f8df86 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 23 Apr 2025 02:17:15 +0000 Subject: [PATCH 062/136] * [unittest] modify unit test, modify sql. --- db/update21.7.sql | 2 +- db/zentao.sql | 2 +- module/project/batchupdate.php | 103 ++++++++++++++++++ module/project/test/model/addplans.php | 13 ++- module/project/test/model/batchupdate.php | 6 +- .../test/model/getdisabledproducts.php | 9 +- .../yaml/getdisabledproducts/project.yaml | 2 +- 7 files changed, 129 insertions(+), 8 deletions(-) create mode 100755 module/project/batchupdate.php diff --git a/db/update21.7.sql b/db/update21.7.sql index 45f40ed443..fb96d5fb07 100644 --- a/db/update21.7.sql +++ b/db/update21.7.sql @@ -16,4 +16,4 @@ CREATE TABLE IF NOT EXISTS `zt_deliverable` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ALTER TABLE `zt_workflowgroup` ADD COLUMN `deliverable` text NULL DEFAULT ''; -ALTER TABLE `zt_project` ADD `taskDateLimit` varchar(30) NOT NULL DEFAULT 'auto' AFTER `linkType`; \ No newline at end of file +ALTER TABLE `zt_project` ADD `taskDateLimit` varchar(5) NOT NULL DEFAULT 'auto' AFTER `linkType`; \ No newline at end of file diff --git a/db/zentao.sql b/db/zentao.sql index 25e0548094..0795b0bcba 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -1608,7 +1608,7 @@ CREATE TABLE IF NOT EXISTS `zt_project` ( `parallel` mediumint(9) NOT NULL DEFAULT '0', `enabled` enum('on','off') NOT NULL DEFAULT 'on', `linkType` varchar(30) NOT NULL DEFAULT 'plan', - `taskDateLimit` varchar(30) NOT NULL DEFAULT 'auto', + `taskDateLimit` varchar(5) NOT NULL DEFAULT 'auto', `colWidth` smallint(6) NOT NULL DEFAULT '264', `minColWidth` smallint(6) NOT NULL DEFAULT '200', `maxColWidth` smallint(6) NOT NULL DEFAULT '384', diff --git a/module/project/batchupdate.php b/module/project/batchupdate.php new file mode 100755 index 0000000000..4ad7533a3a --- /dev/null +++ b/module/project/batchupdate.php @@ -0,0 +1,103 @@ +#!/usr/bin/env php +id->range('1-5'); +$project->project->range('0'); +$project->name->prefix("项目")->range('1-5'); +$project->code->prefix("project")->range('1-5'); +$project->model->range("scrum,waterfall,kanban"); +$project->auth->range("[]"); +$project->path->range("[]"); +$project->type->range("project"); +$project->grade->range("1"); +$project->days->range("1"); +$project->status->range("wait"); +$project->desc->range("[]"); +$project->budget->range("100000,200000"); +$project->budgetUnit->range("CNY"); +$project->percent->range("0-0"); + +$project->gen(4); + +/** + +title=测试taskModel->batchUpdate(); +timeout=0 +cid=1 + +- 查看被编辑了的项目数量 @3 +- 查看被编辑了的项目11详情 + - 第1条的name属性 @批量修改项目11 + - 第1条的parent属性 @1 + - 第1条的PM属性 @user10 + - 第1条的begin属性 @2022-02-08 + - 第1条的acl属性 @open +- 查看被编辑了的项目12详情 + - 第2条的name属性 @批量修改项目12 + - 第2条的parent属性 @2 + - 第2条的PM属性 @user11 + - 第2条的begin属性 @2022-03-05 + - 第2条的acl属性 @private +- 查看被编辑了的项目13详情 + - 第3条的name属性 @批量修改项目13 + - 第3条的parent属性 @3 + - 第3条的PM属性 @user13 + - 第3条的begin属性 @2022-02-19 + - 第3条的acl属性 @program +- 异常情况第message[end]条的0属性 @ID4『计划完成』应当大于『2023-02-19』。 + +*/ + +$project = new Project(); +$projectIdList = array(1, 2, 3); + +$data[1] = new stdClass(); +$data[1]->name = '批量修改项目11'; +$data[1]->parent = 1; +$data[1]->PM = 'user10'; +$data[1]->begin = '2022-02-08'; +$data[1]->end = '2022-04-13'; +$data[1]->days = 10; +$data[1]->acl = 'open'; + +$data[2] = new stdClass(); +$data[2]->name = '批量修改项目12'; +$data[2]->parent = 2; +$data[2]->PM = 'user11'; +$data[2]->begin = '2022-03-05'; +$data[2]->end = '2022-04-13'; +$data[2]->days = 10; +$data[2]->acl = 'private'; + +$data[3] = new stdClass(); +$data[3]->name = '批量修改项目13'; +$data[3]->parent = 3; +$data[3]->PM = 'user13'; +$data[3]->begin = '2022-02-19'; +$data[3]->end = '2022-04-13'; +$data[3]->days = 14; +$data[3]->acl = 'program'; + +$projects = $project->batchUpdate($data); + +r(count($projects)) && p() && e('3'); // 查看被编辑了的项目数量 +r($projects) && p('1:name,parent,PM,begin,acl') && e('批量修改项目11,1,user10,2022-02-08,open'); // 查看被编辑了的项目11详情 +r($projects) && p('2:name,parent,PM,begin,acl') && e('批量修改项目12,2,user11,2022-03-05,private'); // 查看被编辑了的项目12详情 +r($projects) && p('3:name,parent,PM,begin,acl') && e('批量修改项目13,3,user13,2022-02-19,program'); // 查看被编辑了的项目13详情 + +$data = array(); +$data[4] = new stdClass(); +$data[4]->name = '批量修改项目14'; +$data[4]->parent = 4; +$data[4]->PM = 'user14'; +$data[4]->begin = '2023-02-19'; +$data[4]->end = '2022-04-13'; +$data[4]->day = 14; +$data[4]->acl = 'program'; + +$projects = $project->batchUpdate($data); +r($projects) && p('message[end]:0') && e('ID4『计划完成』应当大于『2023-02-19』。'); // 异常情况 \ No newline at end of file diff --git a/module/project/test/model/addplans.php b/module/project/test/model/addplans.php index 7cab569203..5f9e6c3418 100755 --- a/module/project/test/model/addplans.php +++ b/module/project/test/model/addplans.php @@ -8,7 +8,9 @@ zenData('product')->gen(100); zenData('productplan')->gen(100); $storyTable = zenData('story'); $storyTable->status->range('active'); +$storyTable->version->range('1'); $storyTable->gen(100); +zenData('storyspec')->gen(100); zenData('planstory')->gen(100); zenData('projectstory')->gen(0); @@ -20,6 +22,15 @@ title=测试 projectModel::addPlans(); timeout=0 cid=1 +- 将计划1,4,7下的需求关联到项目13,查看关联后的需求数 @16 +- 将计划1,4,7下的需求关联到项目13,查看关联后的需求ID/产品ID + - 第3条的story属性 @4 + - 第3条的product属性 @1 +- 将计划2,5,10,13下的需求关联到项目11,查看关联后的需求数 @8 +- 将计划2,5,10,13下的需求关联到项目11,查看关联后的需求ID/产品ID + - 第0条的story属性 @13 + - 第0条的product属性 @4 + */ $project = new Project(); @@ -32,4 +43,4 @@ r($project->addPlansTest(13, $plan)) && p('3:story,product') && e('4,1'); // 将 $plan = array(); $plan[1] = array(2, 5, 10, 13); r(count($project->addPlansTest(11, $plan))) && p('') && e('8'); // 将计划2,5,10,13下的需求关联到项目11,查看关联后的需求数 -r($project->addPlansTest(11, $plan)) && p('0:story,product') && e('13,4'); // 将计划2,5,10,13下的需求关联到项目11,查看关联后的需求ID/产品ID +r($project->addPlansTest(11, $plan)) && p('0:story,product') && e('13,4'); // 将计划2,5,10,13下的需求关联到项目11,查看关联后的需求ID/产品ID \ No newline at end of file diff --git a/module/project/test/model/batchupdate.php b/module/project/test/model/batchupdate.php index 91824daaf1..876a7b9c96 100755 --- a/module/project/test/model/batchupdate.php +++ b/module/project/test/model/batchupdate.php @@ -40,7 +40,7 @@ $data[1]->parent = 1; $data[1]->PM = 'user10'; $data[1]->begin = '2022-02-08'; $data[1]->end = '2022-04-13'; -$data[1]->day = 10; +$data[1]->days = 10; $data[1]->acl = 'open'; $data[2] = new stdClass(); @@ -49,7 +49,7 @@ $data[2]->parent = 2; $data[2]->PM = 'user11'; $data[2]->begin = '2022-03-05'; $data[2]->end = '2022-04-13'; -$data[2]->day = 10; +$data[2]->days = 10; $data[2]->acl = 'private'; $data[3] = new stdClass(); @@ -58,7 +58,7 @@ $data[3]->parent = 3; $data[3]->PM = 'user13'; $data[3]->begin = '2022-02-19'; $data[3]->end = '2022-04-13'; -$data[3]->day = 14; +$data[3]->days = 14; $data[3]->acl = 'program'; $projects = $project->batchUpdate($data); diff --git a/module/project/test/model/getdisabledproducts.php b/module/project/test/model/getdisabledproducts.php index 2fd5c5cb4a..aa45dc5eb8 100644 --- a/module/project/test/model/getdisabledproducts.php +++ b/module/project/test/model/getdisabledproducts.php @@ -9,6 +9,13 @@ title=测试 projectModel->getDisabledProducts(); timeout=0 cid=1 +- 测试获取敏捷项目不可修改产品 @0 +- 测试获取以产品创建的瀑布项目不可修改产品属性2 @项目已经关联了该产品中的研发需求,不能取消关联,您可以取消关联研发需求后再操作。 +- 测试获取以产品创建的瀑布项目不可修改产品属性3 @该产品已经创建了阶段,如需解除与项目的关联,请删除已创建的阶段后再操作。 +- 测试获取以产品创建的瀑布项目不可修改产品属性4 @该产品已经创建了阶段并关联了研发需求,如需解除与项目的关联,请先解除研发需求的关联关系,然后删除已创建的阶段后再操作。 +- 测试获取以项目创建的瀑布项目不可修改产品属性5 @该产品的研发需求已经关联到了项目和执行中,请先解除研发需求与项目和执行的关联后再操作。 +- 测试获取以项目创建的瀑布项目不可修改产品属性6 @项目已经关联了该产品中的研发需求,不能取消关联,您可以取消关联研发需求后再操作。 + */ zenData('project')->loadYaml('project')->gen(10); @@ -24,4 +31,4 @@ r($projectTester->getDisabledProductsTest($projectIdList[1])) && p('2') && e(' r($projectTester->getDisabledProductsTest($projectIdList[2])) && p('3') && e('该产品已经创建了阶段,如需解除与项目的关联,请删除已创建的阶段后再操作。'); // 测试获取以产品创建的瀑布项目不可修改产品 r($projectTester->getDisabledProductsTest($projectIdList[3])) && p('4') && e('该产品已经创建了阶段并关联了研发需求,如需解除与项目的关联,请先解除研发需求的关联关系,然后删除已创建的阶段后再操作。'); // 测试获取以产品创建的瀑布项目不可修改产品 r($projectTester->getDisabledProductsTest($projectIdList[4])) && p('5') && e('该产品的研发需求已经关联到了项目和执行中,请先解除研发需求与项目和执行的关联后再操作。'); // 测试获取以项目创建的瀑布项目不可修改产品 -r($projectTester->getDisabledProductsTest($projectIdList[5])) && p('6') && e('项目已经关联了该产品中的研发需求,不能取消关联,您可以取消关联研发需求后再操作。'); // 测试获取以项目创建的瀑布项目不可修改产品 +r($projectTester->getDisabledProductsTest($projectIdList[5])) && p('6') && e('项目已经关联了该产品中的研发需求,不能取消关联,您可以取消关联研发需求后再操作。'); // 测试获取以项目创建的瀑布项目不可修改产品 \ No newline at end of file diff --git a/module/project/test/model/yaml/getdisabledproducts/project.yaml b/module/project/test/model/yaml/getdisabledproducts/project.yaml index 2cf2a1d34d..f1aaef5293 100644 --- a/module/project/test/model/yaml/getdisabledproducts/project.yaml +++ b/module/project/test/model/yaml/getdisabledproducts/project.yaml @@ -7,7 +7,7 @@ fields: - field: type range: project{6},stage{6} - field: stageBy - range: "product{4},project{2},[]{6}" + range: "product{4},project{2}" - field: project range: '0{6},3{2},4,5' - field: model From 1c5817773d2493c011acfe1b41eb4c517614b8fa Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 23 Apr 2025 02:18:47 +0000 Subject: [PATCH 063/136] * [unittest] modify unittest. --- module/project/test/tao/setmenubymodel.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/module/project/test/tao/setmenubymodel.php b/module/project/test/tao/setmenubymodel.php index 37648e686f..391d2b8b4d 100644 --- a/module/project/test/tao/setmenubymodel.php +++ b/module/project/test/tao/setmenubymodel.php @@ -9,8 +9,16 @@ su('admin'); /** title=测试 projectModel::setMenuByModel(); +timeout=0 cid=1 -pid=1 + +- 项目不存在的情况 @迭代 +- 项目不存在的情况 @迭代 +- 敏捷项目 @迭代 +- 融合敏捷项目 @迭代 +- 融合瀑布项目 @阶段 +- 瀑布项目 @阶段 +- 看板项目 @项目看板 */ @@ -22,4 +30,4 @@ r($projectTester->setMenuByModelTest('scrum')) && p() && e('迭代'); r($projectTester->setMenuByModelTest('agileplus')) && p() && e('迭代'); // 融合敏捷项目 r($projectTester->setMenuByModelTest('waterfall')) && p() && e('阶段'); // 融合瀑布项目 r($projectTester->setMenuByModelTest('waterfallplus')) && p() && e('阶段'); // 瀑布项目 -r($projectTester->setMenuByModelTest('kanban')) && p() && e('项目看板'); // 看板项目 +r($projectTester->setMenuByModelTest('kanban')) && p() && e('项目看板'); // 看板项目 \ No newline at end of file From 335eb2eec99a0c957ffd946effd03e9dc28e6c9b Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 23 Apr 2025 02:30:31 +0000 Subject: [PATCH 064/136] * [misc] move file. --- module/project/batchupdate.php | 103 ---------------------- module/project/test/model/batchupdate.php | 23 ++++- 2 files changed, 22 insertions(+), 104 deletions(-) delete mode 100755 module/project/batchupdate.php diff --git a/module/project/batchupdate.php b/module/project/batchupdate.php deleted file mode 100755 index 4ad7533a3a..0000000000 --- a/module/project/batchupdate.php +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env php -id->range('1-5'); -$project->project->range('0'); -$project->name->prefix("项目")->range('1-5'); -$project->code->prefix("project")->range('1-5'); -$project->model->range("scrum,waterfall,kanban"); -$project->auth->range("[]"); -$project->path->range("[]"); -$project->type->range("project"); -$project->grade->range("1"); -$project->days->range("1"); -$project->status->range("wait"); -$project->desc->range("[]"); -$project->budget->range("100000,200000"); -$project->budgetUnit->range("CNY"); -$project->percent->range("0-0"); - -$project->gen(4); - -/** - -title=测试taskModel->batchUpdate(); -timeout=0 -cid=1 - -- 查看被编辑了的项目数量 @3 -- 查看被编辑了的项目11详情 - - 第1条的name属性 @批量修改项目11 - - 第1条的parent属性 @1 - - 第1条的PM属性 @user10 - - 第1条的begin属性 @2022-02-08 - - 第1条的acl属性 @open -- 查看被编辑了的项目12详情 - - 第2条的name属性 @批量修改项目12 - - 第2条的parent属性 @2 - - 第2条的PM属性 @user11 - - 第2条的begin属性 @2022-03-05 - - 第2条的acl属性 @private -- 查看被编辑了的项目13详情 - - 第3条的name属性 @批量修改项目13 - - 第3条的parent属性 @3 - - 第3条的PM属性 @user13 - - 第3条的begin属性 @2022-02-19 - - 第3条的acl属性 @program -- 异常情况第message[end]条的0属性 @ID4『计划完成』应当大于『2023-02-19』。 - -*/ - -$project = new Project(); -$projectIdList = array(1, 2, 3); - -$data[1] = new stdClass(); -$data[1]->name = '批量修改项目11'; -$data[1]->parent = 1; -$data[1]->PM = 'user10'; -$data[1]->begin = '2022-02-08'; -$data[1]->end = '2022-04-13'; -$data[1]->days = 10; -$data[1]->acl = 'open'; - -$data[2] = new stdClass(); -$data[2]->name = '批量修改项目12'; -$data[2]->parent = 2; -$data[2]->PM = 'user11'; -$data[2]->begin = '2022-03-05'; -$data[2]->end = '2022-04-13'; -$data[2]->days = 10; -$data[2]->acl = 'private'; - -$data[3] = new stdClass(); -$data[3]->name = '批量修改项目13'; -$data[3]->parent = 3; -$data[3]->PM = 'user13'; -$data[3]->begin = '2022-02-19'; -$data[3]->end = '2022-04-13'; -$data[3]->days = 14; -$data[3]->acl = 'program'; - -$projects = $project->batchUpdate($data); - -r(count($projects)) && p() && e('3'); // 查看被编辑了的项目数量 -r($projects) && p('1:name,parent,PM,begin,acl') && e('批量修改项目11,1,user10,2022-02-08,open'); // 查看被编辑了的项目11详情 -r($projects) && p('2:name,parent,PM,begin,acl') && e('批量修改项目12,2,user11,2022-03-05,private'); // 查看被编辑了的项目12详情 -r($projects) && p('3:name,parent,PM,begin,acl') && e('批量修改项目13,3,user13,2022-02-19,program'); // 查看被编辑了的项目13详情 - -$data = array(); -$data[4] = new stdClass(); -$data[4]->name = '批量修改项目14'; -$data[4]->parent = 4; -$data[4]->PM = 'user14'; -$data[4]->begin = '2023-02-19'; -$data[4]->end = '2022-04-13'; -$data[4]->day = 14; -$data[4]->acl = 'program'; - -$projects = $project->batchUpdate($data); -r($projects) && p('message[end]:0') && e('ID4『计划完成』应当大于『2023-02-19』。'); // 异常情况 \ No newline at end of file diff --git a/module/project/test/model/batchupdate.php b/module/project/test/model/batchupdate.php index 876a7b9c96..4ad7533a3a 100755 --- a/module/project/test/model/batchupdate.php +++ b/module/project/test/model/batchupdate.php @@ -29,6 +29,27 @@ title=测试taskModel->batchUpdate(); timeout=0 cid=1 +- 查看被编辑了的项目数量 @3 +- 查看被编辑了的项目11详情 + - 第1条的name属性 @批量修改项目11 + - 第1条的parent属性 @1 + - 第1条的PM属性 @user10 + - 第1条的begin属性 @2022-02-08 + - 第1条的acl属性 @open +- 查看被编辑了的项目12详情 + - 第2条的name属性 @批量修改项目12 + - 第2条的parent属性 @2 + - 第2条的PM属性 @user11 + - 第2条的begin属性 @2022-03-05 + - 第2条的acl属性 @private +- 查看被编辑了的项目13详情 + - 第3条的name属性 @批量修改项目13 + - 第3条的parent属性 @3 + - 第3条的PM属性 @user13 + - 第3条的begin属性 @2022-02-19 + - 第3条的acl属性 @program +- 异常情况第message[end]条的0属性 @ID4『计划完成』应当大于『2023-02-19』。 + */ $project = new Project(); @@ -79,4 +100,4 @@ $data[4]->day = 14; $data[4]->acl = 'program'; $projects = $project->batchUpdate($data); -r($projects) && p('message[end]:0') && e('ID4『计划完成』应当大于『2023-02-19』。'); // 异常情况 +r($projects) && p('message[end]:0') && e('ID4『计划完成』应当大于『2023-02-19』。'); // 异常情况 \ No newline at end of file From c7c47d40462c1057efed62be1083f4dceb0fa32c Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 23 Apr 2025 06:30:32 +0000 Subject: [PATCH 065/136] * [task#142095,doing,0.5h] add canDownload. --- lib/zin/wg/deliverable/js/v1.js | 2 +- lib/zin/wg/deliverable/v1.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/zin/wg/deliverable/js/v1.js b/lib/zin/wg/deliverable/js/v1.js index 37fc55329e..56b49c015a 100644 --- a/lib/zin/wg/deliverable/js/v1.js +++ b/lib/zin/wg/deliverable/js/v1.js @@ -31,6 +31,6 @@ window.getDeliverableActions = function(deliverable) { let actions = []; actions[0] = {text: addFile, icon: 'file', key: 'selectFile'}; - if(deliverable.template > 0) actions[1] = {text: downloadTemplate, icon: 'download', key: 'downloadTemplate'}; + if(deliverable.template > 0 && canDownload) actions[1] = {text: downloadTemplate, icon: 'download', key: 'downloadTemplate', url: $.createLink('file', 'download', 'templateID=' + deliverable.template), target: '_blank'}; return actions; } diff --git a/lib/zin/wg/deliverable/v1.php b/lib/zin/wg/deliverable/v1.php index 99bdf23e8f..c79c50c752 100644 --- a/lib/zin/wg/deliverable/v1.php +++ b/lib/zin/wg/deliverable/v1.php @@ -32,6 +32,7 @@ class deliverable extends wg jsVar('addFile', $lang->doc->addFile); jsVar('downloadTemplate', $lang->doc->downloadTemplate); jsVar('deleteItem', $lang->delete); + jsVar('canDownload', hasPriv('file', 'download')); return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js'); } From e7d53bbaeb10fc2259630d54226ef6a01c8cd7e0 Mon Sep 17 00:00:00 2001 From: wangyuting Date: Wed, 23 Apr 2025 14:19:10 +0800 Subject: [PATCH 066/136] * [task#142082,done,3h,0h] Add deliverable column project table. --- db/update21.7.sql | 5 +++-- module/file/model.php | 9 +++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/db/update21.7.sql b/db/update21.7.sql index fb96d5fb07..a36cd6e432 100644 --- a/db/update21.7.sql +++ b/db/update21.7.sql @@ -15,5 +15,6 @@ CREATE TABLE IF NOT EXISTS `zt_deliverable` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -ALTER TABLE `zt_workflowgroup` ADD COLUMN `deliverable` text NULL DEFAULT ''; -ALTER TABLE `zt_project` ADD `taskDateLimit` varchar(5) NOT NULL DEFAULT 'auto' AFTER `linkType`; \ No newline at end of file +ALTER TABLE `zt_workflowgroup` ADD COLUMN `deliverable` text NULL DEFAULT '' AFTER `editedDate`; +ALTER TABLE `zt_project` ADD COLUMN `taskDateLimit` varchar(5) NOT NULL DEFAULT 'auto' AFTER `linkType`; +ALTER TABLE `zt_project` ADD COLUMN `deliverable` text NULL DEFAULT '' AFTER `maxColWidth`; diff --git a/module/file/model.php b/module/file/model.php index 611e7bc02e..5b4732dedc 100755 --- a/module/file/model.php +++ b/module/file/model.php @@ -185,7 +185,7 @@ class fileModel extends model $file['objectID'] = $objectID; $file['addedBy'] = $this->app->user->account; $file['addedDate'] = $now; - $file['extra'] = $extra; + if($extra) $file['extra'] = $extra; unset($file['tmpname']); $this->dao->insert(TABLE_FILE)->data($file)->exec(); $fileTitles[$this->dao->lastInsertId()] = $file['title']; @@ -279,6 +279,7 @@ class fileModel extends model $file['title'] = $purifier->purify($file['title']); $file['size'] = $size[$id]; $file['tmpname'] = $tmp_name[$id]; + $file['extra'] = !empty($extra[$id]) ? $extra[$id] : ''; $files[] = $file; } } @@ -464,12 +465,12 @@ class fileModel extends model /** * Set path name of the uploaded file to be saved. * - * @param int $fileID - * @param string $extension + * @param string|int $fileID + * @param string $extension * @access public * @return string */ - public function setPathName(int $fileID, string $extension): string + public function setPathName(string|int $fileID, string $extension): string { $sessionID = session_id(); $randString = substr($sessionID, mt_rand(0, strlen($sessionID) - 5), 3); From 6c49241883f97ac3270d1894fbc76fe80524c0fc Mon Sep 17 00:00:00 2001 From: wangyuting Date: Wed, 23 Apr 2025 15:44:21 +0800 Subject: [PATCH 067/136] * [task#142082,done,1h,0h] Finish copy doc. --- module/doc/model.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/doc/model.php b/module/doc/model.php index f51fdc75eb..022114ec7c 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -1563,12 +1563,12 @@ class docModel extends model } $files = $this->loadModel('file')->getUpload(); - if($doc->type == 'attachment' && (empty($files) || isset($files['name']))) return dao::$errors['files'] = sprintf($this->lang->error->notempty, $this->lang->doc->uploadFile); + if($doc->type == 'attachment' && empty($doc->copy) && (empty($files) || isset($files['name']))) return dao::$errors['files'] = sprintf($this->lang->error->notempty, $this->lang->doc->uploadFile); $doc->draft = $isDraft ? $docContent->content : ''; $doc->vision = $this->config->vision; $doc->version = $isDraft ? 0 : 1; - $this->dao->insert(TABLE_DOC)->data($doc, 'content')->autoCheck()->batchCheck($requiredFields, 'notempty')->exec(); + $this->dao->insert(TABLE_DOC)->data($doc, 'content,copy')->autoCheck()->batchCheck($requiredFields, 'notempty')->exec(); if(dao::isError()) return false; $docID = $this->dao->lastInsertID(); From 88e82ae53cdcd91da5217aba2c333398e4fc62f1 Mon Sep 17 00:00:00 2001 From: wangyuting Date: Fri, 25 Apr 2025 09:39:03 +0800 Subject: [PATCH 068/136] * [bug#61958,done,0.2h,0h] Fix search doc by keyword error. --- module/doc/model.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/module/doc/model.php b/module/doc/model.php index 022114ec7c..b81249c7ff 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -939,7 +939,7 @@ class docModel extends model */ public function getMySpaceDocs(string $type, string $browseType, string $query = '', string $orderBy = 'id_desc', object $pager = null): array { - if(!in_array($type, array('view', 'collect', 'createdby', 'editedby'))) return array(); + if(!in_array($type, array('all', 'view', 'collect', 'createdby', 'editedby'))) return array(); $allLibs = $this->getLibs('all'); $allLibIDList = array_keys($allLibs); @@ -988,6 +988,8 @@ class docModel extends model ->beginIF(!common::hasPriv('doc', 'teamSpace'))->andWhere('t2.type')->ne('custom')->fi() ->beginIF($browseType == 'draft')->andWhere('t1.status')->eq('draft')->andWhere('t1.addedBy')->eq($this->app->user->account)->fi() ->beginIF($browseType == 'bysearch')->andWhere($query)->fi() + ->beginIF($browseType == 'bykeyword')->andWhere('t1.status')->eq('normal')->fi() + ->beginIF($browseType == 'bykeyword' && $query)->andWhere('t1.title')->like("%$query%")->fi() ->beginIF(!empty($hasPrivDocIdList))->andWhere('t1.id')->in($hasPrivDocIdList)->fi() ->orderBy($orderBy) ->page($pager) From d0794cda5797fc3b4a9a8f5d0339cb21b05f556b Mon Sep 17 00:00:00 2001 From: sunguangming Date: Fri, 25 Apr 2025 05:23:43 +0000 Subject: [PATCH 069/136] * [task#142094,doing,0.5h] add form name to deliverable. --- lib/zin/wg/deliverable/v1.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/zin/wg/deliverable/v1.php b/lib/zin/wg/deliverable/v1.php index c79c50c752..77f74c4617 100644 --- a/lib/zin/wg/deliverable/v1.php +++ b/lib/zin/wg/deliverable/v1.php @@ -13,7 +13,8 @@ class deliverable extends wg */ protected static array $defineProps = array ( - 'items: array', // 交付物条目。 + 'items: array', // 交付物条目。 + 'formName: string' // 表单名称。 ); /** @@ -50,8 +51,11 @@ class deliverable extends wg $app->loadLang('doc'); $app->loadLang('file'); + $formName = $this->prop('formName') ? $this->prop('formName') : 'deliverable'; + return zui::deliverableList ( + set::formName($formName), set::items($this->prop('items')), set::docPicker(array('placeholder' => $lang->doc->selectDoc, 'items' => helper::createLink('doc', 'ajaxGetMineDocs', 'keyword={search}'))), set::getFileActions(jsRaw('window.getFileActions')), From b168c762b412acecddba1191fbc3a841856a350f Mon Sep 17 00:00:00 2001 From: wangyidong Date: Fri, 25 Apr 2025 11:59:01 +0800 Subject: [PATCH 070/136] * [perf story #73251] Prompt for child task for estStarted and deadline fields by parent. --- module/task/js/batchcreate.ui.js | 35 +++--- module/task/js/batchedit.ui.js | 77 ++++++++----- module/task/js/create.ui.js | 39 ++++--- module/task/js/edit.ui.js | 44 +++++--- module/task/lang/zh-cn.php | 2 + module/task/model.php | 2 +- module/task/ui/batchedit.html.php | 3 + module/task/ui/edit.html.php | 3 + module/task/zen.php | 179 ++++++++++++++++++++---------- 9 files changed, 237 insertions(+), 147 deletions(-) diff --git a/module/task/js/batchcreate.ui.js b/module/task/js/batchcreate.ui.js index 92b17bf40d..a54e59a7b2 100644 --- a/module/task/js/batchcreate.ui.js +++ b/module/task/js/batchcreate.ui.js @@ -161,32 +161,24 @@ function checkBatchEstStartedAndDeadline(event) const estStarted = $currentRow.find('[name^=estStarted]').val(); const deadline = $currentRow.find('[name^=deadline]').val(); + const $estStartedTd = $currentRow.find('td[data-name=estStarted]'); + $estStartedTd.find('.date-tip').remove(); if(field == 'estStarted' && estStarted.length > 0 && parentEstStarted.length > 0 && estStarted < parentEstStarted) { - const $estStartedTd = $currentRow.find('td[data-name=estStarted]'); - if($estStartedTd.find('.date-tip').length == 0 || $estStartedTd.find('.date-tip .form-tip').length > 0) - { - $estStartedTd.find('.date-tip').remove(); - - let $datetip = $('
'); - $datetip.append('
' + overParentEstStartedLang + '' + ignoreLang + '
'); - $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); - $estStartedTd.append($datetip); - } + let $datetip = $('
'); + $datetip.append('
' + overParentEstStartedLang + '' + ignoreLang + '
'); + $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); + $estStartedTd.append($datetip); } + const $deadlineTd = $currentRow.find('td[data-name=deadline]'); + $deadlineTd.find('.date-tip').remove(); if(field == 'deadline' && deadline.length > 0 && parentDeadline.length > 0 && deadline > parentDeadline) { - const $deadlineTd = $currentRow.find('td[data-name=deadline]'); - if($deadlineTd.find('.date-tip').length == 0 || $deadlineTd.find('.date-tip .form-tip').length > 0) - { - $deadlineTd.find('.date-tip').remove(); - - let $datetip = $('
'); - $datetip.append('
' + overParentDeadlineLang + '' + ignoreLang + '
'); - $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); - $deadlineTd.append($datetip); - } + let $datetip = $('
'); + $datetip.append('
' + overParentDeadlineLang + '' + ignoreLang + '
'); + $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); + $deadlineTd.append($datetip); } } @@ -281,6 +273,9 @@ window.handleRenderRow = function($row, index) const $preAssignedTo = $prevRow.find('input[name^=assignedTo]').zui('picker'); if($preAssignedTo != undefined) $assignedTo.render({items: $preAssignedTo.options.items}); }) + + $row.find('[data-name=estStarted]').find('[id^=estStarted]').on('inited', function(e, info) { info[0].render({disabled: parentEstStarted == ''}); }) + $row.find('[data-name=deadline]').find('[id^=deadline]').on('inited', function(e, info) { info[0].render({disabled: parentDeadline == ''}); }) }; $(function() diff --git a/module/task/js/batchedit.ui.js b/module/task/js/batchedit.ui.js index 4193418ff6..880e3ab488 100644 --- a/module/task/js/batchedit.ui.js +++ b/module/task/js/batchedit.ui.js @@ -8,6 +8,8 @@ window.renderRowData = function($row, index, row) members[teamAccount] = users[teamAccount]; }); + $row.attr('data-parent', row.parent); + let taskMembers = []; if(row.mode != '' && teams[row.id] != undefined) { @@ -26,10 +28,7 @@ window.renderRowData = function($row, index, row) const taskUsers = []; let disabled = false; $row.find('.form-batch-input[data-name="assignedTo"]').empty(); - if(teams[row.id] != undefined && ((row.mode == 'linear' && row.status != 'done') || taskMembers[currentUser] == undefined)) - { - disabled = true; - } + if(teams[row.id] != undefined && ((row.mode == 'linear' && row.status != 'done') || taskMembers[currentUser] == undefined)) disabled = true; if(row.status == 'closed') disabled = true; if(row.assignedTo && taskMembers[row.assignedTo] == undefined) taskMembers[row.assignedTo] = users[row.assignedTo]; @@ -173,51 +172,71 @@ window.statusChange = function(event) function checkBatchEstStartedAndDeadline(event) { - if(parentTasks.length == 0) return true; - const $currentRow = $(event.target).closest('tr'); const taskID = $currentRow.find('[name^=id]').val(); const parentID = tasks[taskID].parent; - if(typeof parentTasks[parentID] == 'undefined' || !parentTasks[parentID]) return true; - const parentTask = parentTasks[parentID]; const field = $(event.target).closest('.form-batch-control').data('name'); const estStarted = $currentRow.find('[name^=estStarted]').val(); const deadline = $currentRow.find('[name^=deadline]').val(); + const parentTask = parentTasks[parentID] ? parentTasks[parentID] : {estStarted: '', deadline: ''}; if(field == 'estStarted') { - let parentEstStarted = typeof tasks[parentID] == 'undefined' || $(event.target).closest('tbody').find('[name="estStarted[' + parentID + ']"]').length == 0 ? parentTask.estStarted : $(event.target).closest('tbody').find('[name="estStarted[' + parentID + ']"]').val(); - if(estStarted.length > 0 && parentEstStarted.length > 0 && estStarted < parentEstStarted) - { - const $estStartedTd = $currentRow.find('td[data-name=estStarted]'); - if($estStartedTd.find('.date-tip').length == 0 || $estStartedTd.find('.date-tip .form-tip').length > 0) - { - $estStartedTd.find('.date-tip').remove(); + const $estStartedTd = $currentRow.find('td[data-name=estStarted]'); + $estStartedTd.find('.date-tip').remove(); - let $datetip = $('
'); - $datetip.append('
' + overParentEstStartedLang.replace('%s', parentEstStarted) + '' + ignoreLang + '
'); - $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); - $estStartedTd.append($datetip); + if(estStarted.length > 0) + { + let $datetip = $('
'); + let parentEstStarted = typeof tasks[parentID] == 'undefined' || $(event.target).closest('tbody').find('[name="estStarted[' + parentID + ']"]').length == 0 ? parentTask.estStarted : $(event.target).closest('tbody').find('[name="estStarted[' + parentID + ']"]').val(); + if(parentEstStarted.length > 0 && estStarted < parentEstStarted) + { + $datetip.append('
' + overParentEstStartedLang.replace('%s', parentEstStarted) + '' + ignoreLang + '
'); + $datetip.off('click', '.ignore-parent').on('click', '.ignore-parent', function(e){ignoreTip(e)}); } + + let childEstStarted = childrenDateLimit[taskID] ? childrenDateLimit[taskID].estStarted : ''; + $(event.target).closest('tbody').find('tr[data-parent="' + taskID + '"]').find('[name^=estStarted]').each(function() + { + if(childEstStarted.length == 0 || ($(this).val().length > 0 && $(this).val() < childEstStarted)) childEstStarted = $(this).val(); + }); + if(childEstStarted.length > 0 && estStarted > childEstStarted) + { + $datetip.append('
' + overChildEstStartedLang.replace('%s', childEstStarted) + '' + ignoreLang + '
'); + $datetip.off('click', '.ignore-child').on('click', '.ignore-child', function(e){ignoreTip(e)}); + } + $estStartedTd.append($datetip); } } if(field == 'deadline') { - let parentDeadline = typeof tasks[parentID] == 'undefined' || $(event.target).closest('tbody').find('[name="deadline[' + parentID + ']"]').length == 0 ? parentTask.deadline : $(event.target).closest('tbody').find('[name="deadline[' + parentID + ']"]').val(); - if(deadline.length > 0 && parentDeadline.length > 0 && deadline > parentDeadline) - { - const $deadlineTd = $currentRow.find('td[data-name=deadline]'); - if($deadlineTd.find('.date-tip').length == 0 || $deadlineTd.find('.date-tip .form-tip').length > 0) - { - $deadlineTd.find('.date-tip').remove(); + const $deadlineTd = $currentRow.find('td[data-name=deadline]'); + $deadlineTd.find('.date-tip').remove(); - let $datetip = $('
'); - $datetip.append('
' + overParentDeadlineLang.replace('%s', parentDeadline) + '' + ignoreLang + '
'); + if(deadline.length > 0) + { + let $datetip = $('
'); + + let parentDeadline = typeof tasks[parentID] == 'undefined' || $(event.target).closest('tbody').find('[name="deadline[' + parentID + ']"]').length == 0 ? parentTask.deadline : $(event.target).closest('tbody').find('[name="deadline[' + parentID + ']"]').val(); + if(parentDeadline.length > 0 && deadline > parentDeadline) + { + $datetip.append('
' + overParentDeadlineLang.replace('%s', parentDeadline) + '' + ignoreLang + '
'); $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); - $deadlineTd.append($datetip); } + + let childDeadline = childrenDateLimit[taskID] ? childrenDateLimit[taskID].deadline : ''; + $(event.target).closest('tbody').find('tr[data-parent="' + taskID + '"]').find('[name^=deadline]').each(function() + { + if(childDeadline.length == 0 || ($(this).val().length > 0 && $(this).val() > childDeadline)) childDeadline = $(this).val(); + }); + if(childDeadline.length > 0 && deadline > childDeadline) + { + $datetip.append('
' + overChildDeadlineLang.replace('%s', childDeadline) + '' + ignoreLang + '
'); + $datetip.off('click', '.ignore-child').on('click', '.ignore-child', function(e){ignoreTip(e)}); + } + $deadlineTd.append($datetip); } } } diff --git a/module/task/js/create.ui.js b/module/task/js/create.ui.js index d4e59bb2b4..da7408f032 100644 --- a/module/task/js/create.ui.js +++ b/module/task/js/create.ui.js @@ -672,31 +672,30 @@ window.checkEstStartedAndDeadline = function(event) const $deadline = $form.find('[name=deadline]'); const deadline = $deadline.val(); + const $estStartedDiv = $estStarted.closest('.form-group'); + if(field == 'estStarted') $estStartedDiv.find('.date-tip').remove(); if(field == 'estStarted' && estStarted.length > 0 && parentEstStarted.length > 0 && estStarted < parentEstStarted) { - const $estStartedDiv = $estStarted.closest('.form-group'); - if($estStartedDiv.find('.date-tip').length == 0 || $estStartedDiv.find('.date-tip .form-tip').length > 0) - { - $estStartedDiv.find('.date-tip').remove(); - - let $datetip = $('
'); - $datetip.append('
' + overParentEstStartedLang + '' + ignoreLang + '
'); - $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); - $estStartedDiv.append($datetip); - } + let $datetip = $('
'); + $datetip.append('
' + overParentEstStartedLang + '' + ignoreLang + '
'); + $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); + $estStartedDiv.append($datetip); } + const $deadlineDiv = $deadline.closest('.form-group'); + if(field == 'deadline') $deadlineDiv.find('.date-tip').remove(); if(field == 'deadline' && deadline.length > 0 && parentDeadline.length > 0 && deadline > parentDeadline) { - const $deadlineDiv = $deadline.closest('.form-group'); - if($deadlineDiv.find('.date-tip').length == 0 || $deadlineDiv.find('.date-tip .form-tip').length > 0) - { - $deadlineDiv.find('.date-tip').remove(); - - let $datetip = $('
'); - $datetip.append('
' + overParentDeadlineLang + '' + ignoreLang + '
'); - $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); - $deadlineDiv.append($datetip); - } + let $datetip = $('
'); + $datetip.append('
' + overParentDeadlineLang + '' + ignoreLang + '
'); + $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); + $deadlineDiv.append($datetip); } + + let $estStartedPicker = $estStarted.zui('datePicker'); + let $deadlinePicker = $deadline.zui('datePicker'); + $estStartedPicker.render({disabled: parentEstStarted == ''}); + $deadlinePicker.render({disabled: parentDeadline == ''}); + if(parentEstStarted == '') $estStartedPicker.$.setValue(''); + if(parentDeadline == '') $deadlinePicker.$.setValue(''); } diff --git a/module/task/js/edit.ui.js b/module/task/js/edit.ui.js index 1cf5ce55be..cf0b4eee5f 100644 --- a/module/task/js/edit.ui.js +++ b/module/task/js/edit.ui.js @@ -432,31 +432,39 @@ function checkEstStartedAndDeadline(event) const $deadline = $form.find('[name=deadline]'); const deadline = $deadline.val(); - if(field == 'estStarted' && estStarted.length > 0 && parentEstStarted.length > 0 && estStarted < parentEstStarted) + const $estStartedDiv = $estStarted.closest('.form-group'); + if(field == 'estStarted' && estStarted.length > 0) { - const $estStartedDiv = $estStarted.closest('.form-group'); - if($estStartedDiv.find('.date-tip').length == 0 || $estStartedDiv.find('.date-tip .form-tip').length > 0) + $estStartedDiv.find('.date-tip').remove(); + let $datetip = $('
'); + if(parentEstStarted.length > 0 && estStarted < parentEstStarted) { - $estStartedDiv.find('.date-tip').remove(); - - let $datetip = $('
'); - $datetip.append('
' + overParentEstStartedLang + '' + ignoreLang + '
'); - $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); - $estStartedDiv.append($datetip); + $datetip.append('
' + overParentEstStartedLang + '' + ignoreLang + '
'); + $datetip.off('click', '.ignore-parent').on('click', '.ignore-parent', function (e) { ignoreTip(e) }); } + if(childDateLimit['estStarted'].length > 0 && estStarted > childDateLimit['estStarted']) + { + $datetip.append('
' + overChildEstStartedLang + '' + ignoreLang + '
'); + $datetip.off('click', '.ignore-child').on('click', '.ignore-child', function (e) { ignoreTip(e) }); + } + $estStartedDiv.append($datetip); } - if(field == 'deadline' && deadline.length > 0 && parentDeadline.length > 0 && deadline > parentDeadline) + const $deadlineDiv = $deadline.closest('.form-group'); + if(field == 'deadline' && deadline.length > 0) { - const $deadlineDiv = $deadline.closest('.form-group'); - if($deadlineDiv.find('.date-tip').length == 0 || $deadlineDiv.find('.date-tip .form-tip').length > 0) + $deadlineDiv.find('.date-tip').remove(); + let $datetip = $('
'); + if(parentDeadline.length > 0 && deadline > parentDeadline) { - $deadlineDiv.find('.date-tip').remove(); - - let $datetip = $('
'); - $datetip.append('
' + overParentDeadlineLang + '' + ignoreLang + '
'); - $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); - $deadlineDiv.append($datetip); + $datetip.append('
' + overParentDeadlineLang + '' + ignoreLang + '
'); + $datetip.off('click', '.ignore-parent').on('click', '.ignore-parent', function (e) { ignoreTip(e) }); } + if(childDateLimit['deadline'].length > 0 && deadline > childDateLimit['deadline']) + { + $datetip.append('
' + overChildDeadlineLang + '' + ignoreLang + '
'); + $datetip.off('click', '.ignore-child').on('click', '.ignore-child', function (e) { ignoreTip(e) }); + } + $deadlineDiv.append($datetip); } } diff --git a/module/task/lang/zh-cn.php b/module/task/lang/zh-cn.php index d09ef454f5..164a921461 100755 --- a/module/task/lang/zh-cn.php +++ b/module/task/lang/zh-cn.php @@ -437,6 +437,8 @@ $lang->task->overEsEndDate = '已超出%s计划结束时间,请先修改%s $lang->task->overParentEsStarted = '任务的预计开始日期小于了父任务的预计开始日期:%s'; $lang->task->overParentDeadline = '任务的截止日期大于了父任务的截止日期:%s'; +$lang->task->overChildEstStarted = '存在子任务的预计开始日期小于了该任务的预计开始日期:%s'; +$lang->task->overChildDeadline = '存在子任务的截止日期超出了该任务的截止日期:%s'; $lang->task->disabledHint = new stdclass(); $lang->task->disabledHint->assignedConfirmStoryChange = '只有指派人才能确认变更'; diff --git a/module/task/model.php b/module/task/model.php index 1bee5f95b4..88afbdef3e 100755 --- a/module/task/model.php +++ b/module/task/model.php @@ -3724,7 +3724,7 @@ class taskModel extends model */ public function getChildTasksByList(array $taskIdList): array|false { - $childTasks = $this->dao->select('id,parent')->from(TABLE_TASK)->where('parent')->in($taskIdList)->andWhere('deleted')->eq('0')->fetchGroup('parent', 'id'); + $childTasks = $this->dao->select('id,parent,path,estStarted,deadline')->from(TABLE_TASK)->where('parent')->in($taskIdList)->andWhere('deleted')->eq('0')->fetchGroup('parent', 'id'); $nonStoryChildTasks = $this->dao->select('id,parent')->from(TABLE_TASK)->where('parent')->in($taskIdList)->andWhere('story')->eq('0')->andWhere('deleted')->eq('0')->fetchGroup('parent', 'id'); return array($childTasks, $nonStoryChildTasks); } diff --git a/module/task/ui/batchedit.html.php b/module/task/ui/batchedit.html.php index 86b24479ba..3714abb646 100644 --- a/module/task/ui/batchedit.html.php +++ b/module/task/ui/batchedit.html.php @@ -27,6 +27,7 @@ jsVar('moduleGroup', $moduleGroup); jsVar('executionID', $executionID); jsVar('childTasks', $childTasks); jsVar('nonStoryChildTasks', $nonStoryChildTasks); +jsVar('childrenDateLimit', $childrenDateLimit); jsVar('tasks', $tasks); jsVar('noPauseStatusList', $noPauseStatusList); jsVar('stories', $stories); @@ -37,6 +38,8 @@ jsVar('noSprintPairs', $noSprintPairs); jsVar('ignoreLang', $lang->project->ignore); jsVar('overParentEstStartedLang', $lang->task->overParentEsStarted); jsVar('overParentDeadlineLang', $lang->task->overParentDeadline); +jsVar('overChildEstStartedLang', $lang->task->overChildEstStarted); +jsVar('overChildDeadlineLang', $lang->task->overChildDeadline); jsVar('manageTeamMemberText', $lang->execution->manageTeamMember); /* ====== Define the page structure with zin widgets ====== */ diff --git a/module/task/ui/edit.html.php b/module/task/ui/edit.html.php index 7335ac6a22..835bb9a23f 100644 --- a/module/task/ui/edit.html.php +++ b/module/task/ui/edit.html.php @@ -34,9 +34,12 @@ jsVar('leftNotEmpty', sprintf($lang->error->gt, $lang->task->left, '0')); jsVar('requiredFields', $config->task->edit->requiredFields); jsVar('+parentEstStarted', !empty($parentTask) ? $parentTask->estStarted : ''); jsVar('+parentDeadline', !empty($parentTask) ? $parentTask->deadline : ''); +jsVar('childDateLimit', $childDateLimit); jsVar('ignoreLang', $lang->project->ignore); jsVar('+overParentEstStartedLang', !empty($parentTask) ? sprintf($lang->task->overParentEsStarted, $parentTask->estStarted) : ''); jsVar('+overParentDeadlineLang', !empty($parentTask) ? sprintf($lang->task->overParentDeadline, $parentTask->deadline) : ''); +jsVar('+overChildEstStartedLang', sprintf($lang->task->overChildEstStarted, $childDateLimit['estStarted'])); +jsVar('+overChildDeadlineLang', sprintf($lang->task->overChildDeadline, $childDateLimit['deadline'])); $confirmSyncTip = ''; if(!empty($syncChildren) && !empty($task->children)) $confirmSyncTip = sprintf($lang->task->syncStoryToChildrenTip, 'ID' . implode(', ID', $syncChildren)); diff --git a/module/task/zen.php b/module/task/zen.php index 5a64a353ab..5664fe4993 100644 --- a/module/task/zen.php +++ b/module/task/zen.php @@ -247,6 +247,18 @@ class taskZen extends task } list($childTasks, $nonStoryChildTasks) = $this->task->getChildTasksByList(array_keys($tasks)); + $childrenDateLimit = array(); + foreach($childTasks as $parent => $children) + { + $childDateLimit = array('estStarted' => '', 'deadline' => ''); + foreach($children as $child) + { + if(!helper::isZeroDate($child->estStarted) && (empty($childDateLimit['estStarted']) || $childDateLimit['estStarted'] > $child->estStarted)) $childDateLimit['estStarted'] = $child->estStarted; + if(!helper::isZeroDate($child->deadline) && (empty($childDateLimit['deadline']) || $childDateLimit['deadline'] < $child->deadline)) $childDateLimit['deadline'] = $child->deadline; + } + $childrenDateLimit[$parent] = $childDateLimit; + } + $storyPairs = $this->story->getExecutionStoryPairs($executionID, 0, 'all', '', 'full', 'active', 'story', false);; $storyList = $this->story->getByList(array_keys($storyPairs)); $stories = array(); @@ -268,6 +280,7 @@ class taskZen extends task $this->view->moduleGroup = $moduleGroup; $this->view->childTasks = $childTasks; $this->view->nonStoryChildTasks = $nonStoryChildTasks; + $this->view->childrenDateLimit = $childrenDateLimit; $this->view->stories = $stories; $this->view->parentTasks = $this->task->getByIdList($parentTaskIdList); $this->view->noSprintPairs = $this->loadModel('project')->getProjectExecutionPairs(); @@ -301,7 +314,7 @@ class taskZen extends task $executions = !empty($task->project) ? $this->execution->getByProject($task->project, 'all', 0, true) : array(); /* Get task members. */ - $taskMembers = array(); + $taskMembers = $this->view->members; if(!empty($task->team)) { foreach($task->members as $teamAccount) @@ -310,10 +323,6 @@ class taskZen extends task $taskMembers[$teamAccount] = $this->view->members[$teamAccount]; } } - else - { - $taskMembers = $this->view->members; - } /* Get execution stories. */ $moduleID = $task->module; @@ -324,29 +333,33 @@ class taskZen extends task } $stories = $this->story->getExecutionStoryPairs($this->view->execution->id, 0, 'all', $moduleID, 'full', 'active', 'story', false); - $syncChildren = array(); + $syncChildren = array(); + $childDateLimit = array('estStarted' => '', 'deadline' => ''); if(!empty($task->children)) { foreach($task->children as $child) { if(empty($child->story)) $syncChildren[] = $child->id; + if(!helper::isZeroDate($child->estStarted) && (empty($childDateLimit['estStarted']) || $childDateLimit['estStarted'] > $child->estStarted)) $childDateLimit['estStarted'] = $child->estStarted; + if(!helper::isZeroDate($child->deadline) && (empty($childDateLimit['deadline']) || $childDateLimit['deadline'] < $child->deadline)) $childDateLimit['deadline'] = $child->deadline; } } if($this->view->execution->multiple) $manageLink = common::hasPriv('execution', 'manageMembers') ? $this->createLink('execution', 'manageMembers', "execution={$this->view->execution->id}") : ''; if(!$this->view->execution->multiple) $manageLink = common::hasPriv('project', 'manageMembers') ? $this->createLink('project', 'manageMembers', "projectID={$this->view->execution->project}") : ''; - $this->view->title = $this->lang->task->edit . 'TASK' . $this->lang->hyphen . $this->view->task->name; - $this->view->stories = $this->story->addGradeLabel($stories); - $this->view->tasks = $tasks; - $this->view->taskMembers = $taskMembers; - $this->view->users = $this->loadModel('user')->getPairs('nodeleted|noclosed', "{$task->openedBy},{$task->canceledBy},{$task->closedBy}"); - $this->view->showAllModule = isset($this->config->execution->task->allModule) ? $this->config->execution->task->allModule : ''; - $this->view->modules = $this->tree->getTaskOptionMenu($task->execution, 0, $this->view->showAllModule ? 'allModule' : ''); - $this->view->executions = $executions; - $this->view->syncChildren = $syncChildren; - $this->view->parentTask = !empty($task->parent) ? $this->task->getById($task->parent) : null; - $this->view->manageLink = $manageLink; + $this->view->title = $this->lang->task->edit . 'TASK' . $this->lang->hyphen . $this->view->task->name; + $this->view->stories = $this->story->addGradeLabel($stories); + $this->view->tasks = $tasks; + $this->view->taskMembers = $taskMembers; + $this->view->users = $this->loadModel('user')->getPairs('nodeleted|noclosed', "{$task->openedBy},{$task->canceledBy},{$task->closedBy}"); + $this->view->showAllModule = isset($this->config->execution->task->allModule) ? $this->config->execution->task->allModule : ''; + $this->view->modules = $this->tree->getTaskOptionMenu($task->execution, 0, $this->view->showAllModule ? 'allModule' : ''); + $this->view->executions = $executions; + $this->view->syncChildren = $syncChildren; + $this->view->childDateLimit = $childDateLimit; + $this->view->parentTask = !empty($task->parent) ? $this->task->getById($task->parent) : null; + $this->view->manageLink = $manageLink; $this->display(); } @@ -558,12 +571,13 @@ class taskZen extends task ->stripTags($this->config->task->editor->edit['id'], $this->config->allowedTags) ->get(); + $project = $this->loadModel('project')->fetchById($oldTask->project); + $parents = $this->getParentEstStartedAndDeadline(array($task->parent)); + $this->checkLegallyDate($task, $project->taskDateLimit == 'limit', isset($parents[$task->parent]) ? $parents[$task->parent] : null); + $team = $this->post->team ? array_filter($this->post->team) : array(); - if($task->mode && empty($team)) - { - dao::$errors['assignedTo'] = $this->lang->task->teamNotEmpty; - return false; - } + if($task->mode && empty($team)) dao::$errors['assignedTo'] = $this->lang->task->teamNotEmpty; + if(dao::isError()) return false; return $this->loadModel('file')->processImgURL($task, $this->config->task->editor->edit['id'], (string)$this->post->uid); } @@ -1010,6 +1024,32 @@ class taskZen extends task $this->setMenu($this->view->execution->id); } + /** + * 检查任务的开始时间和截止时间是否合法。 + * Check if the start and end time of the task is legal. + * + * @param object $task + * @param bool $isDateLimit + * @param object $parent + * @param int|null $rowID + * @access public + * @return void + */ + public function checkLegallyDate(object $task, bool $isDateLimit, object|null $parent, int|null $rowID = null): void + { + $beginIndex = $rowID === null ? 'estStarted' : "estStarted[$rowID]"; + $endIndex = $rowID === null ? 'deadline' : "deadline[$rowID]"; + + $beginIsZeroDate = helper::isZeroDate($task->estStarted); + $endIsZeroDate = helper::isZeroDate($task->deadline); + if(!$beginIsZeroDate and !$endIsZeroDate and $task->deadline < $task->estStarted) dao::$errors[$endIndex] = $this->lang->task->error->deadlineSmall; + + if(!$isDateLimit || empty($parent)) return; + if(!$beginIsZeroDate and $task->estStarted < $parent->estStarted) dao::$errors[$beginIndex] = sprintf($this->lang->task->overParentEsStarted, $parent->estStarted); + if(!$endIsZeroDate and $task->deadline > $parent->deadline) dao::$errors[$endIndex] = sprintf($this->lang->task->overParentDeadline, $parent->deadline); + return; + } + /** * 检查传入的创建数据是否符合要求。 * Check if the input post meets the requirements. @@ -1022,17 +1062,9 @@ class taskZen extends task protected function checkCreateTask(object $task, array $team): bool { /* Check if the estimate is positive. */ - if($task->estimate < 0) - { - dao::$errors['estimate'] = $this->lang->task->error->recordMinus; - return false; - } - - if($this->post->multiple && empty($team)) - { - dao::$errors['assignedTo'] = $this->lang->task->teamNotEmpty; - return false; - } + if($task->estimate < 0) dao::$errors['estimate'] = $this->lang->task->error->recordMinus; + if($this->post->multiple && empty($team)) dao::$errors['assignedTo'] = $this->lang->task->teamNotEmpty; + if(dao::isError()) return false; /* If the task start and end date must be between the execution start and end date, check if the task start and end date accord with the conditions. */ if(!empty($this->config->limitTaskDate)) @@ -1041,12 +1073,9 @@ class taskZen extends task if(dao::isError()) return false; } - /* Check start and end date. */ - if(!helper::isZeroDate($task->deadline) && $task->estStarted > $task->deadline) - { - dao::$errors['deadline'] = $this->lang->task->error->deadlineSmall; - return false; - } + $project = $this->dao->findById($task->project)->from(TABLE_PROJECT)->fetch(); + $parents = $this->getParentEstStartedAndDeadline(array($task->parent)); + $this->checkLegallyDate($task, $project->taskDateLimit == 'limit', isset($parents[$task->parent]) ? $parents[$task->parent] : null); return !dao::isError(); } @@ -1064,26 +1093,23 @@ class taskZen extends task { /* Set required fields. */ $requiredFields = $this->config->task->create->requiredFields; - $execution = $this->loadModel('execution')->getById($executionID); + $execution = $this->loadModel('execution')->fetchById($executionID); if($this->task->isNoStoryExecution($execution)) $requiredFields = str_replace(',story,', ',', ',' . $requiredFields . ','); $requiredFields = array_filter(explode(',', $requiredFields)); + $project = $this->loadModel('project')->fetchById($execution->project); + $parentIdList = array_filter(array_column($tasks, 'parent', 'parent')); + $parents = $this->getParentEstStartedAndDeadline($parentIdList); foreach($tasks as $rowIndex => $task) { - if(mb_strlen($task->name) > 255) - { - dao::$errors["name[$rowIndex]"] = sprintf($this->lang->task->error->length, 255); - } + if(mb_strlen($task->name) > 255) dao::$errors["name[$rowIndex]"] = sprintf($this->lang->task->error->length, 255); if(!empty($this->post->estimate[$rowIndex]) and !preg_match("/^[0-9]+(.[0-9]+)?$/", (string)$this->post->estimate[$rowIndex])) { dao::$errors["estimate[$rowIndex]"] = $this->lang->task->error->estimateNumber; } /* If the task start and end date must be between the execution start and end date, check if the task start and end date accord with the conditions. */ - if(!empty($this->config->limitTaskDate)) - { - $this->task->checkEstStartedAndDeadline($executionID, (string)$task->estStarted, (string)$task->deadline); - } + if(!empty($this->config->limitTaskDate)) $this->task->checkEstStartedAndDeadline($executionID, (string)$task->estStarted, (string)$task->deadline); /* Check start and end date. */ if(!helper::isZeroDate($task->deadline) && $task->deadline < $task->estStarted) @@ -1091,24 +1117,19 @@ class taskZen extends task dao::$errors["deadline[$rowIndex]"] = $this->lang->task->error->deadlineSmall; } + $this->checkLegallyDate($task, $project->taskDateLimit == 'limit', isset($parents[$task->parent]) ? $parents[$task->parent] : null, $rowIndex); + /* Check if the estimate is positive. */ - if($task->estimate < 0) - { - dao::$errors["estimate[$rowIndex]"] = $this->lang->task->error->recordMinus; - } + if($task->estimate < 0) dao::$errors["estimate[$rowIndex]"] = $this->lang->task->error->recordMinus; /* Check if the required fields are empty. */ foreach($requiredFields as $field) { - if(empty($task->$field)) - { - dao::$errors[$field . "[$rowIndex]"] = sprintf($this->lang->error->notempty, $this->lang->task->$field); - } + if(empty($task->$field)) dao::$errors[$field . "[$rowIndex]"] = sprintf($this->lang->error->notempty, $this->lang->task->$field); } } - if(dao::isError()) return false; - return true; + return !dao::isError(); } /** @@ -1122,6 +1143,10 @@ class taskZen extends task */ protected function checkBatchEditTask(array $tasks, array $oldTasks): bool { + $oldTask = reset($oldTasks); + $project = $this->loadModel('project')->fetchById($oldTask->project); + $parentIdList = array_filter(array_column($tasks, 'parent', 'parent')); + $parents = $this->getParentEstStartedAndDeadline($parentIdList); foreach($tasks as $taskID => $task) { $oldTask = $oldTasks[$taskID]; @@ -1139,7 +1164,8 @@ class taskZen extends task if($task->status == 'cancel') continue; if($task->status == 'done' && !$task->consumed) dao::$errors["consumed[{$taskID}]"] = (array)sprintf($this->lang->error->notempty, $this->lang->task->consumedThisTime); - if(!empty($task->deadline) && $task->estStarted > $task->deadline) dao::$errors["deadline[{$taskID}]"] = (array)$this->lang->task->error->deadlineSmall; + + $this->checkLegallyDate($task, $project->taskDateLimit == 'limit', isset($parents[$task->parent]) ? $parents[$task->parent] : null, $taskID); } return !dao::isError(); } @@ -2118,4 +2144,39 @@ class taskZen extends task return $options; } + + /** + * 获取父任务的开始时间和截止时间。 + * Get the start and end time of the parent task. + * + * @param array $parentIdList + * @access protected + * @return array + */ + protected function getParentEstStartedAndDeadline(array $parentIdList): array + { + $pathPairs = $this->dao->select('id,path')->from(TABLE_TASK)->where('id')->in($parentIdList)->fetchPairs(); + if($pathPairs) return array(); + + $allParentIdList = array_filter(array_unique(explode(',', implode(',', $pathPairs)))); + $allParents = $this->dao->select('id,estStarted,deadline')->from(TABLE_TASK)->where('id')->in($allParentIdList)->fetchAll('id'); + $parents = array(); + foreach($pathPairs as $parentID => $path) + { + $parent = new stdClass(); + $parent->estStarted = null; + $parent->deadline = null; + foreach(array_reverse(array_filter(explode(',', $path))) as $taskID) + { + if(!isset($allParents[$taskID])) continue; + + $task = $allParents[$taskID]; + if(empty($parent->estStarted) && !helper::isZeroDate($task->estStarted)) $parent->estStarted = $task->estStarted; + if(empty($parent->deadline) && !helper::isZeroDate($task->deadline)) $parent->deadline = $task->deadline; + if(!empty($parent->estStarted) && !empty($parent->deadline)) break; + } + $parents[$parentID] = $parent; + } + return $parents; + } } From 5bd6dde9d1dd01c170ca9d8c64f01e89eab981ca Mon Sep 17 00:00:00 2001 From: wangyidong Date: Fri, 25 Apr 2025 13:42:27 +0800 Subject: [PATCH 071/136] * [perf story #73251] Disable child task estStarted and deadline fields when this parent field is empty. --- module/task/js/batchedit.ui.js | 29 ++++++++++++++++++++--------- module/task/js/create.ui.js | 11 +++++++++-- module/task/js/edit.ui.js | 18 ++++++++++++++++-- module/task/ui/edit.html.php | 2 ++ 4 files changed, 47 insertions(+), 13 deletions(-) diff --git a/module/task/js/batchedit.ui.js b/module/task/js/batchedit.ui.js index 880e3ab488..080a33e319 100644 --- a/module/task/js/batchedit.ui.js +++ b/module/task/js/batchedit.ui.js @@ -34,6 +34,19 @@ window.renderRowData = function($row, index, row) if(row.assignedTo && taskMembers[row.assignedTo] == undefined) taskMembers[row.assignedTo] = users[row.assignedTo]; for(let account in taskMembers) taskUsers.push({value: account, text: taskMembers[account]}); + if(parentTasks[row.parent] != undefined) + { + const parentTask = parentTasks[row.parent]; + $row.find('[id^="estStarted"]').on('inited', function(e, info) + { + if(parentTask.estStarted == '') info[0].render({disabled: true}); + }); + $row.find('[id^="deadline"]').on('inited', function(e, info) + { + if(parentTask.deadline == '') info[0].render({disabled: true}); + }); + } + $row.find('[data-name="assignedTo"]').find('.picker-box').on('inited', function(e, info) { const $assignedTo = info[0]; @@ -45,13 +58,7 @@ window.renderRowData = function($row, index, row) $assignedTo.render({items: taskUsers, disabled: disabled, toolbar: pickerToolbar}); }); - if(row.status == 'wait') - { - $row.find('[data-name="status"]').find('.picker-box').on('inited', function(e, info) - { - info[0].render({items: noPauseStatusList}); - }); - } + if(row.status == 'wait') $row.find('[data-name="status"]').find('.picker-box').on('inited', function(e, info) { info[0].render({items: noPauseStatusList}); }); if(teams[row.id] != undefined || row.isParent > 0) { @@ -186,6 +193,8 @@ function checkBatchEstStartedAndDeadline(event) const $estStartedTd = $currentRow.find('td[data-name=estStarted]'); $estStartedTd.find('.date-tip').remove(); + const $childrenEstStarted = $(event.target).closest('tbody').find('tr[data-parent="' + taskID + '"]').find('[name^=estStarted]'); + $childrenEstStarted.each(function(){$(this).zui('datePicker').render({disabled: estStarted.length == 0});}); if(estStarted.length > 0) { let $datetip = $('
'); @@ -197,7 +206,7 @@ function checkBatchEstStartedAndDeadline(event) } let childEstStarted = childrenDateLimit[taskID] ? childrenDateLimit[taskID].estStarted : ''; - $(event.target).closest('tbody').find('tr[data-parent="' + taskID + '"]').find('[name^=estStarted]').each(function() + $childrenEstStarted.each(function() { if(childEstStarted.length == 0 || ($(this).val().length > 0 && $(this).val() < childEstStarted)) childEstStarted = $(this).val(); }); @@ -215,6 +224,8 @@ function checkBatchEstStartedAndDeadline(event) const $deadlineTd = $currentRow.find('td[data-name=deadline]'); $deadlineTd.find('.date-tip').remove(); + const $childrenDeadline = $(event.target).closest('tbody').find('tr[data-parent="' + taskID + '"]').find('[name^=deadline]'); + $childrenDeadline.each(function(){$(this).zui('datePicker').render({disabled: deadline.length == 0});}); if(deadline.length > 0) { let $datetip = $('
'); @@ -227,7 +238,7 @@ function checkBatchEstStartedAndDeadline(event) } let childDeadline = childrenDateLimit[taskID] ? childrenDateLimit[taskID].deadline : ''; - $(event.target).closest('tbody').find('tr[data-parent="' + taskID + '"]').find('[name^=deadline]').each(function() + $childrenDeadline.each(function() { if(childDeadline.length == 0 || ($(this).val().length > 0 && $(this).val() > childDeadline)) childDeadline = $(this).val(); }); diff --git a/module/task/js/create.ui.js b/module/task/js/create.ui.js index da7408f032..8f93297f9b 100644 --- a/module/task/js/create.ui.js +++ b/module/task/js/create.ui.js @@ -644,8 +644,15 @@ overParentEstStartedLang = ''; overParentDeadlineLang = ''; window.getParentEstStartedAndDeadline = function() { - const parent = $('[name=parent]').val(); - if(!parent) return; + const $parent = $('[name=parent]'); + const parent = $parent.val(); + if(!parent) + { + const $form = $parent.closest('form'); + $form.find('[name=estStarted]').zui('datePicker').render({disabled: false}); + $form.find('[name=deadline]').zui('datePicker').render({disabled: false}); + return; + } const link = $.createLink('task', 'ajaxGetTaskEstStartedAndDeadline', 'taskID=' + parent); $.getJSON(link, function(data) diff --git a/module/task/js/edit.ui.js b/module/task/js/edit.ui.js index cf0b4eee5f..f8d7ac84af 100644 --- a/module/task/js/edit.ui.js +++ b/module/task/js/edit.ui.js @@ -407,8 +407,15 @@ window.setStoryModule = function() getParentEstStartedAndDeadline = function() { - const parent = $('[name=parent]').val(); - if(!parent) return; + const $parent = $('[name=parent]'); + const parent = $parent.val(); + if(!parent) + { + const $form = $parent.closest('form'); + $form.find('[name=estStarted]').zui('datePicker').render({disabled: false}); + $form.find('[name=deadline]').zui('datePicker').render({disabled: false}); + return; + } const link = $.createLink('task', 'ajaxGetTaskEstStartedAndDeadline', 'taskID=' + parent); $.getJSON(link, function(data) @@ -467,4 +474,11 @@ function checkEstStartedAndDeadline(event) } $deadlineDiv.append($datetip); } + + let $estStartedPicker = $estStarted.zui('datePicker'); + let $deadlinePicker = $deadline.zui('datePicker'); + $estStartedPicker.render({disabled: parentEstStarted == ''}); + $deadlinePicker.render({disabled: parentDeadline == ''}); + if(parentEstStarted == '') $estStartedPicker.$.setValue(''); + if(parentDeadline == '') $deadlinePicker.$.setValue(''); } diff --git a/module/task/ui/edit.html.php b/module/task/ui/edit.html.php index 835bb9a23f..e23fa6555d 100644 --- a/module/task/ui/edit.html.php +++ b/module/task/ui/edit.html.php @@ -465,6 +465,7 @@ detailBody datePicker ( set::name('estStarted'), + set::disabled(!empty($parentTask) && helper::isZeroDate($parentTask->estStarted) ? true : false), on::change('checkEstStartedAndDeadline'), helper::isZeroDate($task->estStarted) ? null : set::value($task->estStarted) ) @@ -479,6 +480,7 @@ detailBody datePicker ( set::name('deadline'), + set::disabled(!empty($parentTask) && helper::isZeroDate($parentTask->deadline) ? true : false), on::change('checkEstStartedAndDeadline'), helper::isZeroDate($task->deadline) ? null : set::value($task->deadline) ) From 649af2593796145a0ba15c781ef4197ebfbe48e1 Mon Sep 17 00:00:00 2001 From: wangyidong Date: Fri, 25 Apr 2025 13:53:02 +0800 Subject: [PATCH 072/136] * [perf story #73251] Add other lang. --- module/task/lang/de.php | 2 ++ module/task/lang/en.php | 2 ++ module/task/lang/fr.php | 2 ++ 3 files changed, 6 insertions(+) diff --git a/module/task/lang/de.php b/module/task/lang/de.php index ba80d1888f..8feeb4a82b 100644 --- a/module/task/lang/de.php +++ b/module/task/lang/de.php @@ -437,6 +437,8 @@ $lang->task->overEsEndDate = 'The %s schedule end time has exceeded, please mo $lang->task->overParentEsStarted = 'StartDate is less than the parent task\'s startDate: %s'; $lang->task->overParentDeadline = 'Deadline is greater than the parent task\'s deadline: %s'; +$lang->task->overChildEstStarted = "Existed child task's startDate is less than the task's startDate: %s"; +$lang->task->overChildDeadline = "Existed child task's deadline is greater than the task's deadline: %s"; $lang->task->disabledHint = new stdclass(); $lang->task->disabledHint->assignedConfirmStoryChange = 'Changes can only be confirmed by the assignee.'; diff --git a/module/task/lang/en.php b/module/task/lang/en.php index 3eaf16fa8c..a9d6796b81 100755 --- a/module/task/lang/en.php +++ b/module/task/lang/en.php @@ -437,6 +437,8 @@ $lang->task->overEsEndDate = 'The %s schedule end time has exceeded, please mo $lang->task->overParentEsStarted = 'StartDate is less than the parent task\'s startDate: %s'; $lang->task->overParentDeadline = 'Deadline is greater than the parent task\'s deadline: %s'; +$lang->task->overChildEstStarted = "Existed child task's startDate is less than the task's startDate: %s"; +$lang->task->overChildDeadline = "Existed child task's deadline is greater than the task's deadline: %s"; $lang->task->disabledHint = new stdclass(); $lang->task->disabledHint->assignedConfirmStoryChange = 'Changes can only be confirmed by the assignee.'; diff --git a/module/task/lang/fr.php b/module/task/lang/fr.php index 2a33173f1b..a85ea8bcb5 100644 --- a/module/task/lang/fr.php +++ b/module/task/lang/fr.php @@ -437,6 +437,8 @@ $lang->task->overEsEndDate = 'The %s schedule end time has exceeded, please mo $lang->task->overParentEsStarted = 'StartDate is less than the parent task\'s startDate: %s'; $lang->task->overParentDeadline = 'Deadline is greater than the parent task\'s deadline: %s'; +$lang->task->overChildEstStarted = "Existed child task's startDate is less than the task's startDate: %s"; +$lang->task->overChildDeadline = "Existed child task's deadline is greater than the task's deadline: %s"; $lang->task->disabledHint = new stdclass(); $lang->task->disabledHint->assignedConfirmStoryChange = 'Changes can only be confirmed by the assignee.'; From a468cb875a756e0c68ce251c819ee17552ed76cd Mon Sep 17 00:00:00 2001 From: wangyidong Date: Fri, 25 Apr 2025 17:00:53 +0800 Subject: [PATCH 073/136] * [perf story #73251] Adjust by taskDateLimit condition. --- module/task/js/batchcreate.ui.js | 13 +++++++++---- module/task/js/batchedit.ui.js | 16 +++++----------- module/task/js/create.ui.js | 10 ++++++---- module/task/js/edit.ui.js | 18 ++++++++---------- module/task/model.php | 1 - module/task/ui/batchcreate.html.php | 1 + module/task/ui/batchedit.html.php | 1 + module/task/ui/create.html.php | 1 + module/task/ui/edit.html.php | 1 + module/task/zen.php | 4 ++++ 10 files changed, 36 insertions(+), 30 deletions(-) diff --git a/module/task/js/batchcreate.ui.js b/module/task/js/batchcreate.ui.js index a54e59a7b2..f4658d7f39 100644 --- a/module/task/js/batchcreate.ui.js +++ b/module/task/js/batchcreate.ui.js @@ -156,6 +156,8 @@ $(document).off('change', '#formSettingBtn input[value=story]').on('change', '#f function checkBatchEstStartedAndDeadline(event) { + if(taskDateLimit != 'limit') return; + const $currentRow = $(event.target).closest('tr'); const field = $(event.target).closest('.form-batch-control').data('name'); const estStarted = $currentRow.find('[name^=estStarted]').val(); @@ -166,7 +168,7 @@ function checkBatchEstStartedAndDeadline(event) if(field == 'estStarted' && estStarted.length > 0 && parentEstStarted.length > 0 && estStarted < parentEstStarted) { let $datetip = $('
'); - $datetip.append('
' + overParentEstStartedLang + '' + ignoreLang + '
'); + $datetip.append('
' + overParentEstStartedLang + '
'); $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); $estStartedTd.append($datetip); } @@ -176,7 +178,7 @@ function checkBatchEstStartedAndDeadline(event) if(field == 'deadline' && deadline.length > 0 && parentDeadline.length > 0 && deadline > parentDeadline) { let $datetip = $('
'); - $datetip.append('
' + overParentDeadlineLang + '' + ignoreLang + '
'); + $datetip.append('
' + overParentDeadlineLang + '
'); $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); $deadlineTd.append($datetip); } @@ -274,8 +276,11 @@ window.handleRenderRow = function($row, index) if($preAssignedTo != undefined) $assignedTo.render({items: $preAssignedTo.options.items}); }) - $row.find('[data-name=estStarted]').find('[id^=estStarted]').on('inited', function(e, info) { info[0].render({disabled: parentEstStarted == ''}); }) - $row.find('[data-name=deadline]').find('[id^=deadline]').on('inited', function(e, info) { info[0].render({disabled: parentDeadline == ''}); }) + if(taskDateLimit == 'limit') + { + $row.find('[data-name=estStarted]').find('[id^=estStarted]').on('inited', function(e, info) { info[0].render({disabled: parentEstStarted == ''}); }) + $row.find('[data-name=deadline]').find('[id^=deadline]').on('inited', function(e, info) { info[0].render({disabled: parentDeadline == ''}); }) + } }; $(function() diff --git a/module/task/js/batchedit.ui.js b/module/task/js/batchedit.ui.js index 080a33e319..abe3cac531 100644 --- a/module/task/js/batchedit.ui.js +++ b/module/task/js/batchedit.ui.js @@ -34,7 +34,7 @@ window.renderRowData = function($row, index, row) if(row.assignedTo && taskMembers[row.assignedTo] == undefined) taskMembers[row.assignedTo] = users[row.assignedTo]; for(let account in taskMembers) taskUsers.push({value: account, text: taskMembers[account]}); - if(parentTasks[row.parent] != undefined) + if(parentTasks[row.parent] != undefined && taskDateLimit == 'limit') { const parentTask = parentTasks[row.parent]; $row.find('[id^="estStarted"]').on('inited', function(e, info) @@ -179,6 +179,8 @@ window.statusChange = function(event) function checkBatchEstStartedAndDeadline(event) { + if(taskDateLimit != 'limit') return; + const $currentRow = $(event.target).closest('tr'); const taskID = $currentRow.find('[name^=id]').val(); const parentID = tasks[taskID].parent; @@ -199,11 +201,7 @@ function checkBatchEstStartedAndDeadline(event) { let $datetip = $('
'); let parentEstStarted = typeof tasks[parentID] == 'undefined' || $(event.target).closest('tbody').find('[name="estStarted[' + parentID + ']"]').length == 0 ? parentTask.estStarted : $(event.target).closest('tbody').find('[name="estStarted[' + parentID + ']"]').val(); - if(parentEstStarted.length > 0 && estStarted < parentEstStarted) - { - $datetip.append('
' + overParentEstStartedLang.replace('%s', parentEstStarted) + '' + ignoreLang + '
'); - $datetip.off('click', '.ignore-parent').on('click', '.ignore-parent', function(e){ignoreTip(e)}); - } + if(parentEstStarted.length > 0 && estStarted < parentEstStarted) $datetip.append('
' + overParentEstStartedLang.replace('%s', parentEstStarted) + '
'); let childEstStarted = childrenDateLimit[taskID] ? childrenDateLimit[taskID].estStarted : ''; $childrenEstStarted.each(function() @@ -231,11 +229,7 @@ function checkBatchEstStartedAndDeadline(event) let $datetip = $('
'); let parentDeadline = typeof tasks[parentID] == 'undefined' || $(event.target).closest('tbody').find('[name="deadline[' + parentID + ']"]').length == 0 ? parentTask.deadline : $(event.target).closest('tbody').find('[name="deadline[' + parentID + ']"]').val(); - if(parentDeadline.length > 0 && deadline > parentDeadline) - { - $datetip.append('
' + overParentDeadlineLang.replace('%s', parentDeadline) + '' + ignoreLang + '
'); - $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); - } + if(parentDeadline.length > 0 && deadline > parentDeadline) $datetip.append('
' + overParentDeadlineLang.replace('%s', parentDeadline) + '
'); let childDeadline = childrenDateLimit[taskID] ? childrenDateLimit[taskID].deadline : ''; $childrenDeadline.each(function() diff --git a/module/task/js/create.ui.js b/module/task/js/create.ui.js index 8f93297f9b..3792650d21 100644 --- a/module/task/js/create.ui.js +++ b/module/task/js/create.ui.js @@ -648,6 +648,8 @@ window.getParentEstStartedAndDeadline = function() const parent = $parent.val(); if(!parent) { + if(taskDateLimit != 'limit') return; + const $form = $parent.closest('form'); $form.find('[name=estStarted]').zui('datePicker').render({disabled: false}); $form.find('[name=deadline]').zui('datePicker').render({disabled: false}); @@ -669,6 +671,8 @@ window.getParentEstStartedAndDeadline = function() window.checkEstStartedAndDeadline = function(event) { + if(taskDateLimit != 'limit') return; + const parent = $('[name=parent]').val(); if(!parent) return; @@ -684,8 +688,7 @@ window.checkEstStartedAndDeadline = function(event) if(field == 'estStarted' && estStarted.length > 0 && parentEstStarted.length > 0 && estStarted < parentEstStarted) { let $datetip = $('
'); - $datetip.append('
' + overParentEstStartedLang + '' + ignoreLang + '
'); - $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); + $datetip.append('
' + overParentEstStartedLang + '
'); $estStartedDiv.append($datetip); } @@ -694,8 +697,7 @@ window.checkEstStartedAndDeadline = function(event) if(field == 'deadline' && deadline.length > 0 && parentDeadline.length > 0 && deadline > parentDeadline) { let $datetip = $('
'); - $datetip.append('
' + overParentDeadlineLang + '' + ignoreLang + '
'); - $datetip.off('click', '.ignore-date').on('click', '.ignore-date', function(e){ignoreTip(e)}); + $datetip.append('
' + overParentDeadlineLang + '
'); $deadlineDiv.append($datetip); } diff --git a/module/task/js/edit.ui.js b/module/task/js/edit.ui.js index f8d7ac84af..1637ee69fd 100644 --- a/module/task/js/edit.ui.js +++ b/module/task/js/edit.ui.js @@ -411,6 +411,8 @@ getParentEstStartedAndDeadline = function() const parent = $parent.val(); if(!parent) { + if(taskDateLimit != 'limit') return; + const $form = $parent.closest('form'); $form.find('[name=estStarted]').zui('datePicker').render({disabled: false}); $form.find('[name=deadline]').zui('datePicker').render({disabled: false}); @@ -432,6 +434,8 @@ getParentEstStartedAndDeadline = function() function checkEstStartedAndDeadline(event) { + if(taskDateLimit != 'limit') return; + const $form = $(event.target).closest('form'); const field = $(event.target).attr('name') const $estStarted = $form.find('[name=estStarted]'); @@ -444,11 +448,8 @@ function checkEstStartedAndDeadline(event) { $estStartedDiv.find('.date-tip').remove(); let $datetip = $('
'); - if(parentEstStarted.length > 0 && estStarted < parentEstStarted) - { - $datetip.append('
' + overParentEstStartedLang + '' + ignoreLang + '
'); - $datetip.off('click', '.ignore-parent').on('click', '.ignore-parent', function (e) { ignoreTip(e) }); - } + if(parentEstStarted.length > 0 && estStarted < parentEstStarted) $datetip.append('
' + overParentEstStartedLang + '
'); + if(childDateLimit['estStarted'].length > 0 && estStarted > childDateLimit['estStarted']) { $datetip.append('
' + overChildEstStartedLang + '' + ignoreLang + '
'); @@ -462,11 +463,8 @@ function checkEstStartedAndDeadline(event) { $deadlineDiv.find('.date-tip').remove(); let $datetip = $('
'); - if(parentDeadline.length > 0 && deadline > parentDeadline) - { - $datetip.append('
' + overParentDeadlineLang + '' + ignoreLang + '
'); - $datetip.off('click', '.ignore-parent').on('click', '.ignore-parent', function (e) { ignoreTip(e) }); - } + if(parentDeadline.length > 0 && deadline > parentDeadline) $datetip.append('
' + overParentDeadlineLang + '
'); + if(childDateLimit['deadline'].length > 0 && deadline > childDateLimit['deadline']) { $datetip.append('
' + overChildDeadlineLang + '' + ignoreLang + '
'); diff --git a/module/task/model.php b/module/task/model.php index 88afbdef3e..c147515b79 100755 --- a/module/task/model.php +++ b/module/task/model.php @@ -1337,7 +1337,6 @@ class taskModel extends model ->where('t1.id')->eq($taskID) ->beginIf($vision != 'all')->andWhere('t1.vision')->eq($this->config->vision)->fi() ->fetch(); - if(!$task) return false; /* Format data. */ $task->openedDate = !empty($task->openedDate) ? substr($task->openedDate, 0, 19) : null; diff --git a/module/task/ui/batchcreate.html.php b/module/task/ui/batchcreate.html.php index 9a22456b53..9227d8db9f 100644 --- a/module/task/ui/batchcreate.html.php +++ b/module/task/ui/batchcreate.html.php @@ -24,6 +24,7 @@ jsVar('overParentEstStartedLang', isset($parentTask) ? sprintf($lang->task->over jsVar('overParentDeadlineLang', isset($parentTask) ? sprintf($lang->task->overParentDeadline, $parentTask->deadline) : ''); jsVar('taskHasConsumed', $taskConsumed > 0); jsVar('langAddChildTask', $lang->task->addChildTask); +jsVar('taskDateLimit', $project->taskDateLimit); /* zin: Set variables to define picker options for form. */ $storyItem = ''; diff --git a/module/task/ui/batchedit.html.php b/module/task/ui/batchedit.html.php index 3714abb646..8a159656c3 100644 --- a/module/task/ui/batchedit.html.php +++ b/module/task/ui/batchedit.html.php @@ -41,6 +41,7 @@ jsVar('overParentDeadlineLang', $lang->task->overParentDeadline); jsVar('overChildEstStartedLang', $lang->task->overChildEstStarted); jsVar('overChildDeadlineLang', $lang->task->overChildDeadline); jsVar('manageTeamMemberText', $lang->execution->manageTeamMember); +jsVar('taskDateLimit', empty($project) ? '' : $project->taskDateLimit); /* ====== Define the page structure with zin widgets ====== */ formBatchPanel diff --git a/module/task/ui/create.html.php b/module/task/ui/create.html.php index abdb3a52e7..0ef6939158 100644 --- a/module/task/ui/create.html.php +++ b/module/task/ui/create.html.php @@ -29,6 +29,7 @@ jsVar('showFields', $showFields); jsVar('canViewStory', common::hasPriv('execution', 'storyView')); jsVar('ignoreLang', $lang->project->ignore); jsVar('assignedToOptions', $assignedToOptions); +jsVar('taskDateLimit', $project->taskDateLimit); if(!empty($task->team)) { diff --git a/module/task/ui/edit.html.php b/module/task/ui/edit.html.php index e23fa6555d..bbb18fd6d3 100644 --- a/module/task/ui/edit.html.php +++ b/module/task/ui/edit.html.php @@ -40,6 +40,7 @@ jsVar('+overParentEstStartedLang', !empty($parentTask) ? sprintf($lang->task->ov jsVar('+overParentDeadlineLang', !empty($parentTask) ? sprintf($lang->task->overParentDeadline, $parentTask->deadline) : ''); jsVar('+overChildEstStartedLang', sprintf($lang->task->overChildEstStarted, $childDateLimit['estStarted'])); jsVar('+overChildDeadlineLang', sprintf($lang->task->overChildDeadline, $childDateLimit['deadline'])); +jsVar('taskDateLimit', empty($project) ? '' : $project->taskDateLimit); $confirmSyncTip = ''; if(!empty($syncChildren) && !empty($task->children)) $confirmSyncTip = sprintf($lang->task->syncStoryToChildrenTip, 'ID' . implode(', ID', $syncChildren)); diff --git a/module/task/zen.php b/module/task/zen.php index 5664fe4993..221b7ec706 100644 --- a/module/task/zen.php +++ b/module/task/zen.php @@ -70,6 +70,7 @@ class taskZen extends task $this->view->showFields = $this->config->task->custom->createFields; $this->view->gobackLink = (isset($output['from']) && $output['from'] == 'global') ? $this->createLink('execution', 'task', "executionID={$executionID}") : ''; $this->view->execution = $execution; + $this->view->project = $this->loadModel('project')->fetchById($execution->project); $this->view->storyID = $storyID; $this->view->blockID = helper::isAjaxRequest('modal') ? $this->loadModel('block')->getSpecifiedBlockID('my', 'assigntome', 'assigntome') : 0; $this->view->hideStory = $this->task->isNoStoryExecution($execution); @@ -195,6 +196,7 @@ class taskZen extends task $this->view->title = $execution->name . $this->lang->hyphen . $this->lang->task->batchEdit; $this->view->execution = $execution; + $this->view->project = $this->loadModel('project')->fetchById($execution->project); $this->view->modules = $this->tree->getTaskOptionMenu($executionID, 0, !empty($this->config->task->allModule) ? 'allModule' : ''); } else @@ -360,6 +362,7 @@ class taskZen extends task $this->view->childDateLimit = $childDateLimit; $this->view->parentTask = !empty($task->parent) ? $this->task->getById($task->parent) : null; $this->view->manageLink = $manageLink; + $this->view->project = $task->project ? $this->loadModel('project')->fetchById($task->project) : null; $this->display(); } @@ -450,6 +453,7 @@ class taskZen extends task $this->view->title = $this->lang->task->batchCreate; $this->view->execution = $execution; + $this->view->project = $this->loadModel('project')->fetchById($execution->project); $this->view->modules = $modules; $this->view->parent = $taskID; $this->view->storyID = $storyID; From 2026aa3c975279f3bae003fb21d15bc7f6fc8c2e Mon Sep 17 00:00:00 2001 From: wangyidong Date: Fri, 25 Apr 2025 17:35:52 +0800 Subject: [PATCH 074/136] * [perf story #73251] Revert code. --- module/task/model.php | 1 + 1 file changed, 1 insertion(+) diff --git a/module/task/model.php b/module/task/model.php index c147515b79..88afbdef3e 100755 --- a/module/task/model.php +++ b/module/task/model.php @@ -1337,6 +1337,7 @@ class taskModel extends model ->where('t1.id')->eq($taskID) ->beginIf($vision != 'all')->andWhere('t1.vision')->eq($this->config->vision)->fi() ->fetch(); + if(!$task) return false; /* Format data. */ $task->openedDate = !empty($task->openedDate) ? substr($task->openedDate, 0, 19) : null; From 15093a3a318ad54bc4ed00e12d16d725abc377a9 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Fri, 25 Apr 2025 08:33:22 +0000 Subject: [PATCH 075/136] * [task#142091,done,1h] finish task. --- module/project/config/dtable.php | 11 +++++++++++ module/project/zen.php | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/module/project/config/dtable.php b/module/project/config/dtable.php index a50eff4b17..54b84a8340 100755 --- a/module/project/config/dtable.php +++ b/module/project/config/dtable.php @@ -97,6 +97,17 @@ $config->project->dtable->fieldList['invested']['group'] = 5; $config->project->dtable->fieldList['invested']['show'] = true; $config->project->dtable->fieldList['invested']['sortType'] = false; +if(in_array($config->edition, array('max', 'ipd'))) +{ + $config->project->dtable->fieldList['deliverable']['title'] = $lang->project->deliverableAbbr; + $config->project->dtable->fieldList['deliverable']['name'] = 'deliverable'; + $config->project->dtable->fieldList['deliverable']['type'] = 'html'; + $config->project->dtable->fieldList['deliverable']['width'] = '120px'; + $config->project->dtable->fieldList['deliverable']['group'] = 5; + $config->project->dtable->fieldList['deliverable']['show'] = true; + $config->project->dtable->fieldList['deliverable']['sortType'] = false; +} + $config->project->dtable->fieldList['begin']['title'] = $lang->project->begin; $config->project->dtable->fieldList['begin']['name'] = 'begin'; $config->project->dtable->fieldList['begin']['type'] = 'date'; diff --git a/module/project/zen.php b/module/project/zen.php index ec118dcc37..14c0109231 100755 --- a/module/project/zen.php +++ b/module/project/zen.php @@ -1393,6 +1393,30 @@ class projectZen extends project $project->estimate = helper::formatHours($project->estimate); $project->consume = helper::formatHours($project->consume); $project->left = helper::formatHours($project->left); + + /* 交付物提交进度。 */ + if(in_array($this->config->edition, array('max', 'ipd'))) + { + $numerator = 0; + $denominator = 0; + if($project->deliverable) + { + $deliverables = json_decode($project->deliverable); + foreach($deliverables as $methodList) + { + foreach($methodList as $itemList) + { + array_map(function($item) use(&$numerator, &$denominator) + { + if(!empty($item->file) || !empty($item->doc)) $numerator ++; + if(!empty($item->file) || !empty($item->doc) || $item->required) $denominator ++; + }, $itemList); + } + } + } + + $project->deliverable = $denominator && common::hasPriv('project', 'deliverable') ? html::a($this->createLink('project', 'deliverable', "projectID={$project->id}"), $numerator . ' / ' . $denominator) : '0 / 0'; + } } return array_values($projectList); From 378b89a2b2261d5cd671eca9ff039aeb26d06009 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Fri, 25 Apr 2025 09:04:29 +0000 Subject: [PATCH 076/136] * [task#142091,done,0.5h] add title. --- module/project/zen.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/module/project/zen.php b/module/project/zen.php index 14c0109231..f3ecde1c8b 100755 --- a/module/project/zen.php +++ b/module/project/zen.php @@ -1415,7 +1415,14 @@ class projectZen extends project } } - $project->deliverable = $denominator && common::hasPriv('project', 'deliverable') ? html::a($this->createLink('project', 'deliverable', "projectID={$project->id}"), $numerator . ' / ' . $denominator) : '0 / 0'; + if($denominator && common::hasPriv('project', 'deliverable')) + { + $project->deliverable = html::a($this->createLink('project', 'deliverable', "projectID={$project->id}"), $numerator . ' / ' . $denominator, '', 'title=' . $this->lang->project->deliverableTips); + } + else + { + $project->deliverable = '0 / 0'; + } } } From 87c2456752fd868dee6c4b5be54ab310608fde84 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Fri, 25 Apr 2025 09:08:31 +0000 Subject: [PATCH 077/136] * Fix bug. --- module/project/zen.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/project/zen.php b/module/project/zen.php index f3ecde1c8b..b1341bd000 100755 --- a/module/project/zen.php +++ b/module/project/zen.php @@ -1415,9 +1415,9 @@ class projectZen extends project } } - if($denominator && common::hasPriv('project', 'deliverable')) + if($denominator) { - $project->deliverable = html::a($this->createLink('project', 'deliverable', "projectID={$project->id}"), $numerator . ' / ' . $denominator, '', 'title=' . $this->lang->project->deliverableTips); + $project->deliverable = common::hasPriv('project', 'deliverable') ? html::a($this->createLink('project', 'deliverable', "projectID={$project->id}"), $numerator . ' / ' . $denominator, '', 'title=' . $this->lang->project->deliverableTips) : $numerator . ' / ' . $denominator; } else { From 6dd26e29795c54a7b063ed9fe1d7ce964af10a77 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Sun, 27 Apr 2025 01:54:31 +0000 Subject: [PATCH 078/136] * [task#142091,doing,0.5h] move func to max. --- module/project/zen.php | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/module/project/zen.php b/module/project/zen.php index b1341bd000..414a8478e4 100755 --- a/module/project/zen.php +++ b/module/project/zen.php @@ -1397,32 +1397,7 @@ class projectZen extends project /* 交付物提交进度。 */ if(in_array($this->config->edition, array('max', 'ipd'))) { - $numerator = 0; - $denominator = 0; - if($project->deliverable) - { - $deliverables = json_decode($project->deliverable); - foreach($deliverables as $methodList) - { - foreach($methodList as $itemList) - { - array_map(function($item) use(&$numerator, &$denominator) - { - if(!empty($item->file) || !empty($item->doc)) $numerator ++; - if(!empty($item->file) || !empty($item->doc) || $item->required) $denominator ++; - }, $itemList); - } - } - } - - if($denominator) - { - $project->deliverable = common::hasPriv('project', 'deliverable') ? html::a($this->createLink('project', 'deliverable', "projectID={$project->id}"), $numerator . ' / ' . $denominator, '', 'title=' . $this->lang->project->deliverableTips) : $numerator . ' / ' . $denominator; - } - else - { - $project->deliverable = '0 / 0'; - } + $project->deliverable = $this->project->countDeliverable($project); } } From 0f949b65b4ce750a6bc02d832aefd8f2733241b2 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Sun, 27 Apr 2025 02:08:10 +0000 Subject: [PATCH 079/136] * [misc] remove return. --- module/task/zen.php | 1 - 1 file changed, 1 deletion(-) diff --git a/module/task/zen.php b/module/task/zen.php index 221b7ec706..24b97e125c 100644 --- a/module/task/zen.php +++ b/module/task/zen.php @@ -1051,7 +1051,6 @@ class taskZen extends task if(!$isDateLimit || empty($parent)) return; if(!$beginIsZeroDate and $task->estStarted < $parent->estStarted) dao::$errors[$beginIndex] = sprintf($this->lang->task->overParentEsStarted, $parent->estStarted); if(!$endIsZeroDate and $task->deadline > $parent->deadline) dao::$errors[$endIndex] = sprintf($this->lang->task->overParentDeadline, $parent->deadline); - return; } /** From a58630b9fb65a1312ccc6b790120184a5520950a Mon Sep 17 00:00:00 2001 From: sunguangming Date: Sun, 27 Apr 2025 03:18:50 +0000 Subject: [PATCH 080/136] * [misc] rename func. --- lib/zin/wg/deliverable/js/v1.js | 2 +- lib/zin/wg/deliverable/v1.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/zin/wg/deliverable/js/v1.js b/lib/zin/wg/deliverable/js/v1.js index 56b49c015a..f48434fa84 100644 --- a/lib/zin/wg/deliverable/js/v1.js +++ b/lib/zin/wg/deliverable/js/v1.js @@ -2,7 +2,7 @@ * 获取附件的操作按钮。 * Get file actions. */ -window.getFileActions = function(file, deliverable) +window.getDeliverableFileActions = function(file, deliverable) { let actions = []; actions[0] = {icon: 'edit', key: 'rename'}; diff --git a/lib/zin/wg/deliverable/v1.php b/lib/zin/wg/deliverable/v1.php index 77f74c4617..0b97901fbc 100644 --- a/lib/zin/wg/deliverable/v1.php +++ b/lib/zin/wg/deliverable/v1.php @@ -58,7 +58,7 @@ class deliverable extends wg set::formName($formName), set::items($this->prop('items')), set::docPicker(array('placeholder' => $lang->doc->selectDoc, 'items' => helper::createLink('doc', 'ajaxGetMineDocs', 'keyword={search}'))), - set::getFileActions(jsRaw('window.getFileActions')), + set::getFileActions(jsRaw('window.getDeliverableFileActions')), set::getDocActions(jsRaw('window.getDocActions')), set::getEmptyActions(jsRaw('window.getDeliverableActions')) ); From aa54b37cc1c5587802b0411c336816a2e4d45982 Mon Sep 17 00:00:00 2001 From: wangyidong Date: Mon, 28 Apr 2025 09:13:43 +0800 Subject: [PATCH 081/136] * [perf story #73251] Fix mutual testing question. --- module/task/js/batchcreate.ui.js | 3 ++- module/task/js/create.ui.js | 4 ++-- module/task/js/edit.ui.js | 3 +++ module/task/zen.php | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/module/task/js/batchcreate.ui.js b/module/task/js/batchcreate.ui.js index f4658d7f39..d0e448f848 100644 --- a/module/task/js/batchcreate.ui.js +++ b/module/task/js/batchcreate.ui.js @@ -162,6 +162,7 @@ function checkBatchEstStartedAndDeadline(event) const field = $(event.target).closest('.form-batch-control').data('name'); const estStarted = $currentRow.find('[name^=estStarted]').val(); const deadline = $currentRow.find('[name^=deadline]').val(); + if($currentRow.find('td[data-name=name]').find('input[name^=name]').val() == '') return; const $estStartedTd = $currentRow.find('td[data-name=estStarted]'); $estStartedTd.find('.date-tip').remove(); @@ -276,7 +277,7 @@ window.handleRenderRow = function($row, index) if($preAssignedTo != undefined) $assignedTo.render({items: $preAssignedTo.options.items}); }) - if(taskDateLimit == 'limit') + if(taskDateLimit == 'limit' && parentID) { $row.find('[data-name=estStarted]').find('[id^=estStarted]').on('inited', function(e, info) { info[0].render({disabled: parentEstStarted == ''}); }) $row.find('[data-name=deadline]').find('[id^=deadline]').on('inited', function(e, info) { info[0].render({disabled: parentDeadline == ''}); }) diff --git a/module/task/js/create.ui.js b/module/task/js/create.ui.js index 3792650d21..57a0a5ea99 100644 --- a/module/task/js/create.ui.js +++ b/module/task/js/create.ui.js @@ -683,7 +683,7 @@ window.checkEstStartedAndDeadline = function(event) const $deadline = $form.find('[name=deadline]'); const deadline = $deadline.val(); - const $estStartedDiv = $estStarted.closest('.form-group'); + const $estStartedDiv = $estStarted.closest('.form-group-wrapper'); if(field == 'estStarted') $estStartedDiv.find('.date-tip').remove(); if(field == 'estStarted' && estStarted.length > 0 && parentEstStarted.length > 0 && estStarted < parentEstStarted) { @@ -692,7 +692,7 @@ window.checkEstStartedAndDeadline = function(event) $estStartedDiv.append($datetip); } - const $deadlineDiv = $deadline.closest('.form-group'); + const $deadlineDiv = $deadline.closest('.form-group-wrapper'); if(field == 'deadline') $deadlineDiv.find('.date-tip').remove(); if(field == 'deadline' && deadline.length > 0 && parentDeadline.length > 0 && deadline > parentDeadline) { diff --git a/module/task/js/edit.ui.js b/module/task/js/edit.ui.js index 1637ee69fd..80ac85a034 100644 --- a/module/task/js/edit.ui.js +++ b/module/task/js/edit.ui.js @@ -436,6 +436,9 @@ function checkEstStartedAndDeadline(event) { if(taskDateLimit != 'limit') return; + const parent = $('[name=parent]').val(); + if(!parent) return; + const $form = $(event.target).closest('form'); const field = $(event.target).attr('name') const $estStarted = $form.find('[name=estStarted]'); diff --git a/module/task/zen.php b/module/task/zen.php index 24b97e125c..3c7efb6714 100644 --- a/module/task/zen.php +++ b/module/task/zen.php @@ -2159,7 +2159,7 @@ class taskZen extends task protected function getParentEstStartedAndDeadline(array $parentIdList): array { $pathPairs = $this->dao->select('id,path')->from(TABLE_TASK)->where('id')->in($parentIdList)->fetchPairs(); - if($pathPairs) return array(); + if(empty($pathPairs)) return array(); $allParentIdList = array_filter(array_unique(explode(',', implode(',', $pathPairs)))); $allParents = $this->dao->select('id,estStarted,deadline')->from(TABLE_TASK)->where('id')->in($allParentIdList)->fetchAll('id'); From 8254c686cf7879548dd8b92ec9839a2d9143454a Mon Sep 17 00:00:00 2001 From: wangyuting Date: Fri, 25 Apr 2025 16:24:36 +0800 Subject: [PATCH 082/136] * [task#142086,doing,1h,0h] Check if deliverable has been uploaded when batch edit stage. --- module/programplan/js/create.ui.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/module/programplan/js/create.ui.js b/module/programplan/js/create.ui.js index e908ef6a5b..c4625bce27 100644 --- a/module/programplan/js/create.ui.js +++ b/module/programplan/js/create.ui.js @@ -203,6 +203,12 @@ window.handleRenderRow = function($row, index, data) } }); + /* 有交付物的阶段无法变更阶段类型。 */ + $row.find('[data-name="attribute"]').find('.picker-box').on('inited', function(e, info) + { + if(typeof data != 'undefined' && typeof data.hasDeliverable != 'undefined') info[0].render({disabled: true}); + }); + if(project.model == 'ipd') { if(planID == 0) $row.find('[data-name="ACTIONS"]').find('[data-type="sort"]').addClass('hidden'); From 8b7bc2e89c377372d65bf3adc94a3daccb51eada Mon Sep 17 00:00:00 2001 From: wangyuting Date: Fri, 25 Apr 2025 17:01:30 +0800 Subject: [PATCH 083/136] * [task#142086,doing,1h,3h] Check if deliverable has been uploaded when edit stage. --- module/programplan/ui/edit.html.php | 2 +- module/programplan/zen.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/module/programplan/ui/edit.html.php b/module/programplan/ui/edit.html.php index 195582d4fa..286a92d018 100644 --- a/module/programplan/ui/edit.html.php +++ b/module/programplan/ui/edit.html.php @@ -95,7 +95,7 @@ formPanel ( setID('attributeType'), setClass('flex self-center w-full'), - $enableOptionalAttr ? picker + $enableOptionalAttr && empty($plan->hasDeliverable) ? picker ( setID('attribute'), set::name('attribute'), diff --git a/module/programplan/zen.php b/module/programplan/zen.php index 90f2d9bcd9..c08ff34d5d 100644 --- a/module/programplan/zen.php +++ b/module/programplan/zen.php @@ -279,7 +279,7 @@ class programplanZen extends programplan * @access protected * @return void */ - protected function buildEditView(object $plan) + public function buildEditView(object $plan) { $this->loadModel('project'); $this->loadModel('execution'); From 679f728e64019b11a5e28123fdbfdc2f4a4f7fe3 Mon Sep 17 00:00:00 2001 From: wangyuting Date: Fri, 25 Apr 2025 17:12:49 +0800 Subject: [PATCH 084/136] * [task#142095,doing,0.1h,0h] Optimize deliverable wg style. --- lib/zin/wg/deliverable/v1.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/zin/wg/deliverable/v1.php b/lib/zin/wg/deliverable/v1.php index 0b97901fbc..83fcae40eb 100644 --- a/lib/zin/wg/deliverable/v1.php +++ b/lib/zin/wg/deliverable/v1.php @@ -60,7 +60,8 @@ class deliverable extends wg set::docPicker(array('placeholder' => $lang->doc->selectDoc, 'items' => helper::createLink('doc', 'ajaxGetMineDocs', 'keyword={search}'))), set::getFileActions(jsRaw('window.getDeliverableFileActions')), set::getDocActions(jsRaw('window.getDocActions')), - set::getEmptyActions(jsRaw('window.getDeliverableActions')) + set::getEmptyActions(jsRaw('window.getDeliverableActions')), + set::extraCategory($lang->other) ); } } From f3393c58b51c49ee679bf5d56c751941fa710dbe Mon Sep 17 00:00:00 2001 From: wangyuting Date: Mon, 28 Apr 2025 09:45:58 +0800 Subject: [PATCH 085/136] * [task#142086,doing,1h,2h] Check if deliverable has been uploaded when edit execution. --- module/execution/control.php | 2 +- module/execution/js/batchedit.ui.js | 1 + module/programplan/js/create.ui.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/module/execution/control.php b/module/execution/control.php index 2081fcd549..4f24b646b7 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1342,7 +1342,7 @@ class execution extends control } $executionIDList = $this->post->executionIDList; - $executions = $this->dao->select('*')->from(TABLE_EXECUTION)->where('id')->in($executionIDList)->fetchAll('id'); + $executions = $this->dao->select('*')->from(TABLE_EXECUTION)->where('id')->in($executionIDList)->fetchAll('id', false); $relatedProjects = $this->dao->select('id,project')->from(TABLE_PROJECT)->where('id')->in($executionIDList)->fetchPairs(); /* 获取执行所属的项目列表。*/ $projects = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->in($relatedProjects)->fetchAll('id'); /* 获取执行所属的项目列表中每个项目的项目信息。*/ diff --git a/module/execution/js/batchedit.ui.js b/module/execution/js/batchedit.ui.js index 7e5513263f..8f7344ef8b 100644 --- a/module/execution/js/batchedit.ui.js +++ b/module/execution/js/batchedit.ui.js @@ -11,6 +11,7 @@ window.renderRowData = function($row, index, row) { let $attribute = info[0]; $attribute.render({items: stageItems, required: true, name: 'attribute', disabled: row.grade > 1 && parentType != 'mix'}); + if(typeof row != 'undefined' && typeof row.hasDeliverable != 'undefined') $attribute.render({disabled: true}); $(e.target).attr('data-parent', row.parent); }); } diff --git a/module/programplan/js/create.ui.js b/module/programplan/js/create.ui.js index c4625bce27..ae02e2ab85 100644 --- a/module/programplan/js/create.ui.js +++ b/module/programplan/js/create.ui.js @@ -203,7 +203,7 @@ window.handleRenderRow = function($row, index, data) } }); - /* 有交付物的阶段无法变更阶段类型。 */ + /* 已关闭且有交付物的阶段无法变更阶段类型。 */ $row.find('[data-name="attribute"]').find('.picker-box').on('inited', function(e, info) { if(typeof data != 'undefined' && typeof data.hasDeliverable != 'undefined') info[0].render({disabled: true}); From a97d1c7fb9738ec96ac99d1f638ecd33c84a47ac Mon Sep 17 00:00:00 2001 From: wangyuting Date: Mon, 28 Apr 2025 10:25:15 +0800 Subject: [PATCH 086/136] * Remove file. --- module/upgrade/config.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/module/upgrade/config.php b/module/upgrade/config.php index a78a9cef29..d8c7209582 100644 --- a/module/upgrade/config.php +++ b/module/upgrade/config.php @@ -1470,6 +1470,13 @@ $config->delete['21_6_beta'][] = 'extension/ipd/common/ext/lang/en/effort.php'; $config->delete['21_6_beta'][] = 'extension/ipd/common/ext/lang/fr/effort.php'; $config->delete['21_6_beta'][] = 'extension/ipd/common/ext/lang/zh-cn/effort.php'; +$config->delete['21_6_beta'][] = 'extension/ipd/project/ext/model/class/zentaoipd.class.php'; +$config->delete['21_6_beta'][] = 'extension/max/project/ext/model/class/zentaoipd.class.php'; +$config->delete['21_6_beta'][] = 'extension/biz/project/ext/model/class/zentaoipd.class.php'; +$config->delete['21_6_beta'][] = 'extension/ipd/project/ext/model/zentaoipd.php'; +$config->delete['21_6_beta'][] = 'extension/max/project/ext/model/zentaoipd.php'; +$config->delete['21_6_beta'][] = 'extension/biz/project/ext/model/zentaoipd.php'; + $config->upgrade->openModules = array('action', 'admin', 'ai', 'bi', 'aiapp', 'api', 'automation', 'backup', 'block', 'branch', 'budget', 'bug', 'build', 'cache', 'caselib', 'chart', 'ci', 'client', 'common', 'company', 'compile', 'convert', 'cron', 'custom', 'datatable', 'dataview', 'dept', 'design', 'dev', 'dimension', 'doc', 'durationestimation', 'entry', 'execution', 'extension', 'file', 'git', 'gitlab', 'group', 'holiday', 'im', 'index', 'index.html', 'install', 'issue', 'jenkins', 'job', 'kanban', 'license', 'mail', 'message', 'metric', 'misc', 'mr', 'my', 'personnel', 'pipeline', 'product', 'productplan', 'productset', 'program', 'programplan', 'project', 'projectbuild', 'projectplan', 'projectrelease', 'projectstory', 'pivot', 'qa', 'release', 'repo', 'report', 'risk', 'score', 'screen', 'search', 'setting', 'sonarqube', 'sso', 'stage', 'stakeholder', 'story', 'subject', 'svn', 'task', 'testcase', 'testreport', 'testsuite', 'testtask', 'todo', 'tree', 'tutorial', 'upgrade', 'user', 'webhook', 'weekly', 'workestimation', 'gitea', 'gogs', 'transfer', 'zahost', 'zanode', 'editor', 'charter', 'roadmap', 'account', 'cne', 'host', 'instance', 'ops', 'serverroom', 'space', 'store', 'system', 'solution', 'demand', 'gitfox', 'epic', 'requirement', 'mark'); $config->upgrade->unsetModules = array('design', 'program', 'programplan', 'projectbuild', 'projectrelease', 'stage', 'stakeholder', 'product', 'branch', 'productplan', 'release', 'build', 'qa', 'bug', 'testcase', 'testtask', 'testreport', 'testsuite', 'caselib', 'automation', 'repo', 'ci', 'compile', 'jenkins', 'job', 'svn', 'gitlab', 'sonarqube', 'mr', 'git', 'report', 'sqlbuilder', 'feedback', 'faq', 'attend', 'holiday', 'leave', 'makeup', 'overtime', 'lieu', 'ops', 'host', 'serverroom', 'account', 'domain', 'service', 'deploy', 'conference', 'traincourse', 'pssp', 'baseline', 'classify', 'cm', 'cmcl', 'auditcl', 'reviewcl', 'process', 'activity', 'zoutput', 'auditplan', 'nc', 'subject', 'weekly', 'workestimation', 'issue', 'durationestimation', 'risk', 'opportunity', 'trainplan', 'gapanalysis', 'researchplan', 'researchreport', 'meeting', 'meetingroom', 'budget', 'reviewissue', 'reviewsetting', 'review', 'milestone', 'measurement', 'measrecord', 'assetlib', 'setting', 'im', 'client', 'ldap', 'dev', 'api', 'gitea', 'gogs', 'zanode', 'zahost'); From 586d4dcce0a4be205de30c2972002ab858874bb5 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Mon, 28 Apr 2025 04:06:53 +0000 Subject: [PATCH 087/136] * [task#142093,done,1h] add execution deliverable col. --- module/execution/config/dtable.php | 11 +++++++++++ module/execution/control.php | 1 + module/execution/model.php | 4 +++- module/project/config/dtable.php | 11 +++++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/module/execution/config/dtable.php b/module/execution/config/dtable.php index 0fe823bf71..50081ab515 100644 --- a/module/execution/config/dtable.php +++ b/module/execution/config/dtable.php @@ -49,6 +49,17 @@ $config->execution->dtable->fieldList['status']['width'] = '80'; $config->execution->dtable->fieldList['status']['group'] = '1'; $config->execution->dtable->fieldList['status']['show'] = true; +if(in_array($config->edition, array('max', 'ipd'))) +{ + $config->execution->dtable->fieldList['deliverable']['title'] = $lang->execution->deliverableAbbr; + $config->execution->dtable->fieldList['deliverable']['name'] = 'deliverable'; + $config->execution->dtable->fieldList['deliverable']['type'] = 'html'; + $config->execution->dtable->fieldList['deliverable']['width'] = '100px'; + $config->execution->dtable->fieldList['deliverable']['group'] = '1'; + $config->execution->dtable->fieldList['deliverable']['show'] = true; + $config->execution->dtable->fieldList['deliverable']['sortType'] = false; +} + $config->execution->dtable->fieldList['PM']['title'] = $lang->execution->execPM; $config->execution->dtable->fieldList['PM']['name'] = 'PM'; $config->execution->dtable->fieldList['PM']['type'] = 'avatarBtn'; diff --git a/module/execution/control.php b/module/execution/control.php index 4f24b646b7..6b9ea64d8e 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -2873,6 +2873,7 @@ class execution extends control $this->app->loadLang('stage'); $this->app->loadLang('programplan'); $this->loadModel('product'); + $this->loadModel('project'); $this->loadModel('datatable'); $from = $this->app->tab; diff --git a/module/execution/model.php b/module/execution/model.php index 71e79c08ed..3d80aeb774 100755 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -1431,7 +1431,7 @@ class executionModel extends model $executionQuery = $browseType == 'bySearch' ? $this->getExecutionQuery($param) : ''; $projectModel = $this->dao->select('model')->from(TABLE_PROJECT)->where('id')->eq($projectID)->fetch('model'); - return $this->dao->select('t1.*,t2.name projectName, t2.model as projectModel')->from(TABLE_EXECUTION)->alias('t1') + return $this->dao->select('t1.*,t1.deliverable,t2.name projectName, t2.model as projectModel')->from(TABLE_EXECUTION)->alias('t1') ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') ->beginIF($productID)->leftJoin(TABLE_PROJECTPRODUCT)->alias('t3')->on('t1.id=t3.project')->fi() ->where('t1.type')->in('sprint,stage,kanban') @@ -4808,6 +4808,8 @@ class executionModel extends model $execution->PMAvatar = zget($avatarList, $execution->PMAccount, ''); } + if(in_array($this->config->edition, array('max', 'ipd'))) $execution->deliverable = $this->project->countDeliverable($execution, 'execution'); + $rows[$execution->id] = $execution; /* Append tasks and child stages. */ diff --git a/module/project/config/dtable.php b/module/project/config/dtable.php index 54b84a8340..41477b9827 100755 --- a/module/project/config/dtable.php +++ b/module/project/config/dtable.php @@ -200,6 +200,17 @@ $config->project->execution->dtable->fieldList['status']['width'] = '80'; $config->project->execution->dtable->fieldList['status']['group'] = '1'; $config->project->execution->dtable->fieldList['status']['show'] = true; +if(in_array($config->edition, array('max', 'ipd'))) +{ + $config->project->execution->dtable->fieldList['deliverable']['title'] = $lang->project->deliverableAbbr; + $config->project->execution->dtable->fieldList['deliverable']['name'] = 'deliverable'; + $config->project->execution->dtable->fieldList['deliverable']['type'] = 'html'; + $config->project->execution->dtable->fieldList['deliverable']['width'] = '100px'; + $config->project->execution->dtable->fieldList['deliverable']['group'] = '1'; + $config->project->execution->dtable->fieldList['deliverable']['show'] = true; + $config->project->execution->dtable->fieldList['deliverable']['sortType'] = false; +} + $config->project->execution->dtable->fieldList['PM']['title'] = $lang->project->PM; $config->project->execution->dtable->fieldList['PM']['name'] = 'PM'; $config->project->execution->dtable->fieldList['PM']['type'] = 'avatarBtn'; From d276ce6996be42e992758d18a4c626295d494de3 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Mon, 28 Apr 2025 05:28:11 +0000 Subject: [PATCH 088/136] * [misc] add download file link. --- lib/zin/wg/deliverable/js/v1.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/zin/wg/deliverable/js/v1.js b/lib/zin/wg/deliverable/js/v1.js index f48434fa84..d9364c4a16 100644 --- a/lib/zin/wg/deliverable/js/v1.js +++ b/lib/zin/wg/deliverable/js/v1.js @@ -7,6 +7,7 @@ window.getDeliverableFileActions = function(file, deliverable) let actions = []; actions[0] = {icon: 'edit', key: 'rename'}; actions[1] = {icon: 'trash', key: 'delete'}; + if(canDownload) actions[2] = {icon: 'download', key: 'download', url: $.createLink('file', 'download', 'id=' + file.id), target: '_blank'}; return actions; } From a302723d6e12a4079eb3a4f5137e0a9f1d9c82e1 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Mon, 28 Apr 2025 05:43:29 +0000 Subject: [PATCH 089/136] * [misc] add false to fetchAll. --- module/execution/model.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/execution/model.php b/module/execution/model.php index 3d80aeb774..ad7a6307bd 100755 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -1431,7 +1431,7 @@ class executionModel extends model $executionQuery = $browseType == 'bySearch' ? $this->getExecutionQuery($param) : ''; $projectModel = $this->dao->select('model')->from(TABLE_PROJECT)->where('id')->eq($projectID)->fetch('model'); - return $this->dao->select('t1.*,t1.deliverable,t2.name projectName, t2.model as projectModel')->from(TABLE_EXECUTION)->alias('t1') + return $this->dao->select('t1.*,t2.name projectName, t2.model as projectModel')->from(TABLE_EXECUTION)->alias('t1') ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') ->beginIF($productID)->leftJoin(TABLE_PROJECTPRODUCT)->alias('t3')->on('t1.id=t3.project')->fi() ->where('t1.type')->in('sprint,stage,kanban') @@ -1452,7 +1452,7 @@ class executionModel extends model ->fi() ->orderBy($orderBy) ->page($pager, 't1.id') - ->fetchAll('id'); + ->fetchAll('id', false); } /** From 9cf66b42cbed5ca46983463a4f390661611b6b39 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Mon, 28 Apr 2025 06:05:25 +0000 Subject: [PATCH 090/136] * [bug#62025,done,0.2h] fix bug. --- module/user/model.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/module/user/model.php b/module/user/model.php index b91f2cd1fc..16a4467f64 100644 --- a/module/user/model.php +++ b/module/user/model.php @@ -1294,6 +1294,7 @@ class userModel extends model */ public function getProjects(string $account, string $status = 'all', string $orderBy = 'id_desc', object $pager = null): array { + $this->loadModel('project'); $projects = $this->userTao->fetchProjects($account, $status, $orderBy, $pager); if(!$projects) return array(); @@ -1313,6 +1314,8 @@ class userModel extends model $project->storyPoints = $projectStory ? round($projectStory->estimate, 1) : 0; $project->storyCount = $projectStory ? $projectStory->count : 0; $project->executionCount = zget($projectExecutionCount, $project->id, 0); + + if(in_array($this->config->edition, array('max', 'ipd'))) $project->deliverable = $this->project->countDeliverable($project); } return $projects; From 4203a4249cbb247b28471b02d14ac5b0d30a767a Mon Sep 17 00:00:00 2001 From: sunguangming Date: Mon, 28 Apr 2025 06:34:01 +0000 Subject: [PATCH 091/136] * [misc] move btn to prev. --- lib/zin/wg/deliverable/js/v1.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/zin/wg/deliverable/js/v1.js b/lib/zin/wg/deliverable/js/v1.js index d9364c4a16..bb6af89571 100644 --- a/lib/zin/wg/deliverable/js/v1.js +++ b/lib/zin/wg/deliverable/js/v1.js @@ -5,9 +5,9 @@ window.getDeliverableFileActions = function(file, deliverable) { let actions = []; - actions[0] = {icon: 'edit', key: 'rename'}; - actions[1] = {icon: 'trash', key: 'delete'}; - if(canDownload) actions[2] = {icon: 'download', key: 'download', url: $.createLink('file', 'download', 'id=' + file.id), target: '_blank'}; + if(canDownload && typeof file.id === 'number') actions[0] = {icon: 'download', key: 'download', url: $.createLink('file', 'download', 'id=' + file.id), target: '_blank'}; + actions[1] = {icon: 'edit', key: 'rename'}; + actions[2] = {icon: 'trash', key: 'delete'}; return actions; } From 2ffe0e36172d6d2e122e69752060c517960de951 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Mon, 28 Apr 2025 07:34:58 +0000 Subject: [PATCH 092/136] * [task#142087,done,1h] add notice when close execution. --- module/execution/control.php | 22 ++++++++++++++++------ module/execution/model.php | 26 ++++++++++++++++++-------- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/module/execution/control.php b/module/execution/control.php index 6b9ea64d8e..280e42ba1b 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1395,8 +1395,8 @@ class execution extends control $executionIdList = $this->post->executionIDList; if(is_string($executionIdList)) $executionIdList = explode(',', $executionIdList); - $filteredStages = $this->execution->batchChangeStatus($executionIdList, $status); - if(!$filteredStages) return $this->sendSuccess(array('load' => true)); + $message = $this->execution->batchChangeStatus($executionIdList, $status); + if(empty($message['byChild']) && empty($message['byDeliverable'])) return $this->sendSuccess(array('load' => true)); $alertMsg = ''; if($status == 'wait') @@ -1406,16 +1406,26 @@ class execution extends control if(empty($project) or (!empty($project) and strpos($project->model, 'waterfall') !== false)) { $executionLang = (empty($project) or (!empty($project) and $project->model == 'waterfallplus')) ? $this->lang->execution->common : $this->lang->stage->common; - $alertMsg = sprintf($this->lang->execution->hasStartedTaskOrSubStage, $executionLang, $filteredStages); + $alertMsg = sprintf($this->lang->execution->hasStartedTaskOrSubStage, $executionLang, $message['byChild']); } if(!empty($project) and strpos('agileplus,scrum', $project->model) !== false) { $executionLang = $project->model == 'scrum' ? $this->lang->executionCommon : $this->lang->execution->common; - $alertMsg = sprintf($this->lang->execution->hasStartedTask, $executionLang, $filteredStages); + $alertMsg = sprintf($this->lang->execution->hasStartedTask, $executionLang, $message['byChild']); + } + } + if($status == 'suspended') $alertMsg = sprintf($this->lang->execution->hasSuspendedOrClosedChildren, $message['byChild']); + if($status == 'closed') + { + if(!empty($message['byChild'])) + { + $alertMsg .= sprintf($this->lang->execution->hasNotClosedChildren, $message['byChild']); + } + elseif(!empty($message['byDeliverable'])) + { + $alertMsg .= sprintf($this->lang->execution->cannotCloseByDeliverable, $message['byDeliverable']); } } - if($status == 'suspended') $alertMsg = sprintf($this->lang->execution->hasSuspendedOrClosedChildren, $filteredStages); - if($status == 'closed') $alertMsg = sprintf($this->lang->execution->hasNotClosedChildren, $filteredStages); return $this->sendSuccess(array('message' => $alertMsg, 'load' => true)); } diff --git a/module/execution/model.php b/module/execution/model.php index ad7a6307bd..ae90319336 100755 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -539,17 +539,26 @@ class executionModel extends model * @param array $executionIdList * @param string $status * @access public - * @return string 返回不符合条件被过滤了的执行,来提示执行下任务或子阶段已经开始,无法修改,已过滤。参见 story#41875。 + * @return array 返回不符合条件被过滤了的执行,来提示执行下任务或子阶段已经开始,无法修改,已过滤。参见 story#41875。 */ - public function batchChangeStatus(array $executionIdList, string $status): string + public function batchChangeStatus(array $executionIdList, string $status): array { /* Sort the IDs, the child stage comes first, and the parent stage follows. */ - $executionIdList = $this->dao->select('id')->from(TABLE_EXECUTION)->where('id')->in($executionIdList)->orderBy('grade_desc')->fetchPairs(); + $executionList = $this->dao->select('id,name,status,deliverable')->from(TABLE_EXECUTION)->where('id')->in($executionIdList)->orderBy('grade_desc')->fetchAll('id'); $this->loadModel('programplan'); - $filteredStages = ''; - foreach($executionIdList as $executionID) + $message = array('byChild' => '', 'byDeliverable' => ''); + foreach($executionList as $executionID => $execution) { + if(in_array($this->config->edition, array('max', 'ipd')) && $status == 'closed' && $execution->status == 'doing') + { + if(!$this->canCloseByDeliverable($execution)) + { + $message['byDeliverable'] .= '#' . $execution->id . ' ' . $execution->name . "\n"; + continue; + } + } + /* The state of the parent stage or the sibling stage may be affected by the child stage before the change, so it cannot be checked in advance. */ $selfAndChildrenList = $this->programplan->getSelfAndChildrenList($executionID); $selfAndChildren = $selfAndChildrenList[$executionID]; @@ -557,7 +566,7 @@ class executionModel extends model if($status == 'wait' and $execution->status != 'wait') { - $filteredStages .= $this->changeStatus2Wait($executionID, $selfAndChildren); + $message['byChild'] .= $this->changeStatus2Wait($executionID, $selfAndChildren); } if($status == 'doing' and $execution->status != 'doing') @@ -567,11 +576,12 @@ class executionModel extends model if(($status == 'suspended' and $execution->status != 'suspended') or ($status == 'closed' and $execution->status != 'closed')) { - $filteredStages .= $this->changeStatus2Inactive($executionID, $status, $selfAndChildren); + $message['byChild'] .= $this->changeStatus2Inactive($executionID, $status, $selfAndChildren); } } - return trim($filteredStages, ','); + $message['byChild'] = trim($message['byChild'], ','); + return $message; } /** From 98ecca6c94050503a218e44ab9fa72a0e9bb3450 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Mon, 28 Apr 2025 07:48:54 +0000 Subject: [PATCH 093/136] * [misc] code for sonar. --- module/execution/model.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/module/execution/model.php b/module/execution/model.php index ae90319336..6cd81c46d8 100755 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -550,13 +550,10 @@ class executionModel extends model $message = array('byChild' => '', 'byDeliverable' => ''); foreach($executionList as $executionID => $execution) { - if(in_array($this->config->edition, array('max', 'ipd')) && $status == 'closed' && $execution->status == 'doing') + if(in_array($this->config->edition, array('max', 'ipd')) && $status == 'closed' && $execution->status == 'doing' && !$this->canCloseByDeliverable($execution)) { - if(!$this->canCloseByDeliverable($execution)) - { - $message['byDeliverable'] .= '#' . $execution->id . ' ' . $execution->name . "\n"; - continue; - } + $message['byDeliverable'] .= '#' . $execution->id . ' ' . $execution->name . "\n"; + continue; } /* The state of the parent stage or the sibling stage may be affected by the child stage before the change, so it cannot be checked in advance. */ From 1ecc4a702581adb266a4b8848874a0cbfd076d17 Mon Sep 17 00:00:00 2001 From: wangyuting Date: Mon, 28 Apr 2025 16:24:24 +0800 Subject: [PATCH 094/136] * Fix change stage attribute error. --- module/execution/js/batchedit.ui.js | 2 +- module/execution/tao.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/module/execution/js/batchedit.ui.js b/module/execution/js/batchedit.ui.js index 8f7344ef8b..7e5e8c4a6e 100644 --- a/module/execution/js/batchedit.ui.js +++ b/module/execution/js/batchedit.ui.js @@ -10,7 +10,7 @@ window.renderRowData = function($row, index, row) $row.find('[data-name="lifetime"]').find('.picker-box').on('inited', function(e, info) { let $attribute = info[0]; - $attribute.render({items: stageItems, required: true, name: 'attribute', disabled: row.grade > 1 && parentType != 'mix'}); + $attribute.render({items: stageItems, required: true, name: 'attribute[' + row.id + ']', disabled: row.grade > 1 && parentType != 'mix'}); if(typeof row != 'undefined' && typeof row.hasDeliverable != 'undefined') $attribute.render({disabled: true}); $(e.target).attr('data-parent', row.parent); }); diff --git a/module/execution/tao.php b/module/execution/tao.php index 279ea9f8a3..597b4407a8 100644 --- a/module/execution/tao.php +++ b/module/execution/tao.php @@ -142,8 +142,8 @@ class executionTao extends executionModel $executions[$executionID]->lastEditedBy = $this->app->user->account; $executions[$executionID]->lastEditedDate = helper::now(); - if(isset($postData->code)) $executions[$executionID]->code = $executionCode; - if(isset($postData->project)) $executions[$executionID]->project = zget($postData->project, $executionID, 0); + if(isset($postData->code)) $executions[$executionID]->code = $executionCode; + if(isset($postData->project)) $executions[$executionID]->project = zget($postData->project, $executionID, 0); if(isset($postData->attribute[$executionID])) $executions[$executionID]->attribute = zget($postData->attribute, $executionID, ''); if(isset($postData->lifetime[$executionID])) $executions[$executionID]->lifetime = $postData->lifetime[$executionID]; From 23560e955ed034a13636d930ad0afd6829b97995 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Mon, 28 Apr 2025 09:18:05 +0000 Subject: [PATCH 095/136] * [misc] add rawParent. --- module/execution/model.php | 1 + 1 file changed, 1 insertion(+) diff --git a/module/execution/model.php b/module/execution/model.php index 6cd81c46d8..2118973a36 100755 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -4778,6 +4778,7 @@ class executionModel extends model $execution->id = 'pid' . (string)$execution->id; $execution->projectID = $execution->project; $execution->project = $execution->projectName; + $execution->rawParent = $execution->parent; $execution->parent = (isset($executionList[$execution->parent]) && $execution->parent && $execution->grade > 1) ? 'pid' . (string)$execution->parent : ''; $execution->hasChild = !empty($execution->isParent); $execution->isParent = !empty($execution->isParent) or !empty($execution->tasks); From 470604e9628e182c2e64b7a92bb22b4f5ad6bd1a Mon Sep 17 00:00:00 2001 From: wangyidong Date: Mon, 28 Apr 2025 10:06:28 +0800 Subject: [PATCH 096/136] * [perf story #73341] Set cascade config for config. --- module/transfer/tao.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/module/transfer/tao.php b/module/transfer/tao.php index b86762f803..bfe5c740a3 100644 --- a/module/transfer/tao.php +++ b/module/transfer/tao.php @@ -117,6 +117,12 @@ class transferTao extends transferModel $linkFieldName = $linkField . 'List'; $tmpFieldName = array(); + if(isset($_POST['cascade'][$field])) + { + $lists[$fieldName] = $_POST['cascade'][$field]; + continue; + } + if(empty($lists[$fieldName]) || empty($lists[$linkFieldName])) continue; /* 根据字段名获取表名。*/ @@ -133,11 +139,7 @@ class transferTao extends transferModel /* 将获取到的数据替换到lists中。*/ /* Replace data to lists. */ - foreach($fieldDatas as $id => $linkFieldID) - { - $tmpFieldName[$linkFieldID][$id] = $lists[$fieldName][$id]; - } - + foreach($fieldDatas as $id => $linkFieldID) $tmpFieldName[$linkFieldID][$id] = $lists[$fieldName][$id]; $lists[$fieldName] = $tmpFieldName; } From 7d588c0a9e2ed1be53597ab8e2630ce048c4ca1b Mon Sep 17 00:00:00 2001 From: wangyidong Date: Mon, 28 Apr 2025 17:34:18 +0800 Subject: [PATCH 097/136] * [perf story #73341] Add programplan priv. --- module/group/packagemanager.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/module/group/packagemanager.php b/module/group/packagemanager.php index 2b4f06e5d8..308b21d4b7 100644 --- a/module/group/packagemanager.php +++ b/module/group/packagemanager.php @@ -2135,8 +2135,10 @@ $config->group->package->programPlan = new stdclass(); $config->group->package->programPlan->order = 5; $config->group->package->programPlan->subset = 'programplan'; $config->group->package->programPlan->privs = array(); -$config->group->package->programPlan->privs['programplan-create'] = array('edition' => 'open,biz,max,ipd', 'vision' => 'rnd', 'order' => 5, 'depend' => array('programplan-browse'), 'recommend' => array('programplan-edit')); -$config->group->package->programPlan->privs['programplan-edit'] = array('edition' => 'open,biz,max,ipd', 'vision' => 'rnd', 'order' => 10, 'depend' => array('programplan-browse'), 'recommend' => array('programplan-create')); +$config->group->package->programPlan->privs['programplan-create'] = array('edition' => 'open,biz,max,ipd', 'vision' => 'rnd', 'order' => 5, 'depend' => array('programplan-browse'), 'recommend' => array('programplan-edit')); +$config->group->package->programPlan->privs['programplan-edit'] = array('edition' => 'open,biz,max,ipd', 'vision' => 'rnd', 'order' => 10, 'depend' => array('programplan-browse'), 'recommend' => array('programplan-create')); +$config->group->package->programPlan->privs['programplan-exportTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 15, 'depend' => array('programplan-browse', 'project-execution'), 'recommend' => array()); +$config->group->package->programPlan->privs['programplan-import'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 20, 'depend' => array('programplan-browse', 'project-execution'), 'recommend' => array()); $config->group->package->browseDesign = new stdclass(); $config->group->package->browseDesign->order = 5; From 08ca612c9b3719fbc356ec884df2b35db56ea55b Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 29 Apr 2025 00:55:09 +0000 Subject: [PATCH 098/136] * [task#142087,done,0.2h] alert notice. --- module/execution/control.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/execution/control.php b/module/execution/control.php index 280e42ba1b..58f1a51463 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1427,7 +1427,7 @@ class execution extends control } } - return $this->sendSuccess(array('message' => $alertMsg, 'load' => true)); + return $this->sendSuccess(array('load' => array('alert' => $alertMsg))); } /** From 9c59dbfb89fd9f4629f16d294818fa9f307dcfe5 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 29 Apr 2025 03:27:04 +0000 Subject: [PATCH 099/136] * [task#142088,done,2h] finish task. --- module/execution/control.php | 6 +++++- module/execution/model.php | 10 +++++++++- module/programplan/model.php | 12 ++++++++++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/module/execution/control.php b/module/execution/control.php index 58f1a51463..1ed6776aca 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1656,7 +1656,11 @@ class execution extends control if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); $project = $this->loadModel('project')->getById($execution->project); - if(in_array($project->model, array('waterfall', 'waterfallplus', 'ipd'))) $this->loadModel('programplan')->computeProgress($executionID, 'close'); + if(in_array($project->model, array('waterfall', 'waterfallplus', 'ipd'))) + { + $result = $this->loadModel('programplan')->computeProgress($executionID, 'close'); + if(is_array($result)) return $this->send($result); + } $this->executeHooks($executionID); diff --git a/module/execution/model.php b/module/execution/model.php index 2118973a36..8f70a74b60 100755 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -1488,6 +1488,7 @@ class executionModel extends model $today = helper::today(); $burns = $this->getBurnData($executions); $parentExecutions = $this->dao->select('parent,parent')->from(TABLE_EXECUTION)->where('parent')->ne(0)->andWhere('deleted')->eq(0)->fetchPairs(); + $statusGroup = $this->dao->select('parent,status')->from(TABLE_EXECUTION)->where('parent')->in(array_keys($executions))->fetchGroup('parent', 'status'); /* Get workingDays. */ $earliestEnd = $today; @@ -1509,6 +1510,13 @@ class executionModel extends model if(isset($parentExecutions[$execution->id])) $executions[$execution->id]->isParent = 1; if(empty($productID) && !empty($productList[$execution->id])) $execution->product = trim($productList[$execution->id]->product, ','); + /** 如果子执行都关闭了,则父执行可以手动关闭。 */ + if(isset($statusGroup[$execution->id])) + { + $childStatus = array_keys($statusGroup[$execution->id]); + if(count($childStatus) == 1 && $childStatus[0] == 'closed') $execution->parentCanClose = true; + } + /* Judge whether the execution is delayed. */ if($execution->status != 'done' && $execution->status != 'closed' && $execution->status != 'suspended' && !empty($workingDays)) { @@ -3829,7 +3837,7 @@ class executionModel extends model $action = strtolower($action); if($action == 'start') return $execution->status == 'wait'; - if($action == 'close') return $execution->status != 'closed' && (!isset($execution->isParent) || (isset($execution->isParent) && !$execution->isParent)); + if($action == 'close') return $execution->status != 'closed' && (empty($execution->isParent) || !empty($execution->parentCanClose)); if($action == 'suspend') return $execution->status == 'wait' || $execution->status == 'doing'; if($action == 'putoff') return $execution->status == 'wait' || $execution->status == 'doing'; if($action == 'activate') return $execution->status == 'suspended' || $execution->status == 'closed'; diff --git a/module/programplan/model.php b/module/programplan/model.php index 04baa84e51..483747b149 100755 --- a/module/programplan/model.php +++ b/module/programplan/model.php @@ -602,9 +602,9 @@ class programplanModel extends model * @param string $action * @param bool $isParent * @access public - * @return bool + * @return bool|array */ - public function computeProgress(int $stageID, string $action = '', bool $isParent = false): bool + public function computeProgress(int $stageID, string $action = '', bool $isParent = false): bool|array { $stage = $this->loadModel('execution')->getByID($stageID); if(empty($stage) || empty($stage->path)) return false; @@ -618,6 +618,14 @@ class programplanModel extends model foreach($parentIdList as $id) { $parent = $this->execution->getByID((int)$id); + + /* 如果当前是顶级阶段,并且由于交付物不能关闭,则跳转到顶级阶段的关闭页面。 */ + if(in_array($this->config->edition, array('max', 'ipd')) && $parent->grade == 1 && $parent->type != 'project' && $stageID != $id && !$this->execution->canCloseByDeliverable($parent)) + { + $url = helper::createLink('execution', 'close', "executionID={$parent->id}"); + return array('result' => 'fail', 'callback' => "zui.Modal.confirm('{$this->lang->execution->cannotAutoCloseParent}').then((res) => {if(res) {loadModal('$url', '.modal-dialog');} else {loadPage();}});"); + } + if(empty($this->lang->execution->typeList[$parent->type]) || (!$isParent && $id == $stageID)) continue; /** 获取子阶段关联开始任务数以及状态下子阶段数量。 */ From 9bf90480a034030d0a4e3a0c6d6c1b5ec08ae691 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 29 Apr 2025 04:08:06 +0000 Subject: [PATCH 100/136] * [misc] for code style. --- module/programplan/model.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/programplan/model.php b/module/programplan/model.php index 483747b149..7885818321 100755 --- a/module/programplan/model.php +++ b/module/programplan/model.php @@ -620,7 +620,8 @@ class programplanModel extends model $parent = $this->execution->getByID((int)$id); /* 如果当前是顶级阶段,并且由于交付物不能关闭,则跳转到顶级阶段的关闭页面。 */ - if(in_array($this->config->edition, array('max', 'ipd')) && $parent->grade == 1 && $parent->type != 'project' && $stageID != $id && !$this->execution->canCloseByDeliverable($parent)) + $isTopStage = $parent->grade == 1 && $parent->type != 'project' && $stageID != $id; + if(in_array($this->config->edition, array('max', 'ipd')) && $isTopStage && !$this->execution->canCloseByDeliverable($parent)) { $url = helper::createLink('execution', 'close', "executionID={$parent->id}"); return array('result' => 'fail', 'callback' => "zui.Modal.confirm('{$this->lang->execution->cannotAutoCloseParent}').then((res) => {if(res) {loadModal('$url', '.modal-dialog');} else {loadPage();}});"); From cd1014aa2812178a8e2bc1025c06548fa831a4e1 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 29 Apr 2025 05:08:12 +0000 Subject: [PATCH 101/136] * [task#142376,done,0.5h] finish task. --- module/programplan/ui/edit.html.php | 1 + module/programplan/zen.php | 24 +++++++++++++----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/module/programplan/ui/edit.html.php b/module/programplan/ui/edit.html.php index 286a92d018..aef5381878 100644 --- a/module/programplan/ui/edit.html.php +++ b/module/programplan/ui/edit.html.php @@ -45,6 +45,7 @@ formPanel set::name('parent'), set::items($parentStageList), set::value($plan->parent), + set::disabled($hasUploadedDeliverable), set::required(true), on::change('changeParentStage') ) diff --git a/module/programplan/zen.php b/module/programplan/zen.php index c08ff34d5d..b913b73763 100644 --- a/module/programplan/zen.php +++ b/module/programplan/zen.php @@ -287,17 +287,19 @@ class programplanZen extends programplan $parentStage = $this->project->getByID($plan->parent, 'stage'); - $this->view->title = $this->lang->programplan->edit; - $this->view->isCreateTask = $this->programplan->isCreateTask($plan->id); - $this->view->plan = $plan; - $this->view->project = $this->project->getByID($plan->project); - $this->view->parentStageList = $this->programplan->getParentStageList($plan->project, $plan->id, $plan->product); - $this->view->enableOptionalAttr = empty($parentStage) || (!empty($parentStage) && $parentStage->attribute == 'mix'); - $this->view->isTopStage = $this->programplan->isTopStage($plan->id); - $this->view->isLeafStage = $this->programplan->checkLeafStage($plan->id); - $this->view->PMUsers = $this->loadModel('user')->getPairs('noclosed|nodeleted|pmfirst', $plan->PM); - $this->view->project = $this->project->getByID($plan->project); - $this->view->requiredFields = $this->config->execution->edit->requiredFields; + $this->view->title = $this->lang->programplan->edit; + $this->view->isCreateTask = $this->programplan->isCreateTask($plan->id); + $this->view->plan = $plan; + $this->view->project = $this->project->getByID($plan->project); + $this->view->parentStageList = $this->programplan->getParentStageList($plan->project, $plan->id, $plan->product); + $this->view->enableOptionalAttr = empty($parentStage) || (!empty($parentStage) && $parentStage->attribute == 'mix'); + $this->view->isTopStage = $this->programplan->isTopStage($plan->id); + $this->view->isLeafStage = $this->programplan->checkLeafStage($plan->id); + $this->view->PMUsers = $this->loadModel('user')->getPairs('noclosed|nodeleted|pmfirst', $plan->PM); + $this->view->project = $this->project->getByID($plan->project); + $this->view->requiredFields = $this->config->execution->edit->requiredFields; + $this->view->hasUploadedDeliverable = in_array($this->config->edition, array('max', 'ipd')) ? $this->execution->hasUploadedDeliverable($plan) : false; + $this->display(); } From 7c63ab987976ec103ef6c3e3a6c71b66e604a595 Mon Sep 17 00:00:00 2001 From: wangyuting Date: Tue, 29 Apr 2025 13:08:37 +0800 Subject: [PATCH 102/136] * [task#142432,done,2h,0h] Finish deliverable switch function. --- module/admin/lang/de.php | 1 + module/admin/lang/en.php | 1 + module/admin/lang/fr.php | 1 + module/admin/lang/menu.php | 14 +++++++------- module/admin/lang/zh-cn.php | 1 + module/project/config/dtable.php | 4 ++-- 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/module/admin/lang/de.php b/module/admin/lang/de.php index f46edad4ef..11bc8a98f8 100755 --- a/module/admin/lang/de.php +++ b/module/admin/lang/de.php @@ -118,6 +118,7 @@ $lang->admin->setModule->opportunitylib = 'Opportunity Lib'; $lang->admin->setModule->practicelib = 'Practice Lib'; $lang->admin->setModule->componentlib = 'Component Lib'; $lang->admin->setModule->devops = 'DevOps'; +$lang->admin->setModule->deliverable = 'Deliverable'; $lang->admin->setModule->kanban = 'Kanban'; $lang->admin->setModule->OA = 'OA'; $lang->admin->setModule->deploy = 'Deploy'; diff --git a/module/admin/lang/en.php b/module/admin/lang/en.php index ca0b92b227..aec0983c5b 100755 --- a/module/admin/lang/en.php +++ b/module/admin/lang/en.php @@ -118,6 +118,7 @@ $lang->admin->setModule->opportunitylib = 'Opportunity Lib'; $lang->admin->setModule->practicelib = 'Practice Lib'; $lang->admin->setModule->componentlib = 'Component Lib'; $lang->admin->setModule->devops = 'DevOps'; +$lang->admin->setModule->deliverable = 'Deliverable'; $lang->admin->setModule->kanban = 'Kanban'; $lang->admin->setModule->OA = 'OA'; $lang->admin->setModule->deploy = 'Deploy'; diff --git a/module/admin/lang/fr.php b/module/admin/lang/fr.php index 1d5b91d323..38b0490e3a 100755 --- a/module/admin/lang/fr.php +++ b/module/admin/lang/fr.php @@ -118,6 +118,7 @@ $lang->admin->setModule->opportunitylib = 'Opportunity Lib'; $lang->admin->setModule->practicelib = 'Practice Lib'; $lang->admin->setModule->componentlib = 'Component Lib'; $lang->admin->setModule->devops = 'DevOps'; +$lang->admin->setModule->deliverable = 'Deliverable'; $lang->admin->setModule->kanban = 'Kanban'; $lang->admin->setModule->OA = 'OA'; $lang->admin->setModule->deploy = 'Deploy'; diff --git a/module/admin/lang/menu.php b/module/admin/lang/menu.php index 88350fb893..8acf9d1353 100644 --- a/module/admin/lang/menu.php +++ b/module/admin/lang/menu.php @@ -86,14 +86,14 @@ $lang->admin->menuList->model['menuOrder']['15'] = 'waterfall'; $lang->admin->menuList->model['menuOrder']['20'] = 'agileplus'; $lang->admin->menuList->model['menuOrder']['25'] = 'waterfallplus'; -$lang->admin->menuList->model['tabMenu']['common']['project'] = array('link' => "{$lang->project->common}|custom|required|module=project", 'alias' => 'set,project', 'exclude' => 'custom-required', 'links' => array('custom|set|module=project&field=unitList')); -if(helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['common']['stage'] = array('link' => "{$lang->stage->type}|stage|settype|", 'subModule' => 'stage'); -if($config->edition == 'max' or $config->edition == 'ipd') $lang->admin->menuList->model['tabMenu']['common']['deliverable'] = array('link' => "{$lang->deliverable->common}|deliverable|browse|", 'subModule' => 'deliverable'); -$lang->admin->menuList->model['tabMenu']['common']['build'] = array('link' => "{$lang->build->common}|custom|required|module=build", 'alias' => 'set', 'exclude' => 'custom'); -$lang->admin->menuList->model['tabMenu']['common']['flow'] = array('link' => "{$lang->custom->flow}|custom|flow|", 'divider' => true); +$lang->admin->menuList->model['tabMenu']['common']['project'] = array('link' => "{$lang->project->common}|custom|required|module=project", 'alias' => 'set,project', 'exclude' => 'custom-required', 'links' => array('custom|set|module=project&field=unitList')); +if(helper::hasFeature('waterfall') || helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['common']['stage'] = array('link' => "{$lang->stage->type}|stage|settype|", 'subModule' => 'stage'); +if(helper::hasFeature('deliverable') && ($config->edition == 'max' || $config->edition == 'ipd')) $lang->admin->menuList->model['tabMenu']['common']['deliverable'] = array('link' => "{$lang->deliverable->common}|deliverable|browse|", 'subModule' => 'deliverable'); +$lang->admin->menuList->model['tabMenu']['common']['build'] = array('link' => "{$lang->build->common}|custom|required|module=build", 'alias' => 'set', 'exclude' => 'custom'); +$lang->admin->menuList->model['tabMenu']['common']['flow'] = array('link' => "{$lang->custom->flow}|custom|flow|", 'divider' => true); -$lang->admin->menuList->model['tabMenu']['common']['percent'] = array('link' => "{$lang->stage->percent}|custom|percent|"); -$lang->admin->menuList->model['tabMenu']['common']['hours'] = array('link' => "{$lang->workingHour}|custom|hours|", 'subModule' => 'holiday', 'links' => array('holiday|browse|', 'custom|hours|')); +$lang->admin->menuList->model['tabMenu']['common']['percent'] = array('link' => "{$lang->stage->percent}|custom|percent|"); +$lang->admin->menuList->model['tabMenu']['common']['hours'] = array('link' => "{$lang->workingHour}|custom|hours|", 'subModule' => 'holiday', 'links' => array('holiday|browse|', 'custom|hours|')); if(helper::hasFeature('waterfall')) $lang->admin->menuList->model['tabMenu']['waterfall']['stage'] = array('link' => "{$lang->stage->list}|stage|browse|", 'subModule' => 'stage', 'exclude' => 'stage-plusbrowse'); if(helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['waterfallplus']['stage'] = array('link' => "{$lang->stage->list}|stage|plusbrowse|", 'subModule' => 'stage', 'exclude' => 'stage-browse'); $lang->admin->menuList->model['tabMenu']['menuOrder']['common']['5'] = 'project'; diff --git a/module/admin/lang/zh-cn.php b/module/admin/lang/zh-cn.php index fda8f7b722..18dbf40abe 100755 --- a/module/admin/lang/zh-cn.php +++ b/module/admin/lang/zh-cn.php @@ -118,6 +118,7 @@ $lang->admin->setModule->opportunitylib = '机会库'; $lang->admin->setModule->practicelib = '最佳实践库'; $lang->admin->setModule->componentlib = '组件库'; $lang->admin->setModule->devops = 'DevOps'; +$lang->admin->setModule->deliverable = '交付物'; $lang->admin->setModule->kanban = '通用看板'; $lang->admin->setModule->OA = '办公'; $lang->admin->setModule->deploy = '运维'; diff --git a/module/project/config/dtable.php b/module/project/config/dtable.php index 41477b9827..85b92fa46e 100755 --- a/module/project/config/dtable.php +++ b/module/project/config/dtable.php @@ -97,7 +97,7 @@ $config->project->dtable->fieldList['invested']['group'] = 5; $config->project->dtable->fieldList['invested']['show'] = true; $config->project->dtable->fieldList['invested']['sortType'] = false; -if(in_array($config->edition, array('max', 'ipd'))) +if(helper::hasFeature('deliverable') && in_array($config->edition, array('max', 'ipd'))) { $config->project->dtable->fieldList['deliverable']['title'] = $lang->project->deliverableAbbr; $config->project->dtable->fieldList['deliverable']['name'] = 'deliverable'; @@ -200,7 +200,7 @@ $config->project->execution->dtable->fieldList['status']['width'] = '80'; $config->project->execution->dtable->fieldList['status']['group'] = '1'; $config->project->execution->dtable->fieldList['status']['show'] = true; -if(in_array($config->edition, array('max', 'ipd'))) +if(helper::hasFeature('deliverable') && in_array($config->edition, array('max', 'ipd'))) { $config->project->execution->dtable->fieldList['deliverable']['title'] = $lang->project->deliverableAbbr; $config->project->execution->dtable->fieldList['deliverable']['name'] = 'deliverable'; From 138a6e7dc59854327a0d9b21be3276df484e175c Mon Sep 17 00:00:00 2001 From: wangyidong Date: Tue, 29 Apr 2025 13:42:51 +0800 Subject: [PATCH 103/136] * [refac bug #62087] Fix for compare child task date. --- module/task/js/batchedit.ui.js | 2 +- module/task/js/edit.ui.js | 2 +- module/task/zen.php | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/module/task/js/batchedit.ui.js b/module/task/js/batchedit.ui.js index abe3cac531..8125bed055 100644 --- a/module/task/js/batchedit.ui.js +++ b/module/task/js/batchedit.ui.js @@ -236,7 +236,7 @@ function checkBatchEstStartedAndDeadline(event) { if(childDeadline.length == 0 || ($(this).val().length > 0 && $(this).val() > childDeadline)) childDeadline = $(this).val(); }); - if(childDeadline.length > 0 && deadline > childDeadline) + if(childDeadline.length > 0 && deadline < childDeadline) { $datetip.append('
' + overChildDeadlineLang.replace('%s', childDeadline) + '' + ignoreLang + '
'); $datetip.off('click', '.ignore-child').on('click', '.ignore-child', function(e){ignoreTip(e)}); diff --git a/module/task/js/edit.ui.js b/module/task/js/edit.ui.js index 80ac85a034..7ce667d2be 100644 --- a/module/task/js/edit.ui.js +++ b/module/task/js/edit.ui.js @@ -468,7 +468,7 @@ function checkEstStartedAndDeadline(event) let $datetip = $('
'); if(parentDeadline.length > 0 && deadline > parentDeadline) $datetip.append('
' + overParentDeadlineLang + '
'); - if(childDateLimit['deadline'].length > 0 && deadline > childDateLimit['deadline']) + if(childDateLimit['deadline'].length > 0 && deadline < childDateLimit['deadline']) { $datetip.append('
' + overChildDeadlineLang + '' + ignoreLang + '
'); $datetip.off('click', '.ignore-child').on('click', '.ignore-child', function (e) { ignoreTip(e) }); diff --git a/module/task/zen.php b/module/task/zen.php index 3c7efb6714..678816d78a 100644 --- a/module/task/zen.php +++ b/module/task/zen.php @@ -1536,11 +1536,11 @@ class taskZen extends task unset($task->team); } - if($task->isParent) + if($task->isParent && strpos($task->name, "[{$this->lang->task->parentAB}]") === false) { $task->name = '[' . $this->lang->task->parentAB . '] ' . $task->name; } - elseif($task->parent > 0) + elseif($task->parent > 0 && strpos($task->name, "[{$this->lang->task->childrenAB}]") === false) { $task->name = '[' . $this->lang->task->childrenAB . '] ' . $task->name; } From 3ed45803c95ef67ab8d2e6066bac0092488d343b Mon Sep 17 00:00:00 2001 From: wangyidong Date: Tue, 29 Apr 2025 13:56:02 +0800 Subject: [PATCH 104/136] * [refac bug #62078] Set open attr for searchToggle. --- module/project/ui/browsebycard.html.php | 2 +- module/project/ui/browsebylist.html.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/module/project/ui/browsebycard.html.php b/module/project/ui/browsebycard.html.php index 67456d5ae4..e2b28d4efa 100644 --- a/module/project/ui/browsebycard.html.php +++ b/module/project/ui/browsebycard.html.php @@ -44,7 +44,7 @@ featureBar set::text($lang->project->mine), set::checked($this->cookie->involved ? 'checked' : '') ), - li(searchToggle(set::module('project'))) + li(searchToggle(set::module('project'), set::open($browseType == 'bysearch'))) ); /* zin: Define the toolbar on main menu. */ diff --git a/module/project/ui/browsebylist.html.php b/module/project/ui/browsebylist.html.php index f2ea2480d0..5d64b2314e 100644 --- a/module/project/ui/browsebylist.html.php +++ b/module/project/ui/browsebylist.html.php @@ -25,7 +25,7 @@ featureBar set::text($lang->project->mine), set::checked($this->cookie->involved ? 'checked' : '') ), - li(searchToggle(set::module('project'))) + li(searchToggle(set::module('project'), set::open($browseType == 'bysearch'))) ); /* zin: Define the toolbar on main menu. */ From 1fd707a17d2224f7a66a3c8a7f2a04e181a1e8da Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 29 Apr 2025 06:04:11 +0000 Subject: [PATCH 105/136] * [task#142680,done,0.1h] fix bug. --- module/execution/control.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/execution/control.php b/module/execution/control.php index 1ed6776aca..ad876d0db3 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1427,7 +1427,7 @@ class execution extends control } } - return $this->sendSuccess(array('load' => array('alert' => $alertMsg))); + return $this->send(array('load' => array('alert' => $alertMsg), 'result' => 'success')); } /** From bfe516f0c51721385cb60b30d7d2baddb4f34e15 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 29 Apr 2025 06:22:33 +0000 Subject: [PATCH 106/136] * [task#142680,done,0.5h] finish task. --- module/execution/model.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/module/execution/model.php b/module/execution/model.php index 8f70a74b60..6c24c21e3d 100755 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -544,13 +544,14 @@ class executionModel extends model public function batchChangeStatus(array $executionIdList, string $status): array { /* Sort the IDs, the child stage comes first, and the parent stage follows. */ - $executionList = $this->dao->select('id,name,status,deliverable')->from(TABLE_EXECUTION)->where('id')->in($executionIdList)->orderBy('grade_desc')->fetchAll('id'); + $executionList = $this->dao->select('id,name,status,grade,deliverable')->from(TABLE_EXECUTION)->where('id')->in($executionIdList)->orderBy('grade_desc')->fetchAll('id'); $this->loadModel('programplan'); $message = array('byChild' => '', 'byDeliverable' => ''); foreach($executionList as $executionID => $execution) { - if(in_array($this->config->edition, array('max', 'ipd')) && $status == 'closed' && $execution->status == 'doing' && !$this->canCloseByDeliverable($execution)) + $needCheckDeliverable = $status == 'closed' && $execution->status == 'doing' && $execution->grade == 1; + if(in_array($this->config->edition, array('max', 'ipd')) && $needCheckDeliverable && !$this->canCloseByDeliverable($execution)) { $message['byDeliverable'] .= '#' . $execution->id . ' ' . $execution->name . "\n"; continue; From f6f43b5d7dc0968971a9b914bde99f54616bf5e5 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 29 Apr 2025 07:26:44 +0000 Subject: [PATCH 107/136] * [misc] remove unused code. --- module/execution/tao.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/module/execution/tao.php b/module/execution/tao.php index 597b4407a8..071f91c29d 100644 --- a/module/execution/tao.php +++ b/module/execution/tao.php @@ -467,11 +467,6 @@ class executionTao extends executionModel $this->lang->execution->menu->kanban = array('link' => "{$this->lang->kanban->common}|execution|kanban|executionID=%s", 'subModule' => 'task', 'alias' => 'importtask'); $this->lang->execution->menu->CFD = array('link' => "{$this->lang->execution->CFD}|execution|cfd|executionID=%s"); $this->lang->execution->menu->build = array('link' => "{$this->lang->build->common}|execution|build|executionID=%s", 'alias' => 'bug', 'subModule' => 'projectbuild,build,bug'); - if(in_array($this->config->edition, array('max', 'ipd'))) - { - $this->lang->execution->menu->deliverable = array('link' => "{$this->lang->deliverable->common}|execution|deliverable|executionID=%s"); - $this->lang->execution->menuOrder[57] = 'deliverable'; - } $this->lang->execution->menu->settings = array('link' => "{$this->lang->settings}|execution|view|executionID=%s", 'subModule' => 'personnel', 'alias' => 'edit,manageproducts,team,whitelist,addwhitelist,managemembers', 'class' => 'dropdown dropdown-hover'); $this->lang->execution->dividerMenu = ''; From 060f2f2d437cbedc359f640442b21053211cb612 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 29 Apr 2025 07:47:58 +0000 Subject: [PATCH 108/136] * [bug#62143,done,0.2h] fix bug. --- module/action/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/action/model.php b/module/action/model.php index 8c8103a502..f95ae829ec 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -936,7 +936,7 @@ class actionModel extends model if(strlen(trim(($action->comment))) !== 0) { $item->comment = $this->formatActionComment($action->comment); - $item->commentEditable = $commentEditable && $endAction->id == $action->id && $action->actor == $account && common::hasPriv('action', 'editComment'); + $item->commentEditable = $commentEditable && $endAction->id == $action->id && $action->actor == $account && common::hasPriv('action', 'editComment') && $action->action == 'commented'; } if($action->action === 'assigned' || $action->action === 'toaudit') From 0e240804ced30aa979df89b26c23afaa31c649df Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 29 Apr 2025 08:01:23 +0000 Subject: [PATCH 109/136] * [misc] for sonar. --- module/action/model.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/action/model.php b/module/action/model.php index f95ae829ec..70d48302ab 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -936,7 +936,8 @@ class actionModel extends model if(strlen(trim(($action->comment))) !== 0) { $item->comment = $this->formatActionComment($action->comment); - $item->commentEditable = $commentEditable && $endAction->id == $action->id && $action->actor == $account && common::hasPriv('action', 'editComment') && $action->action == 'commented'; + $currentUserCanEdit = $action->id == $endAction->id && $action->actor == $account && $action->action == 'commented'; + $item->commentEditable = $commentEditable && common::hasPriv('action', 'editComment') && $currentUserCanEdit; } if($action->action === 'assigned' || $action->action === 'toaudit') From 012e06081cdf073713923dfb90fac90caf212fab Mon Sep 17 00:00:00 2001 From: wangyuting Date: Tue, 29 Apr 2025 15:54:29 +0800 Subject: [PATCH 110/136] * [story#73843,done,0.2h,0h] Finish task related docs. --- db/update21.7.sql | 8 ++++++-- db/zentao.sql | 5 +++++ module/task/ui/edit.html.php | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/db/update21.7.sql b/db/update21.7.sql index a36cd6e432..a1d45d0104 100644 --- a/db/update21.7.sql +++ b/db/update21.7.sql @@ -15,6 +15,10 @@ CREATE TABLE IF NOT EXISTS `zt_deliverable` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -ALTER TABLE `zt_workflowgroup` ADD COLUMN `deliverable` text NULL DEFAULT '' AFTER `editedDate`; +ALTER TABLE `zt_workflowgroup` ADD COLUMN `deliverable` text NULL AFTER `editedDate`; ALTER TABLE `zt_project` ADD COLUMN `taskDateLimit` varchar(5) NOT NULL DEFAULT 'auto' AFTER `linkType`; -ALTER TABLE `zt_project` ADD COLUMN `deliverable` text NULL DEFAULT '' AFTER `maxColWidth`; +ALTER TABLE `zt_project` ADD COLUMN `deliverable` text NULL AFTER `maxColWidth`; + +ALTER TABLE `zt_task` ADD COLUMN `docs` text NULL AFTER `fromIssue`; +ALTER TABLE `zt_story` ADD COLUMN `docs` text NULL AFTER `linkRequirements`; +ALTER TABLE `zt_design` ADD COLUMN `docs` text NULL AFTER `storyVersion`; diff --git a/db/zentao.sql b/db/zentao.sql index 0795b0bcba..28edc2604c 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -769,6 +769,7 @@ CREATE TABLE IF NOT EXISTS `zt_design` ( `deleted` enum('0','1') NOT NULL DEFAULT '0', `story` char(30) NOT NULL DEFAULT '', `storyVersion` smallint(6) UNSIGNED NOT NULL DEFAULT '1', + `docs` text NULL, `desc` mediumtext NULL, `version` smallint(6) NOT NULL DEFAULT '0', `type` char(30) NOT NULL DEFAULT '', @@ -1612,6 +1613,7 @@ CREATE TABLE IF NOT EXISTS `zt_project` ( `colWidth` smallint(6) NOT NULL DEFAULT '264', `minColWidth` smallint(6) NOT NULL DEFAULT '200', `maxColWidth` smallint(6) NOT NULL DEFAULT '384', + `deliverable` text NULL, `deleted` enum('0','1') NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; @@ -1963,6 +1965,7 @@ CREATE TABLE IF NOT EXISTS `zt_story` ( `toBug` mediumint(8) unsigned NOT NULL DEFAULT '0', `linkStories` varchar(255) NOT NULL DEFAULT '', `linkRequirements` varchar(255) NOT NULL DEFAULT '', + `docs` text NULL, `twins` varchar(255) NOT NULL DEFAULT '', `duplicateStory` mediumint(8) unsigned NOT NULL DEFAULT '0', `version` smallint(6) NOT NULL DEFAULT '1', @@ -2065,6 +2068,7 @@ CREATE TABLE IF NOT EXISTS `zt_task` ( `fromBug` mediumint(8) unsigned NOT NULL DEFAULT '0', `feedback` mediumint(8) unsigned NOT NULL DEFAULT '0', `fromIssue` mediumint(8) unsigned NOT NULL DEFAULT '0', + `docs` text NULL, `name` varchar(255) NOT NULL DEFAULT '', `type` varchar(20) NOT NULL DEFAULT '', `mode` varchar(10) NOT NULL DEFAULT '', @@ -13259,6 +13263,7 @@ CREATE TABLE IF NOT EXISTS `zt_workflowgroup` ( `createdDate` datetime NULL, `editedBy` varchar(30) NOT NULL DEFAULT '', `editedDate` datetime NULL, + `deliverable` text NULL, `deleted` enum('0', '1') NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/module/task/ui/edit.html.php b/module/task/ui/edit.html.php index bbb18fd6d3..7769704b66 100644 --- a/module/task/ui/edit.html.php +++ b/module/task/ui/edit.html.php @@ -176,6 +176,7 @@ detailBody ) : null, section ( + setID('files'), set::title($lang->files), fileSelector($task->files ? set::defaultFiles(array_values($task->files)) : null) ), From 79eb022a40add85732dd74f22c44cd286a8caf07 Mon Sep 17 00:00:00 2001 From: wangyuting Date: Tue, 29 Apr 2025 16:49:20 +0800 Subject: [PATCH 111/136] * [story#73846,done,0.1h,0h] Finish design related docs. --- module/design/ui/create.html.php | 1 + module/design/ui/edit.html.php | 1 + 2 files changed, 2 insertions(+) diff --git a/module/design/ui/create.html.php b/module/design/ui/create.html.php index 724e211514..fc4aaf302d 100644 --- a/module/design/ui/create.html.php +++ b/module/design/ui/create.html.php @@ -85,6 +85,7 @@ formPanel ), formRow ( + setID('files'), formGroup ( set::label($lang->design->file), diff --git a/module/design/ui/edit.html.php b/module/design/ui/edit.html.php index 89c2a85f7a..35210126e9 100644 --- a/module/design/ui/edit.html.php +++ b/module/design/ui/edit.html.php @@ -75,6 +75,7 @@ formPanel ), formGroup ( + setID('files'), set::label($lang->design->file), fileSelector($design->files ? set::defaultFiles(array_values($design->files)) : null) ), From db298712abda9cef8103829575fb2ece8d4061ae Mon Sep 17 00:00:00 2001 From: wangyuting Date: Tue, 29 Apr 2025 17:23:10 +0800 Subject: [PATCH 112/136] * [story#73840,done,1h,0h] Finish story related docs. --- module/design/ui/view.html.php | 1 + module/story/ui/edit.html.php | 1 + 2 files changed, 2 insertions(+) diff --git a/module/design/ui/view.html.php b/module/design/ui/view.html.php index d6e102a311..ebd70fdc0d 100644 --- a/module/design/ui/view.html.php +++ b/module/design/ui/view.html.php @@ -78,6 +78,7 @@ detailBody ( section ( + setID('desc'), set::title($lang->design->desc), set::content(empty($design->desc) ? $lang->noDesc : $design->desc), set::useHtml(true) diff --git a/module/story/ui/edit.html.php b/module/story/ui/edit.html.php index 8ae743be5b..dc59fc487d 100644 --- a/module/story/ui/edit.html.php +++ b/module/story/ui/edit.html.php @@ -195,6 +195,7 @@ detailBody ) : null, section ( + setID('comment'), set::title($lang->story->comment), formGroup(editor(set::name('comment'), set::uid($uid))) ) From 66baa117c6e97a9b9e9584c91691b6b985df8a5d Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 30 Apr 2025 03:03:13 +0000 Subject: [PATCH 113/136] * [misc] hide cols when has not feature. --- module/execution/config/dtable.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/execution/config/dtable.php b/module/execution/config/dtable.php index 50081ab515..790d50be86 100644 --- a/module/execution/config/dtable.php +++ b/module/execution/config/dtable.php @@ -49,7 +49,7 @@ $config->execution->dtable->fieldList['status']['width'] = '80'; $config->execution->dtable->fieldList['status']['group'] = '1'; $config->execution->dtable->fieldList['status']['show'] = true; -if(in_array($config->edition, array('max', 'ipd'))) +if(in_array($config->edition, array('max', 'ipd')) && helper::hasFeature('deliverable')) { $config->execution->dtable->fieldList['deliverable']['title'] = $lang->execution->deliverableAbbr; $config->execution->dtable->fieldList['deliverable']['name'] = 'deliverable'; From 1358c966f51d44485cb729d87c8c2fa7f53460a7 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 30 Apr 2025 03:20:25 +0000 Subject: [PATCH 114/136] * [task#142669,done,0.2h] fix bug. --- lib/zin/wg/deliverable/js/v1.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/zin/wg/deliverable/js/v1.js b/lib/zin/wg/deliverable/js/v1.js index bb6af89571..4ca53a2583 100644 --- a/lib/zin/wg/deliverable/js/v1.js +++ b/lib/zin/wg/deliverable/js/v1.js @@ -8,6 +8,13 @@ window.getDeliverableFileActions = function(file, deliverable) if(canDownload && typeof file.id === 'number') actions[0] = {icon: 'download', key: 'download', url: $.createLink('file', 'download', 'id=' + file.id), target: '_blank'}; actions[1] = {icon: 'edit', key: 'rename'}; actions[2] = {icon: 'trash', key: 'delete'}; + + /* 预览图片文件。 */ + if(['txt', 'jpg', 'jpeg', 'gif', 'png', 'bmp', 'mp4'].includes(file.extension) && canDownload) + { + actions[3] = {icon: 'eye', key: 'view', url: $.createLink('file', 'download', `fileID=${file.id}&mouse=left`), 'data-toggle' : 'modal', 'data-size' : 'lg'}; + } + return actions; } From 05be396ed95f5bedbd5c39a10040cbd47be1bc74 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 30 Apr 2025 03:25:42 +0000 Subject: [PATCH 115/136] * [task#142673,done,0.5h] fix bug. --- lib/zin/wg/deliverable/v1.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/zin/wg/deliverable/v1.php b/lib/zin/wg/deliverable/v1.php index 83fcae40eb..dc3c7c86f9 100644 --- a/lib/zin/wg/deliverable/v1.php +++ b/lib/zin/wg/deliverable/v1.php @@ -14,7 +14,8 @@ class deliverable extends wg protected static array $defineProps = array ( 'items: array', // 交付物条目。 - 'formName: string' // 表单名称。 + 'formName: string', // 表单名称。 + 'maxFileSize: string' // 最大文件大小。 ); /** @@ -53,6 +54,15 @@ class deliverable extends wg $formName = $this->prop('formName') ? $this->prop('formName') : 'deliverable'; + if(!$this->hasProp('maxFileSize')) + { + $maxFileSize = ini_get('upload_max_filesize'); + $lastChar = substr($maxFileSize, -1); + $fileSizeUnit = array('K', 'M', 'G', 'T'); + if(in_array($lastChar, $fileSizeUnit)) $maxFileSize .= 'B'; + $this->setProp('maxFileSize', $maxFileSize); + } + return zui::deliverableList ( set::formName($formName), @@ -61,6 +71,7 @@ class deliverable extends wg set::getFileActions(jsRaw('window.getDeliverableFileActions')), set::getDocActions(jsRaw('window.getDocActions')), set::getEmptyActions(jsRaw('window.getDeliverableActions')), + set::maxFileSize($this->prop('maxFileSize')), set::extraCategory($lang->other) ); } From 53896681804065c62971ea768a28667e7ea37657 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 30 Apr 2025 03:27:07 +0000 Subject: [PATCH 116/136] * [task#142710,done,0.2h] fix bug. --- module/tutorial/model.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/tutorial/model.php b/module/tutorial/model.php index 0bacf79939..acb2d40b54 100644 --- a/module/tutorial/model.php +++ b/module/tutorial/model.php @@ -186,6 +186,7 @@ class tutorialModel extends model $project->charter = 0; $project->market = 1; $project->budgetUnit = 'CNY'; + $project->deliverable = ''; list($guide, $guideTask, $guideStepIndex) = empty($_SERVER['HTTP_X_ZIN_TUTORIAL']) ? array('', '', '') : explode('-', $_SERVER['HTTP_X_ZIN_TUTORIAL']); if($guide && strpos($guide, 'scrumProjectManage') !== false) @@ -306,6 +307,7 @@ class tutorialModel extends model $execution->type = 'sprint'; $execution->projectName = ''; $execution->projectModel = 'scrum'; + $execution->deliverable = ''; if($browseType && $browseType != 'all') $execution->name .= '-' . $browseType; From f68a108af310b9edc389406eb6e542e70016a44e Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 30 Apr 2025 04:33:48 +0000 Subject: [PATCH 117/136] * [misc] adjust comment. --- lib/zin/wg/deliverable/js/v1.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/zin/wg/deliverable/js/v1.js b/lib/zin/wg/deliverable/js/v1.js index 4ca53a2583..80fa48a10f 100644 --- a/lib/zin/wg/deliverable/js/v1.js +++ b/lib/zin/wg/deliverable/js/v1.js @@ -9,7 +9,7 @@ window.getDeliverableFileActions = function(file, deliverable) actions[1] = {icon: 'edit', key: 'rename'}; actions[2] = {icon: 'trash', key: 'delete'}; - /* 预览图片文件。 */ + /* 可以预览的文件。 */ if(['txt', 'jpg', 'jpeg', 'gif', 'png', 'bmp', 'mp4'].includes(file.extension) && canDownload) { actions[3] = {icon: 'eye', key: 'view', url: $.createLink('file', 'download', `fileID=${file.id}&mouse=left`), 'data-toggle' : 'modal', 'data-size' : 'lg'}; From 25b56e2d165f18f52a380918795a9c0e6737133a Mon Sep 17 00:00:00 2001 From: wangyuting Date: Wed, 30 Apr 2025 15:17:25 +0800 Subject: [PATCH 118/136] * Adjust update file. --- db/{update21.7.sql => update21.6.1.sql} | 4 ++++ db/update21.6.sql | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) rename db/{update21.7.sql => update21.6.1.sql} (75%) delete mode 100644 db/update21.6.sql diff --git a/db/update21.7.sql b/db/update21.6.1.sql similarity index 75% rename from db/update21.7.sql rename to db/update21.6.1.sql index a1d45d0104..4013d8b988 100644 --- a/db/update21.7.sql +++ b/db/update21.6.1.sql @@ -1,3 +1,7 @@ +ALTER TABLE `zt_relationoftasks` ADD COLUMN `project` mediumint(8) unsigned NOT NULL DEFAULT 0 AFTER `id`; +ALTER TABLE `zt_relationoftasks` MODIFY `execution` char(30) NOT NULL DEFAULT '' AFTER `project`; +UPDATE `zt_relationoftasks` SET `project` = (SELECT `project` FROM `zt_task` WHERE `id` = `zt_relationoftasks`.`task`); + CREATE TABLE IF NOT EXISTS `zt_deliverable` ( `id` int(8) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, diff --git a/db/update21.6.sql b/db/update21.6.sql deleted file mode 100644 index ce5506e56a..0000000000 --- a/db/update21.6.sql +++ /dev/null @@ -1,3 +0,0 @@ -ALTER TABLE `zt_relationoftasks` ADD COLUMN `project` mediumint(8) unsigned NOT NULL DEFAULT 0 AFTER `id`; -ALTER TABLE `zt_relationoftasks` MODIFY `execution` char(30) NOT NULL DEFAULT '' AFTER `project`; -UPDATE `zt_relationoftasks` SET `project` = (SELECT `project` FROM `zt_task` WHERE `id` = `zt_relationoftasks`.`task`); From 5cc20c9f1b1d634d2f28942893e29715cf41df4c Mon Sep 17 00:00:00 2001 From: wangyidong Date: Wed, 30 Apr 2025 14:32:47 +0800 Subject: [PATCH 119/136] * [refac bug #62109] Fix for gantt drag event. --- module/task/model.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/module/task/model.php b/module/task/model.php index 88afbdef3e..4eee20bd84 100755 --- a/module/task/model.php +++ b/module/task/model.php @@ -3247,6 +3247,21 @@ class taskModel extends model if($postData->type == 'task') { + $project = $this->dao->select('id,taskDateLimit')->from(TABLE_PROJECT)->where('id')->eq($oldObject->project)->fetch(); + if($project->taskDateLimit == 'limit') + { + $parentTasks = $this->dao->select('id,estStarted,deadline')->from(TABLE_TASK)->where('id')->in($oldObject->path)->andWhere('id')->ne($oldObject->id)->fetchAll('id'); + foreach(array_reverse(array_filter(explode(',', $oldObject->path))) as $taskID) + { + if(!isset($parentTasks[$taskID])) continue; + + $parentTask = $parentTasks[$taskID]; + if(!helper::isZeroDate($parentTask->estStarted) && $parentTask->estStarted > $postData->startDate) dao::$errors[] = sprintf($this->lang->task->overParentEsStarted, $parentTask->estStarted); + if(!helper::isZeroDate($parentTask->deadline) && $parentTask->deadline < $postData->endDate) dao::$errors[] = sprintf($this->lang->task->overParentDeadline, $parentTask->deadline); + } + if(dao::isError()) return false; + } + $oldObject->estStarted = $postData->startDate; $oldObject->deadline = $postData->endDate; unset($oldObject->openedDate); From afbbaa6945b5177518669f8e73133d521adf86c8 Mon Sep 17 00:00:00 2001 From: wangyidong Date: Wed, 30 Apr 2025 15:33:43 +0800 Subject: [PATCH 120/136] * [refac bug #62124] Check parent estStarted and deadline fields. --- module/task/zen.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/task/zen.php b/module/task/zen.php index 678816d78a..20f24b93a1 100644 --- a/module/task/zen.php +++ b/module/task/zen.php @@ -1049,8 +1049,8 @@ class taskZen extends task if(!$beginIsZeroDate and !$endIsZeroDate and $task->deadline < $task->estStarted) dao::$errors[$endIndex] = $this->lang->task->error->deadlineSmall; if(!$isDateLimit || empty($parent)) return; - if(!$beginIsZeroDate and $task->estStarted < $parent->estStarted) dao::$errors[$beginIndex] = sprintf($this->lang->task->overParentEsStarted, $parent->estStarted); - if(!$endIsZeroDate and $task->deadline > $parent->deadline) dao::$errors[$endIndex] = sprintf($this->lang->task->overParentDeadline, $parent->deadline); + if(!$beginIsZeroDate && !helper::isZeroDate($parent->estStarted) && $task->estStarted < $parent->estStarted) dao::$errors[$beginIndex] = sprintf($this->lang->task->overParentEsStarted, $parent->estStarted); + if(!$endIsZeroDate && !helper::isZeroDate($parent->deadline) && $task->deadline > $parent->deadline) dao::$errors[$endIndex] = sprintf($this->lang->task->overParentDeadline, $parent->deadline); } /** From 910cbbe584dee498b76b7ac3156fbe5311e79f6f Mon Sep 17 00:00:00 2001 From: wangyuting Date: Wed, 30 Apr 2025 16:12:21 +0800 Subject: [PATCH 121/136] * [bug#61986,done,1h,0h] Fix submit form error close project. --- module/project/ui/close.html.php | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/module/project/ui/close.html.php b/module/project/ui/close.html.php index c5d6fd2c23..a6e6f27dc1 100644 --- a/module/project/ui/close.html.php +++ b/module/project/ui/close.html.php @@ -10,25 +10,11 @@ declare(strict_types=1); */ namespace zin; -$beforeSubmit = jsRaw("() => -{ - zui.Modal.confirm('{$confirmTip}').then((res) => - { - if(res) - { - const formData = new FormData($('#zin_project_close_{$project->id}_form')[0]); - const url = $('#zin_project_close_{$project->id}_form').attr('action'); - $.ajaxSubmit({url: url, data: formData}); - } - }); - return false; -}"); - modalHeader(); formPanel ( set::formID("zin_project_close_{$project->id}_form"), - !empty($confirmTip) ? set::ajax(array('beforeSubmit' => $beforeSubmit)) : null, + set::ajax(array('beforeSubmit' => jsRaw("() => zui.Modal.confirm('{$confirmTip}')"))), formGroup ( set::width('1/2'), From 541b858703936ddbe1e5b4153adda4ef40bc249f Mon Sep 17 00:00:00 2001 From: wangyuting Date: Wed, 30 Apr 2025 16:20:40 +0800 Subject: [PATCH 122/136] * Optimize code. --- module/project/ui/close.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/project/ui/close.html.php b/module/project/ui/close.html.php index a6e6f27dc1..bac2aa3438 100644 --- a/module/project/ui/close.html.php +++ b/module/project/ui/close.html.php @@ -14,7 +14,7 @@ modalHeader(); formPanel ( set::formID("zin_project_close_{$project->id}_form"), - set::ajax(array('beforeSubmit' => jsRaw("() => zui.Modal.confirm('{$confirmTip}')"))), + !empty($confirmTip) ? set::ajax(array('beforeSubmit' => jsRaw("() => zui.Modal.confirm('{$confirmTip}')"))) : null, formGroup ( set::width('1/2'), From 42c2b07f39735ee6b1a57bb34ddbcf78ad6f44b3 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 6 May 2025 00:57:52 +0000 Subject: [PATCH 123/136] * [task#142740,done,0.2h] finish task. --- module/project/zen.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/module/project/zen.php b/module/project/zen.php index 414a8478e4..dc54beeaa7 100755 --- a/module/project/zen.php +++ b/module/project/zen.php @@ -484,6 +484,12 @@ class projectZen extends project $this->view->programID = $programID; $this->view->disableParent = $disableParent; $this->view->groups = $this->loadModel('group')->getPairs(); + + if(in_array($this->config->edition, array('max', 'ipd')) && $this->project->checkUploadedDeliverable($project)) + { + $this->view->disableModel = true; + } + $this->display(); } From 29733a8dbdb36dd72940b7a9db34ac5014440c6d Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 6 May 2025 03:21:39 +0000 Subject: [PATCH 124/136] * [task#142830,done,0.2h] fix bug. --- module/programplan/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/programplan/model.php b/module/programplan/model.php index 7885818321..79cb16d6c4 100755 --- a/module/programplan/model.php +++ b/module/programplan/model.php @@ -620,7 +620,7 @@ class programplanModel extends model $parent = $this->execution->getByID((int)$id); /* 如果当前是顶级阶段,并且由于交付物不能关闭,则跳转到顶级阶段的关闭页面。 */ - $isTopStage = $parent->grade == 1 && $parent->type != 'project' && $stageID != $id; + $isTopStage = $parent->grade == 1 && $parent->type != 'project' && $stageID != $id && $parent->status == 'doing'; if(in_array($this->config->edition, array('max', 'ipd')) && $isTopStage && !$this->execution->canCloseByDeliverable($parent)) { $url = helper::createLink('execution', 'close', "executionID={$parent->id}"); From a45946f2234d3309a288145c6a509f59d8652de4 Mon Sep 17 00:00:00 2001 From: wangyidong Date: Tue, 6 May 2025 14:04:39 +0800 Subject: [PATCH 125/136] * [refac bug #62091] Check legally date for batch create. --- module/task/zen.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/module/task/zen.php b/module/task/zen.php index 20f24b93a1..bcb386a3c9 100644 --- a/module/task/zen.php +++ b/module/task/zen.php @@ -1100,11 +1100,14 @@ class taskZen extends task if($this->task->isNoStoryExecution($execution)) $requiredFields = str_replace(',story,', ',', ',' . $requiredFields . ','); $requiredFields = array_filter(explode(',', $requiredFields)); + $levels = array(); $project = $this->loadModel('project')->fetchById($execution->project); $parentIdList = array_filter(array_column($tasks, 'parent', 'parent')); $parents = $this->getParentEstStartedAndDeadline($parentIdList); foreach($tasks as $rowIndex => $task) { + $levels[$task->level] = $rowIndex; + if(mb_strlen($task->name) > 255) dao::$errors["name[$rowIndex]"] = sprintf($this->lang->task->error->length, 255); if(!empty($this->post->estimate[$rowIndex]) and !preg_match("/^[0-9]+(.[0-9]+)?$/", (string)$this->post->estimate[$rowIndex])) { @@ -1120,7 +1123,9 @@ class taskZen extends task dao::$errors["deadline[$rowIndex]"] = $this->lang->task->error->deadlineSmall; } - $this->checkLegallyDate($task, $project->taskDateLimit == 'limit', isset($parents[$task->parent]) ? $parents[$task->parent] : null, $rowIndex); + $parentTask = isset($parents[$task->parent]) ? $parents[$task->parent] : null; + if($task->level > 0 && isset($levels[$task->level - 1])) $parentTask = zget($tasks, $levels[$task->level - 1], null); + $this->checkLegallyDate($task, $project->taskDateLimit == 'limit', $parentTask, $rowIndex); /* Check if the estimate is positive. */ if($task->estimate < 0) dao::$errors["estimate[$rowIndex]"] = $this->lang->task->error->recordMinus; From 754653306c544b856cf4a10ea8502106216313a5 Mon Sep 17 00:00:00 2001 From: wangyidong Date: Tue, 6 May 2025 14:53:11 +0800 Subject: [PATCH 126/136] * [refac bug #62097] compute begin and end only taskDateLimit is not limit. --- module/task/model.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/module/task/model.php b/module/task/model.php index 4eee20bd84..bfc68f5eb5 100755 --- a/module/task/model.php +++ b/module/task/model.php @@ -821,6 +821,11 @@ class taskModel extends model $tasks = $this->dao->select('estStarted, realStarted, deadline')->from(TABLE_TASK)->where('parent')->eq($taskID)->andWhere('status')->ne('cancel')->andWhere('deleted')->eq(0)->fetchAll(); if(empty($tasks)) return !dao::isError(); + /* Initialize task data and update it. */ + $parent = $this->fetchById($taskID); + $taskDateLimit = $this->dao->select('taskDateLimit')->from(TABLE_PROJECT)->where('id')->eq($parent->project)->fetch('taskDateLimit'); + if($taskDateLimit == 'limit') return !dao::isError(); + /* Compute the earliest estStarted, the earliest realStarted and the latest deadline. */ $earliestEstStarted = ''; $earliestRealStarted = ''; @@ -832,9 +837,6 @@ class taskModel extends model if(!helper::isZeroDate($task->deadline) && (empty($latestDeadline) || $latestDeadline < $task->deadline)) $latestDeadline = $task->deadline; } - /* Initialize task data and update it. */ - $parent = $this->fetchById($taskID); - $newTask = array(); if(!empty($earliestEstStarted) && !helper::isZeroDate($parent->estStarted) && $parent->estStarted > $earliestEstStarted) $newTask['estStarted'] = $earliestEstStarted; if(!empty($earliestRealStarted) && !helper::isZeroDate($parent->realStarted) && $parent->realStarted > $earliestRealStarted) $newTask['realStarted'] = $earliestRealStarted; From b95ae2d5785f8e9fb0e5d655f53f7c953bf27829 Mon Sep 17 00:00:00 2001 From: wangyidong Date: Wed, 7 May 2025 13:27:00 +0800 Subject: [PATCH 127/136] * [refac bug #61926] Disable delete btn for ipd. --- module/programplan/js/create.ui.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/module/programplan/js/create.ui.js b/module/programplan/js/create.ui.js index ae02e2ab85..11cf55157d 100644 --- a/module/programplan/js/create.ui.js +++ b/module/programplan/js/create.ui.js @@ -212,7 +212,11 @@ window.handleRenderRow = function($row, index, data) if(project.model == 'ipd') { if(planID == 0) $row.find('[data-name="ACTIONS"]').find('[data-type="sort"]').addClass('hidden'); - if(level == 0 && planID == 0) $row.find('[data-name="ACTIONS"]').find('[data-type="addSibling"]').addClass('disabled').prop('disabled', true); + if(level == 0 && planID == 0) + { + $row.find('[data-name="ACTIONS"]').find('[data-type="addSibling"]').addClass('disabled').prop('disabled', true); + $row.find('[data-name="ACTIONS"]').find('[data-type="delete"]').addClass('disabled').prop('disabled', true); + } $row.find('[data-name="attribute"]').find('.picker-box').on('inited', function(e, info){ info[0].render({disabled: true}); }); From ea482bf228e8f739025758e1a9271252a01e1495 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Wed, 7 May 2025 06:19:02 +0000 Subject: [PATCH 128/136] * [bug#62234,done,0.2h] fix bug. --- module/programplan/model.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/module/programplan/model.php b/module/programplan/model.php index 79cb16d6c4..7a5de25580 100755 --- a/module/programplan/model.php +++ b/module/programplan/model.php @@ -619,14 +619,6 @@ class programplanModel extends model { $parent = $this->execution->getByID((int)$id); - /* 如果当前是顶级阶段,并且由于交付物不能关闭,则跳转到顶级阶段的关闭页面。 */ - $isTopStage = $parent->grade == 1 && $parent->type != 'project' && $stageID != $id && $parent->status == 'doing'; - if(in_array($this->config->edition, array('max', 'ipd')) && $isTopStage && !$this->execution->canCloseByDeliverable($parent)) - { - $url = helper::createLink('execution', 'close', "executionID={$parent->id}"); - return array('result' => 'fail', 'callback' => "zui.Modal.confirm('{$this->lang->execution->cannotAutoCloseParent}').then((res) => {if(res) {loadModal('$url', '.modal-dialog');} else {loadPage();}});"); - } - if(empty($this->lang->execution->typeList[$parent->type]) || (!$isParent && $id == $stageID)) continue; /** 获取子阶段关联开始任务数以及状态下子阶段数量。 */ @@ -647,6 +639,17 @@ class programplanModel extends model $newParent = $result['newParent'] ?? null; $parentAction = $result['parentAction'] ?? ''; + /* 如果当前是顶级阶段,并且由于交付物不能关闭,则跳转到顶级阶段的关闭页面。 */ + if(isset($newParent->status) && $newParent->status == 'closed') + { + $isTopStage = $parent->grade == 1 && $parent->type != 'project' && $stageID != $id && $parent->status == 'doing'; + if(in_array($this->config->edition, array('max', 'ipd')) && $isTopStage && !$this->execution->canCloseByDeliverable($parent)) + { + $url = helper::createLink('execution', 'close', "executionID={$parent->id}"); + return array('result' => 'fail', 'callback' => "zui.Modal.confirm('{$this->lang->execution->cannotAutoCloseParent}').then((res) => {if(res) {loadModal('$url', '.modal-dialog');} else {loadPage();}});"); + } + } + /** 更新状态以及记录日志。 */ /** Update status and save log. */ if(isset($newParent) && $newParent) From 19504be571790bd792531cc9b788f48dcec919a5 Mon Sep 17 00:00:00 2001 From: wangyidong Date: Wed, 7 May 2025 14:45:38 +0800 Subject: [PATCH 129/136] * [refac bug #62111] Disabled estStarted and deadline field when parent task is null. --- module/task/js/batchcreate.ui.js | 35 +++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/module/task/js/batchcreate.ui.js b/module/task/js/batchcreate.ui.js index d0e448f848..d79f94c944 100644 --- a/module/task/js/batchcreate.ui.js +++ b/module/task/js/batchcreate.ui.js @@ -162,6 +162,20 @@ function checkBatchEstStartedAndDeadline(event) const field = $(event.target).closest('.form-batch-control').data('name'); const estStarted = $currentRow.find('[name^=estStarted]').val(); const deadline = $currentRow.find('[name^=deadline]').val(); + const level = $currentRow.attr('data-level'); + + $nextRow = $currentRow.next(); + while($nextRow.length) + { + let nextLevel = $nextRow.attr('data-level'); + if(nextLevel <= level) break; + + if(field == 'estStarted') $nextRow.find('td[data-name=estStarted]').find('[id^=estStarted]').zui('datepicker').render({disabled: estStarted == ''}); + if(field == 'deadline') $nextRow.find('td[data-name=deadline]').find('[id^=deadline]').zui('datepicker').render({disabled: deadline == ''}); + + $nextRow = $nextRow.next(); + } + if($currentRow.find('td[data-name=name]').find('input[name^=name]').val() == '') return; const $estStartedTd = $currentRow.find('td[data-name=estStarted]'); @@ -277,10 +291,25 @@ window.handleRenderRow = function($row, index) if($preAssignedTo != undefined) $assignedTo.render({items: $preAssignedTo.options.items}); }) - if(taskDateLimit == 'limit' && parentID) + if(taskDateLimit == 'limit') { - $row.find('[data-name=estStarted]').find('[id^=estStarted]').on('inited', function(e, info) { info[0].render({disabled: parentEstStarted == ''}); }) - $row.find('[data-name=deadline]').find('[id^=deadline]').on('inited', function(e, info) { info[0].render({disabled: parentDeadline == ''}); }) + let disabledStarted = false; + let disabledDeadline = false; + if(parentID) + { + disabledStarted = parentEstStarted == ''; + disabledDeadline = parentDeadline == ''; + } + else if(parentID == 0 && level > 0) + { + const $prevLevelRow = $row.prev('tr[data-level="' + (level - 1) + '"]'); + const $prevLevelStarted = $prevLevelRow.find('td[data-name=estStarted]').find('[id^=estStarted]'); + const $prevLevelDeadline = $prevLevelRow.find('td[data-name=deadline]').find('[id^=deadline]'); + disabledStarted = $prevLevelStarted.val() == '' || $prevLevelStarted.prop('disabled'); + disabledDeadline = $prevLevelDeadline.val() == '' || $prevLevelDeadline.prop('disabled'); + } + $row.find('td[data-name=estStarted]').find('[id^=estStarted]').on('inited', function(e, info) { info[0].render({disabled: disabledStarted}); }) + $row.find('td[data-name=deadline]').find('[id^=deadline]').on('inited', function(e, info) { info[0].render({disabled: disabledDeadline}); }) } }; From 400d29be309db376a2ebabef6aaefb149b1c0ccc Mon Sep 17 00:00:00 2001 From: wangyidong Date: Wed, 7 May 2025 14:48:27 +0800 Subject: [PATCH 130/136] * [refac bug #62111Adjust code. --- module/task/js/batchcreate.ui.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/task/js/batchcreate.ui.js b/module/task/js/batchcreate.ui.js index d79f94c944..bb139ef6d2 100644 --- a/module/task/js/batchcreate.ui.js +++ b/module/task/js/batchcreate.ui.js @@ -164,7 +164,7 @@ function checkBatchEstStartedAndDeadline(event) const deadline = $currentRow.find('[name^=deadline]').val(); const level = $currentRow.attr('data-level'); - $nextRow = $currentRow.next(); + let $nextRow = $currentRow.next(); while($nextRow.length) { let nextLevel = $nextRow.attr('data-level'); From b2bf396955f17f5051371820191b5bb5dc85b312 Mon Sep 17 00:00:00 2001 From: wangyidong Date: Wed, 7 May 2025 15:23:36 +0800 Subject: [PATCH 131/136] * [refac bug #62083] Adjust for task start and end field for gantt. --- module/programplan/tao.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/module/programplan/tao.php b/module/programplan/tao.php index 95488bf033..f6da94a6a5 100644 --- a/module/programplan/tao.php +++ b/module/programplan/tao.php @@ -276,10 +276,12 @@ class programplanTao extends programplanModel $taskTeams = $this->dao->select('task,account')->from(TABLE_TASKTEAM)->where('task')->in(array_keys($tasks))->fetchGroup('task', 'account'); $users = $this->loadModel('user')->getPairs('noletter'); + $firstTask = reset($tasks); + $taskDateLimit = $this->dao->select('taskDateLimit')->from(TABLE_PROJECT)->where('id')->eq($firstTask->project)->fetch('taskDateLimit'); foreach($tasks as $task) { $plan = zget($plans, $task->execution, null); - $dateLimit = $this->getTaskDateLimit($task, $plan); + $dateLimit = $this->getTaskDateLimit($task, $plan, $taskDateLimit == 'limit' ? zget($tasks, $task->parent, null) : null); $data = $this->buildTaskDataForGantt($task, $dateLimit); $data->id = $task->execution . '-' . $task->id; $data->parent = $task->parent > 0 && isset($tasks[$task->parent]) ? $task->execution . '-' . $task->parent : $task->execution; @@ -870,16 +872,23 @@ class programplanTao extends programplanModel * * @param object $task * @param object|null $execution + * @param object|null $parent * @access protected * @return array */ - protected function getTaskDateLimit(object $task, object|null $execution = null): array + protected function getTaskDateLimit(object $task, object|null $execution = null, object|null $parent = null): array { $estStart = helper::isZeroDate($task->estStarted) ? '' : $task->estStarted; $estEnd = helper::isZeroDate($task->deadline) ? '' : $task->deadline; $realBegan = helper::isZeroDate($task->realStarted) ? '' : $task->realStarted; $realEnd = (in_array($task->status, array('done', 'closed')) and !helper::isZeroDate($task->finishedDate)) ? $task->finishedDate : ''; + if($parent) + { + if(empty($estStart) && !helper::isZeroDate($parent->estStarted)) $estStart = $parent->estStarted; + if(empty($estEnd) && !helper::isZeroDate($parent->deadline)) $estEnd = $parent->deadline; + } + $start = $estStart; $end = $estEnd; if(empty($start) and $execution) $start = $execution->begin; From 858bf2ee4e050fe78f2e2eef33fa14c916bbd66d Mon Sep 17 00:00:00 2001 From: wangyidong Date: Wed, 7 May 2025 16:01:41 +0800 Subject: [PATCH 132/136] * [refac bug #62114] Adjust checkEstStartedAndDeadline method. --- module/task/model.php | 15 +++++++++------ module/task/zen.php | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/module/task/model.php b/module/task/model.php index bfc68f5eb5..dc7b4f08c3 100755 --- a/module/task/model.php +++ b/module/task/model.php @@ -749,26 +749,29 @@ class taskModel extends model * @param int $executionID * @param string $estStarted * @param string $deadline - * @param string $prefix + * @param int|null $rowID * @access public * @return false|void */ - public function checkEstStartedAndDeadline(int $executionID, string $estStarted, string $deadline, string $prefix = '') + public function checkEstStartedAndDeadline(int $executionID, string $estStarted, string $deadline, int|null $rowID = null) { + $beginIndex = $rowID === null ? 'estStarted' : "estStarted[$rowID]"; + $endIndex = $rowID === null ? 'deadline' : "deadline[$rowID]"; + $execution = $this->loadModel('execution')->getByID($executionID); if(empty($execution) || empty($this->config->limitTaskDate)) return false; if(empty($execution->multiple)) $this->lang->execution->common = $this->lang->project->common; if(!empty($estStarted) && !helper::isZeroDate($estStarted)) { - if($estStarted < $execution->begin) dao::$errors['estStarted'] = $prefix . sprintf($this->lang->task->error->beginLtExecution, $this->lang->execution->common, $execution->begin); - if($estStarted > $execution->end) dao::$errors['estStarted'] = $prefix . sprintf($this->lang->task->error->beginGtExecution, $this->lang->execution->common, $execution->end); + if($estStarted < $execution->begin) dao::$errors[$beginIndex] = sprintf($this->lang->task->error->beginLtExecution, $this->lang->execution->common, $execution->begin); + if($estStarted > $execution->end) dao::$errors[$beginIndex] = sprintf($this->lang->task->error->beginGtExecution, $this->lang->execution->common, $execution->end); } if(!empty($deadline) && !helper::isZeroDate($deadline)) { - if($deadline > $execution->end) dao::$errors['deadline'] = $prefix . sprintf($this->lang->task->error->endGtExecution, $this->lang->execution->common, $execution->end); - if($deadline < $execution->begin) dao::$errors['deadline'] = $prefix . sprintf($this->lang->task->error->endLtExecution, $this->lang->execution->common, $execution->begin); + if($deadline > $execution->end) dao::$errors[$endIndex] = sprintf($this->lang->task->error->endGtExecution, $this->lang->execution->common, $execution->end); + if($deadline < $execution->begin) dao::$errors[$endIndex] = sprintf($this->lang->task->error->endLtExecution, $this->lang->execution->common, $execution->begin); } } diff --git a/module/task/zen.php b/module/task/zen.php index bcb386a3c9..ca5c091b8e 100644 --- a/module/task/zen.php +++ b/module/task/zen.php @@ -1168,7 +1168,7 @@ class taskZen extends task if($task->consumed < 0 ) dao::$errors["consumed[{$taskID}]"] = (array)sprintf($this->lang->task->error->recordMinus, $this->lang->task->consumedThisTime); if($task->left < 0) dao::$errors["left[$taskID]"] = (array)sprintf($this->lang->task->error->recordMinus, $this->lang->task->leftAB); - if(!empty($this->config->limitTaskDate)) $this->task->checkEstStartedAndDeadline($oldTask->execution, (string)$task->estStarted, (string)$task->deadline, "task:{$taskID} "); + if(!empty($this->config->limitTaskDate)) $this->task->checkEstStartedAndDeadline($oldTask->execution, (string)$task->estStarted, (string)$task->deadline, $taskID); if($task->status == 'cancel') continue; if($task->status == 'done' && !$task->consumed) dao::$errors["consumed[{$taskID}]"] = (array)sprintf($this->lang->error->notempty, $this->lang->task->consumedThisTime); From b031c26c0f7ca386818066292c394b9f7e800bac Mon Sep 17 00:00:00 2001 From: wangyidong Date: Wed, 7 May 2025 16:12:41 +0800 Subject: [PATCH 133/136] * [refac bug #62198] Add h-auto class style. --- module/transfer/ui/import.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/transfer/ui/import.html.php b/module/transfer/ui/import.html.php index cbf556678e..5a29070e0f 100644 --- a/module/transfer/ui/import.html.php +++ b/module/transfer/ui/import.html.php @@ -22,6 +22,6 @@ formPanel set::items($typeList) ) : null, input(set::type('file'), set::name('file')), - span(setClass('label secondary'), $lang->transfer->importNotice) + span(setClass('label secondary h-auto'), $lang->transfer->importNotice) ); h::js('$.cookie.set("maxImport", 0, {expires:config.cookieLife, path:config.webRoot});'); From 70935c13a673566bd0e3d615e9146976d24f993d Mon Sep 17 00:00:00 2001 From: wangyidong Date: Thu, 8 May 2025 11:20:07 +0800 Subject: [PATCH 134/136] * [refac bug #62109] Adjust synchronous request for gantt. --- lib/zin/wg/gantt/js/v1.js | 47 +++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/lib/zin/wg/gantt/js/v1.js b/lib/zin/wg/gantt/js/v1.js index e671487dc7..5938d8fad4 100644 --- a/lib/zin/wg/gantt/js/v1.js +++ b/lib/zin/wg/gantt/js/v1.js @@ -270,7 +270,6 @@ function validateResources(id) let status = task.status; let type = task.type; let statusLang = ganttLang.taskStatusList['wait']; - flag = true; /* Check status. */ if(status !== statusLang && type != 'point') @@ -292,32 +291,26 @@ function validateResources(id) if(type == 'point') itemID = task.id.split("-")[2]; /* Check data. */ - let postData = { - 'id' : itemID, - 'startDate' : from.toLocaleDateString('en-CA'), - 'endDate' : to.toLocaleDateString('en-CA'), - 'type' : type - }; - /* Sync Close. */ - $.ajax({ - url: $.createLink('programplan', 'ajaxResponseGanttDragEvent'), - dataType: "json", - data: postData, - type: "post", - success: function(response) - { - if(response.result == 'fail' && response.message) - { - zui.Messager.show({content: response.message, type: 'danger-outline', icon: 'exclamation-sign'}); - flag = false; - } - else - { - gantt.updateTask(task.id, task); - if(task.parent) changeParentTask(task, task.parent); - } - } - }); + const postData = 'id=' + itemID + '&startDate=' + from.toLocaleDateString('en-CA') + '&endDate=' + to.toLocaleDateString('en-CA') + '&type=' +type; + + const xhr = new XMLHttpRequest(); + xhr.open('POST', $.createLink('programplan', 'ajaxResponseGanttDragEvent'), false); // 同步模式 + xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + xhr.send(postData); + + let flag = true; + const response = JSON.parse(xhr.responseText); + if(response.result == 'fail' && response.message) + { + zui.Messager.show({content: response.message, type: 'danger-outline', icon: 'exclamation-sign'}); + flag = false; + } + else + { + gantt.updateTask(task.id, task); + if(task.parent) changeParentTask(task, task.parent); + } return flag; } From 946988314c251aee2334f2d75872861227a2a849 Mon Sep 17 00:00:00 2001 From: wangyuting Date: Thu, 8 May 2025 16:41:25 +0800 Subject: [PATCH 135/136] * [bug#142840,done,0.1h,0h] Optimize deliverable history. --- module/action/model.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/module/action/model.php b/module/action/model.php index 70d48302ab..283c084e68 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -1495,7 +1495,14 @@ class actionModel extends model } else { - $content .= sprintf($this->lang->action->desc->diff1, $history->fieldLabel, $history->old, $history->new); + if($history->field == 'deliverable') + { + $content .= $this->processDeliverableJson($history); + } + else + { + $content .= sprintf($this->lang->action->desc->diff1, $history->fieldLabel, $history->old, $history->new); + } } } return $content; From 54593f36a20bc840951f3cde984b449744ecd420 Mon Sep 17 00:00:00 2001 From: wangyuting Date: Fri, 9 May 2025 08:48:28 +0800 Subject: [PATCH 136/136] * [bug#142840,done,1h,0h] Optimize execution deliverable history. --- module/action/model.php | 14 ++++++++------ module/common/view/action.html.php | 2 +- module/common/view/mail.footer.html.php | 2 +- module/execution/model.php | 6 +++--- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/module/action/model.php b/module/action/model.php index 283c084e68..3f743c0a21 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -948,7 +948,7 @@ class actionModel extends model $action->actor = zget($users, $action->actor); if(str_contains($action->actor, ':')) $action->actor = substr($action->actor, strpos($action->actor, ':') + 1); - if(!empty($action->history)) $item->historyChanges = $this->renderChanges($action->objectType, $action->history); + if(!empty($action->history)) $item->historyChanges = $this->renderChanges($action->objectType, $action->objectID, $action->history); $item->id = $action->id; $item->action = $action->action; @@ -1440,12 +1440,13 @@ class actionModel extends model * Render histories of every action. * * @param string $objectType + * @param int $objectID * @param array $histories * @param bool $canChangeTag * @access public * @return string */ - public function renderChanges(string $objectType, array $histories, bool $canChangeTag = true): string + public function renderChanges(string $objectType, int $objectID, array $histories, bool $canChangeTag = true): string { if(empty($histories)) return ''; @@ -1495,9 +1496,9 @@ class actionModel extends model } else { - if($history->field == 'deliverable') + if($history->field == 'deliverable' && ($objectType == 'project' || $objectType == 'execution')) { - $content .= $this->processDeliverableJson($history); + $content .= $this->processDeliverableJson($objectType, $objectID, $history); } else { @@ -1513,14 +1514,15 @@ class actionModel extends model * Print histories of every action. * * @param string $objectType + * @param int $objectID * @param array $histories * @param bool $canChangeTag * @access public * @return void */ - public function printChanges(string $objectType, array $histories, bool $canChangeTag = true): void + public function printChanges(string $objectType, int $objectID, array $histories, bool $canChangeTag = true): void { - $content = $this->renderChanges($objectType, $histories, $canChangeTag); + $content = $this->renderChanges($objectType, $objectID, $histories, $canChangeTag); if(is_string($content)) echo $content; } diff --git a/module/common/view/action.html.php b/module/common/view/action.html.php index d1dadede7f..46c53b7416 100755 --- a/module/common/view/action.html.php +++ b/module/common/view/action.html.php @@ -61,7 +61,7 @@ history)):?>
- action->printChanges($action->objectType, $action->history);?> + action->printChanges($action->objectType, $action->objectID, $action->history);?>
comment))) != 0):?> diff --git a/module/common/view/mail.footer.html.php b/module/common/view/mail.footer.html.php index 3d8d365619..3f632ce7b5 100644 --- a/module/common/view/mail.footer.html.php +++ b/module/common/view/mail.footer.html.php @@ -28,7 +28,7 @@ if(file_exists($extViewFile)) history)):?> -
action->printChanges($action->objectType, $action->history, false);?>
+
action->printChanges($action->objectType, $action->objectID, $action->history, false);?>
diff --git a/module/execution/model.php b/module/execution/model.php index 6c24c21e3d..213d135ced 100755 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -914,9 +914,9 @@ class executionModel extends model * @param int $executionID * @param object $postData * @access public - * @return array|false + * @return int|false */ - public function close(int $executionID, object $postData): array|false + public function close(int $executionID, object $postData): int|false { $oldExecution = $this->fetchById($executionID); /* Save previous execution to variable for later compare. */ @@ -945,7 +945,7 @@ class executionModel extends model } $this->loadModel('score')->create('execution', 'close', $oldExecution); - return $changes; + return $actionID; } /**