diff --git a/lib/zin/func.php b/lib/zin/func.php
index 4df2fdb7fc..c453ec27d0 100644
--- a/lib/zin/func.php
+++ b/lib/zin/func.php
@@ -963,3 +963,14 @@ function floatToolbar()
{
return createWg('floatToolbar', func_get_args());
}
+
+/**
+ * zentao data group.
+ *
+ * string label,
+ * string labelClass?
+ */
+function dataGroup()
+{
+ return createWg('dataGroup', func_get_args());
+}
diff --git a/lib/zin/wg/datagroup/v1.php b/lib/zin/wg/datagroup/v1.php
new file mode 100644
index 0000000000..903a40a114
--- /dev/null
+++ b/lib/zin/wg/datagroup/v1.php
@@ -0,0 +1,34 @@
+prop('labelClass');
+
+ return div
+ (
+ setClass($className, 'text-gray', 'text-right', 'w-16'),
+ $text
+ );
+ }
+
+ protected function build()
+ {
+ $text = $this->prop('label');
+
+ return div
+ (
+ set($this->props->skip(array_keys(static::getDefinedProps()))),
+ setClass('data-group flex justify-start gap-2 my-4'),
+ $this->label($text),
+ $this->children(),
+ );
+ }
+}
diff --git a/module/block/control.php b/module/block/control.php
index f8a3d8cdc3..4d8d9c0644 100755
--- a/module/block/control.php
+++ b/module/block/control.php
@@ -228,16 +228,20 @@ class block extends control
*/
public function dashboard(string $dashboard, string $projectID = '0')
{
- $projectID = (int)$projectID;
+ $projectID = (int)$projectID; // 强制转换为 int 类型,防止调用 model、tao 方法时报错
+
+ /* 获取传入应用对应的区块列表 以及 获取当前应用下区块启用状态 */
$blocks = $this->block->getMyDashboard($dashboard);
$isInitiated = $this->block->fetchBlockInitStatus($dashboard);
- /* Init block when vist index first. */
- if(empty($blocks) and !$isInitiated and !defined('TUTORIAL') and $this->block->initBlock($dashboard))
+ /* 判断用户是否为首次登录 ,判断条件 当前用户没有该 app 下的区块数据 且 没有设置过该 app 下的区块启用状态 且不是演示模式 */
+ if(empty($blocks) and !$isInitiated and !defined('TUTORIAL'))
{
- return print(js::reload());
+ $this->block->initBlock($dashboard); // 初始化该 app 下区块数据
+ $blocks = $this->block->getMyDashboard($dashboard); // 获取初始化后的区块列表
}
+ /* */
$blocks = $this->blockZen->processBlockForRender($blocks, $projectID);
if($this->app->getViewType() == 'json') return print(json_encode($blocks));
diff --git a/module/block/model.php b/module/block/model.php
index f776c11294..32764c870f 100644
--- a/module/block/model.php
+++ b/module/block/model.php
@@ -298,7 +298,7 @@ class blockModel extends model
/**
* Reset dashboard blocks.
*
- * @param string $dashboard
+ * @param string $dashboard
* @access public
* @return bool
*/
@@ -323,7 +323,7 @@ class blockModel extends model
/**
* Hidden a block.
*
- * @param int $blockID
+ * @param int $blockID
* @access public
* @return bool
*/
@@ -341,7 +341,7 @@ class blockModel extends model
/**
* Delete a block.
*
- * @param int $blockID
+ * @param int $blockID
* @access public
* @return bool
*/
@@ -358,9 +358,9 @@ class blockModel extends model
/**
* Set block order.
- *
- * @param int $blockID
- * @param int $order
+ *
+ * @param int $blockID
+ * @param int $order
* @access public
* @return bool
*/
diff --git a/module/block/tao.php b/module/block/tao.php
index bbc9191f0a..716d91b0f9 100644
--- a/module/block/tao.php
+++ b/module/block/tao.php
@@ -3,10 +3,10 @@ declare(strict_types=1);
class blockTao extends blockModel
{
/**
- * Get block list of current user.
* 获取当前用户的区块列表.
+ * Get block list of current user.
*
- * @param string $module
+ * @param string $dashboard
* @param int $hidden 0|1
* @access protected
* @return int[]|false
diff --git a/module/block/zen.php b/module/block/zen.php
index 447873f998..2703d35e2d 100644
--- a/module/block/zen.php
+++ b/module/block/zen.php
@@ -153,47 +153,50 @@ class blockZen extends block
*/
protected function processBlockForRender(array $blocks, int $projectID): array
{
+ /* 根据用户的权限,和当前系统开启的权限 处理区块列表 */
$acls = $this->app->user->rights['acls'];
foreach($blocks as $key => $block)
{
+ /* 将没有开启功能区块过虑 */
if($block->code == 'waterfallrisk' and !helper::hasFeature("waterfall_risk")) continue;
if($block->code == 'waterfallissue' and !helper::hasFeature("waterfall_issue")) continue;
if($block->code == 'scrumrisk' and !helper::hasFeature("scrum_risk")) continue;
if($block->code == 'scrumissue' and !helper::hasFeature("scrum_issue")) continue;
- if(!empty($block->source) and $block->source != 'todo' and !empty($acls['views']) and !isset($acls['views'][$block->source]))
+ /* 将没有视图权限的区块过滤 */
+ if(!empty($block->module) and $block->module != 'todo' and !empty($acls['views']) and !isset($acls['views'][$block->module]))
{
unset($blocks[$key]);
continue;
}
+ /* 处理 params 信息中 count 的值,当没有 count 字段时 ,将 num 字段赋值给 count */
$block->params = json_decode($block->params);
if(isset($block->params->num) and !isset($block->params->count)) $block->params->count = $block->params->num;
- $this->getBlockMoreLink($block, $projectID);
+ /* 补全加载链接 */
+ $this->computeMoreLink($block, $projectID);
}
-
return $blocks;
}
/**
- * 获取区块的更多链接。
+ * 补全区块的加载链接。
* Get the more link of the block.
*
* @param object $block
* @param int $projectID
* @return void
*/
- private function getBlockMoreLink(object $block, int $projectID): void
+ private function computeMoreLink(object $block, int $projectID): void
{
- $code = $block->code;
- $source = empty($block->source) ? 'common' : $block->source;
+ $module = empty($block->module) ? 'common' : $block->module;
$block->blockLink = $this->createLink('block', 'printBlock', "id=$block->id&module=$block->module");
$block->moreLink = '';
- if(isset($this->config->block->modules[$source]->moreLinkList->{$code}))
+ if(isset($this->config->block->modules[$module]->moreLinkList->{$block->code}))
{
- list($moduleName, $method, $vars) = explode('|', sprintf($this->config->block->modules[$source]->moreLinkList->{$code}, isset($block->params->type) ? $block->params->type : ''));
+ list($moduleName, $method, $vars) = explode('|', sprintf($this->config->block->modules[$module]->moreLinkList->{$block->code}, isset($block->params->type) ? $block->params->type : ''));
/* The list assigned to me jumps to the work page when click more button. */
$block->moreLink = $this->createLink($moduleName, $method, $vars);
diff --git a/module/branch/model.php b/module/branch/model.php
index e7983045fa..ac31f690b5 100644
--- a/module/branch/model.php
+++ b/module/branch/model.php
@@ -409,6 +409,7 @@ class branchModel extends model
if(is_array($productID))
{
foreach($productID as $id) $this->linkBranch4Project($id);
+ return;
}
$linkedBranchProject = array();
diff --git a/module/product/config/form.php b/module/product/config/form.php
index 0e23310aa9..ae2802aef3 100644
--- a/module/product/config/form.php
+++ b/module/product/config/form.php
@@ -16,18 +16,33 @@ $config->product->form->create['status'] = array('type' => 'string', 'contro
$config->product->form->create['desc'] = array('type' => 'string', 'control' => 'editor', 'required' => false, 'default' => '', 'width' => 'full');
$config->product->form->create['acl'] = array('type' => 'string', 'control' => 'radio', 'required' => false, 'default' => 'private', 'width' => 'full', 'options' => $lang->product->aclList);
$config->product->form->create['whitelist'] = array('type' => 'array', 'control' => 'multi-select', 'required' => false, 'default' => '', 'filter' => 'join', 'width' => 'full', 'options' => 'users');
+if($config->systemMode != 'ALM') unset($config->product->form->create['program'], $config->product->form->create['line'], $config->product->form->create['lineName']);
$config->product->form->edit = array();
-$config->product->form->edit['program'] = array('type' => 'int', 'control' => 'select', 'required' => false, 'default' => 0, 'options' => array());
-$config->product->form->edit['line'] = array('type' => 'int', 'control' => 'select', 'required' => false, 'default' => 0, 'options' => array());
-$config->product->form->edit['name'] = array('type' => 'string', 'control' => 'text', 'required' => true, 'default' => '', 'filter' => 'trim');
-$config->product->form->edit['code'] = array('type' => 'string', 'control' => 'text', 'required' => true, 'default' => '', 'filter' => 'trim');
-$config->product->form->edit['PO'] = array('type' => 'account', 'control' => 'select', 'required' => false, 'default' => '', 'options' => array());
-$config->product->form->edit['QD'] = array('type' => 'account', 'control' => 'select', 'required' => false, 'default' => '', 'options' => array());
-$config->product->form->edit['RD'] = array('type' => 'account', 'control' => 'select', 'required' => false, 'default' => '', 'options' => array());
-$config->product->form->edit['reviewer'] = array('type' => 'array', 'control' => 'multi-select', 'required' => false, 'default' => '', 'filter' => 'join', 'options' => 'users');
-$config->product->form->edit['type'] = array('type' => 'string', 'control' => 'select', 'required' => false, 'default' => 'normal', 'options' => $lang->product->typeList);
-$config->product->form->edit['status'] = array('type' => 'string', 'control' => 'select', 'required' => false, 'default' => 'normal', 'options' => $lang->product->statusList);
-$config->product->form->edit['desc'] = array('type' => 'string', 'control' => 'textarea', 'required' => false, 'default' => '');
-$config->product->form->edit['acl'] = array('type' => 'string', 'control' => 'radio', 'required' => false, 'default' => 'private', 'options' => $lang->product->aclList);
-$config->product->form->edit['whitelist'] = array('type' => 'array', 'control' => 'multi-select', 'required' => false, 'default' => '', 'filter' => 'join', 'options' => 'users');
+$config->product->form->edit['program'] = array('type' => 'int', 'control' => 'select', 'required' => false, 'default' => 0, 'options' => array());
+$config->product->form->edit['line'] = array('type' => 'int', 'control' => 'select', 'required' => false, 'default' => 0, 'options' => array());
+$config->product->form->edit['name'] = array('type' => 'string', 'control' => 'text', 'required' => true, 'default' => '', 'filter' => 'trim');
+$config->product->form->edit['code'] = array('type' => 'string', 'control' => 'text', 'required' => true, 'default' => '', 'filter' => 'trim');
+$config->product->form->edit['PO'] = array('type' => 'account', 'control' => 'select', 'required' => false, 'default' => '', 'options' => array());
+$config->product->form->edit['QD'] = array('type' => 'account', 'control' => 'select', 'required' => false, 'default' => '', 'options' => array());
+$config->product->form->edit['RD'] = array('type' => 'account', 'control' => 'select', 'required' => false, 'default' => '', 'options' => array());
+$config->product->form->edit['reviewer'] = array('type' => 'array', 'control' => 'multi-select', 'required' => false, 'default' => '', 'filter' => 'join', 'options' => 'users');
+$config->product->form->edit['type'] = array('type' => 'string', 'control' => 'select', 'required' => false, 'default' => 'normal', 'options' => $lang->product->typeList);
+$config->product->form->edit['status'] = array('type' => 'string', 'control' => 'select', 'required' => false, 'default' => 'normal', 'options' => $lang->product->statusList);
+$config->product->form->edit['desc'] = array('type' => 'string', 'control' => 'editor', 'required' => false, 'default' => '');
+$config->product->form->edit['acl'] = array('type' => 'string', 'control' => 'radio', 'required' => false, 'default' => 'private', 'options' => $lang->product->aclList);
+$config->product->form->edit['whitelist'] = array('type' => 'array', 'control' => 'multi-select', 'required' => false, 'default' => '', 'filter' => 'join', 'options' => 'users');
+if($config->systemMode != 'ALM') unset($config->product->form->edit['program'], $config->product->form->edit['line']);
+
+$config->product->form->batchEdit = array();
+$config->product->form->batchEdit['program'] = array('type' => 'array', 'control' => 'select', 'required' => false, 'default' => 0, 'options' => array());
+$config->product->form->batchEdit['name'] = array('type' => 'array', 'control' => 'text', 'required' => true, 'default' => '');
+$config->product->form->batchEdit['line'] = array('type' => 'array', 'control' => 'select', 'required' => false, 'default' => 0, 'options' => array());
+$config->product->form->batchEdit['PO'] = array('type' => 'array', 'control' => 'select', 'required' => false, 'default' => '', 'options' => array());
+$config->product->form->batchEdit['QD'] = array('type' => 'array', 'control' => 'select', 'required' => false, 'default' => '', 'options' => array());
+$config->product->form->batchEdit['RD'] = array('type' => 'array', 'control' => 'select', 'required' => false, 'default' => '', 'options' => array());
+$config->product->form->batchEdit['type'] = array('type' => 'array', 'control' => 'select', 'required' => false, 'default' => 'normal', 'options' => $lang->product->typeList);
+$config->product->form->batchEdit['status'] = array('type' => 'array', 'control' => 'select', 'required' => false, 'default' => 'normal', 'options' => $lang->product->statusList);
+$config->product->form->batchEdit['desc'] = array('type' => 'array', 'control' => 'textarea', 'required' => false, 'default' => '');
+$config->product->form->batchEdit['acl'] = array('type' => 'array', 'control' => 'radio', 'required' => false, 'default' => 'private', 'options' => $lang->product->aclList);
+if($config->systemMode != 'ALM') unset($config->product->form->batchEdit['program'], $config->product->form->batchEdit['line']);
diff --git a/module/product/control.php b/module/product/control.php
index 15962a371e..35239d65b9 100755
--- a/module/product/control.php
+++ b/module/product/control.php
@@ -16,8 +16,8 @@ class product extends control
/**
* Construct function.
*
- * @param moduleName
- * @param methodName
+ * @param string moduleName
+ * @param string methodName
* @access public
* @return void
*/
@@ -390,8 +390,9 @@ class product extends control
if(!empty($_POST))
{
- $data = form::data($this->config->product->form->create);
- $product = $this->productZen->prepareCreateExtras($data, $this->post->acl, $this->post->uid);
+ $formConfig = $this->productZen->appendFlowFields($this->config->product->form->create);
+ $data = form::data($formConfig);
+ $product = $this->productZen->prepareCreateExtras($data, $this->post->acl, $this->post->uid);
$productID = $this->product->create($product, $this->post->uid, zget($_POST, 'lineName', ''));
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
@@ -421,8 +422,9 @@ class product extends control
if(!empty($_POST))
{
- $data = form::data($this->config->product->form->edit);
- $product = $this->productZen->prepareEditExtras($data, $this->post->acl, $this->post->uid);
+ $formConfig = $this->productZen->appendFlowFields($this->config->product->form->edit);
+ $data = form::data($formConfig);
+ $product = $this->productZen->prepareEditExtras($data, $this->post->acl, $this->post->uid);
$changes = $this->product->update($productID, $product, $this->post->uid);
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
@@ -441,17 +443,37 @@ class product extends control
}
/**
+ * 根据POST过来的ID列表,批量编辑相应产品。
* Batch edit products.
*
- * @param int $programID
+ * @param string $programID
* @access public
* @return void
*/
- public function batchEdit($programID = 0)
+ public function batchEdit(string $programID = '0')
{
- if($this->post->names)
+ $programID = (int)$programID;
+
+ $_POST['productIdList'][1] = 1;
+ $_POST['name'][1] = '公司企业网站建设';
+ $_POST['PO'][1] = 'productManager';
+ $_POST['QD'][1] = 'testManager';
+ $_POST['RD'][1] = 'productManager';
+ $_POST['type'][1] = 'normal';
+ $_POST['status'][1] = 'normal';
+ $_POST['desc'][1] = '建立公司企业网站,可以更好对外展示。
';
+ $_POST['acl'][1] = 'open';
+
+ if($this->post->name)
{
- $allChanges = $this->product->batchUpdate();
+ $formConfig = $this->productZen->appendFlowFields($this->config->product->form->batchEdit, 'batch');
+ $data = form::data($formConfig);
+ $products = $this->productZen->prepareBatchEditExtras($data);
+ if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
+
+ $allChanges = $this->product->batchUpdate($products);
+
+
if(!empty($allChanges))
{
foreach($allChanges as $productID => $changes)
@@ -467,76 +489,16 @@ class product extends control
return print(js::locate($locate, 'parent'));
}
- $productIDList = $this->post->productIDList;
- if(empty($productIDList)) return print(js::locate($this->session->productList, 'parent'));
+ /* 获取要修改的产品ID列表。*/
+ $productIdList = $this->post->productIDList;
+ $productIdList = '79,40,68';
+ if(empty($productIdList)) return print(js::locate($this->session->productList, 'parent'));
/* Set menu when page come from program. */
if($this->app->tab == 'program') $this->loadModel('program')->setMenu(0);
- /* Set custom. */
- foreach(explode(',', $this->config->product->customBatchEditFields) as $field) $customFields[$field] = $this->lang->product->$field;
- $this->view->customFields = $customFields;
- $this->view->showFields = $this->config->product->custom->batchEditFields;
-
- $products = $this->dao->select('*')->from(TABLE_PRODUCT)->where('id')->in($productIDList)->fetchAll('id');
- $appendPoUsers = $appendQdUsers = $appendRdUsers = array();
- foreach($products as $product)
- {
- $appendPoUsers[$product->PO] = $product->PO;
- $appendQdUsers[$product->QD] = $product->QD;
- $appendRdUsers[$product->RD] = $product->RD;
- }
-
- $this->loadModel('user');
- $poUsers = $this->user->getPairs('nodeleted|noclosed|pofirst', $appendPoUsers);
- if(!empty($this->config->user->moreLink)) $this->config->moreLinks["PO"] = $this->config->user->moreLink;
-
- $qdUsers = $this->user->getPairs('nodeleted|noclosed|qdfirst', $appendQdUsers);
- if(!empty($this->config->user->moreLink)) $this->config->moreLinks["QD"] = $this->config->user->moreLink;
-
- $rdUsers = $this->user->getPairs('nodeleted|noclosed|devfirst', $appendRdUsers);
- if(!empty($this->config->user->moreLink)) $this->config->moreLinks["RD"] = $this->config->user->moreLink;
-
- $programs = array();
- $unauthorizedPrograms = array();
- if($this->config->systemMode == 'ALM')
- {
- $programs = $this->loadModel('program')->getTopPairs();
-
- /* Get unauthorized programs. */
- $programIDList = array();
- foreach($products as $product)
- {
- if($product->program and !isset($programs[$product->program]) and !in_array($product->program, $programIDList)) $programIDList[] = $product->program;
- }
- $unauthorizedPrograms = $this->program->getPairsByList($programIDList);
-
- /* Get product lines by programs.*/
- $lines = array(0 => '');
- foreach($programs + $unauthorizedPrograms as $id => $program)
- {
- $lines[$id] = array('') + $this->product->getLinePairs($id);
- }
- }
- else
- {
- $lines = array('') + $this->product->getLinePairs();
- }
-
- $this->view->title = $this->lang->product->batchEdit;
- $this->view->position[] = $this->lang->product->batchEdit;
- $this->view->lines = $lines;
- $this->view->productIDList = $productIDList;
- $this->view->products = $products;
- $this->view->poUsers = $poUsers;
- $this->view->qdUsers = $qdUsers;
- $this->view->rdUsers = $rdUsers;
- $this->view->programID = $programID;
- $this->view->programs = array('' => '') + $programs;
- $this->view->unauthorizedPrograms = $unauthorizedPrograms;
-
- unset($this->lang->product->typeList['']);
- $this->display();
+ /* 构造批量编辑页面表单配置数据。*/
+ $this->productZen->buildBatchEditForm($programID, explode(',', $productIdList));
}
/**
@@ -875,7 +837,7 @@ class product extends control
$this->product->buildProductSearchForm($param, $actionURL);
/* Get product lines. */
- list($productLines, $programLines) = $this->getProductLines();
+ list($productLines, $programLines) = $this->productZen->getProductLines();
$this->view->title = $this->lang->productCommon;
$this->view->position[] = $this->lang->productCommon;
diff --git a/module/product/model.php b/module/product/model.php
index 9c5a1056fb..ef5ea8f484 100755
--- a/module/product/model.php
+++ b/module/product/model.php
@@ -206,13 +206,13 @@ class productModel extends model
/**
* Get by idList.
*
- * @param array $productIDList
+ * @param array $productIdList
* @access public
* @return array
*/
- public function getByIdList($productIDList)
+ public function getByIdList(array $productIdList): array
{
- return $this->dao->select('*')->from(TABLE_PRODUCT)->where('id')->in($productIDList)->fetchAll('id');
+ return $this->dao->select('*')->from(TABLE_PRODUCT)->where('id')->in($productIdList)->fetchAll('id');
}
/**
@@ -658,14 +658,8 @@ class productModel extends model
$oldProduct = $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch();
$this->lang->error->unique = $this->lang->error->repeat;
- $this->dao->update(TABLE_PRODUCT)->data($product, 'uid,changeProjects,contactListMenu')->autoCheck()
- ->checkIF(!empty($product->name), 'name', 'unique', "id != {$productID} and `program` = {$product->program} and `deleted` = '0'")
- ->checkIF(!empty($product->code), 'code', 'unique', "id != {$productID} and `deleted` = '0'")
- ->checkFlow()
- ->where('id')->eq($productID)
- ->exec();
-
- if(dao::isError()) return false;
+ $result = $this->productTao->doUpdate($product, $productID, (int)$product->program);
+ if(!$result) return false;
/* Update objectID field of file recode, that upload by editor. */
$this->loadModel('file')->updateObjectID($uid, $productID, 'product');
@@ -681,77 +675,50 @@ class productModel extends model
}
/**
+ * 批量更新产品信息。
* Batch update products.
*
+ * @param array $products
* @access public
* @return array
*/
- public function batchUpdate()
+ public function batchUpdate(array $products): array
{
- $products = array();
- $allChanges = array();
- $data = fixer::input('post')->get();
- $oldProducts = $this->getByIdList($this->post->productIDList);
- $nameList = array();
+ if(empty($products)) return array();
- $extendFields = $this->getFlowExtendFields();
- foreach($data->productIDList as $productID)
- {
- $productName = $data->names[$productID];
+ /* 初始化变量。*/
+ $oldProducts = $this->getByIdList(array_keys($products));
+ $allChanges = array();
+ $updateViewProducts = array();
+ $unlinkProducts = array();
+ $linkProducts = array();
- $productID = (int)$productID;
- $products[$productID] = new stdClass();
- if($this->config->systemMode == 'ALM' and isset($data->programs[$productID])) $products[$productID]->program = (int)$data->programs[$productID];
- if($this->config->systemMode == 'ALM' and isset($data->lines[$productID])) $products[$productID]->line = (int)$data->lines[$productID];
- $products[$productID]->name = $productName;
- $products[$productID]->PO = $data->POs[$productID];
- $products[$productID]->QD = $data->QDs[$productID];
- $products[$productID]->RD = $data->RDs[$productID];
- $products[$productID]->type = $data->types[$productID];
- $products[$productID]->status = $data->statuses[$productID];
- $products[$productID]->desc = strip_tags($this->post->descs[$productID], $this->config->allowedTags);
- $products[$productID]->acl = $data->acls[$productID];
- $products[$productID]->id = $productID;
-
- foreach($extendFields as $extendField)
- {
- $products[$productID]->{$extendField->field} = $this->post->{$extendField->field}[$productID];
- if(is_array($products[$productID]->{$extendField->field})) $products[$productID]->{$extendField->field} = join(',', $products[$productID]->{$extendField->field});
-
- $products[$productID]->{$extendField->field} = htmlSpecialString($products[$productID]->{$extendField->field});
- }
- }
- if(dao::isError()) return print(js::error(dao::getError()));
-
- $unlinkProducts = array();
- $linkProducts = array();
+ /* 根据产品ID,循环更新的产品信息. */
+ $this->loadModel('personnel');
$this->lang->error->unique = $this->lang->error->repeat;
foreach($products as $productID => $product)
{
$oldProduct = $oldProducts[$productID];
- if($this->config->systemMode == 'ALM') $programID = !isset($product->program) ? $oldProduct->program : (empty($product->program) ? 0 : $product->program);
+ if($this->config->systemMode == 'ALM') $programID = (int)zget($product, 'program', $oldProduct->program);
- $this->dao->update(TABLE_PRODUCT)
- ->data($product)
- ->autoCheck()
- ->batchCheck($this->config->product->edit->requiredFields , 'notempty')
- ->checkIF((!empty($product->name) and $this->config->systemMode == 'ALM'), 'name', 'unique', "id != $productID and `program` = $programID and `deleted` = '0'")
- ->checkFlow()
- ->where('id')->eq($productID)
- ->exec();
- if(dao::isError()) return print(js::error('product#' . $productID . dao::getError(true)));
+ $result = $this->productTao->doUpdate($product, $productID, $programID);
+ if(!$result) return array('result' => 'fail', 'message' => 'product#' . $productID . dao::getError(true));
- /* When acl is open, white list set empty. When acl is private,update user view. */
- if($product->acl == 'open') $this->loadModel('personnel')->updateWhitelist(array(), 'product', $productID);
- if($product->acl != 'open') $this->loadModel('user')->updateUserView($productID, 'product');
- if($product->type == 'normal' and $oldProduct->type != 'normal') $unlinkProducts[] = $productID;
- if($product->type != 'normal' and $oldProduct->type == 'normal') $linkProducts[] = $productID;
+ /* When acl is open, white list set empty. */
+ if($product->acl == 'open') $this->personnel->updateWhitelist(array(), 'product', $productID);
+
+ /* 如果产品类型或权限有修改,则标记该产品,用做后面处理。*/
+ if($oldProduct->acl != $product->acl and $product->acl != 'open') $updateViewProducts[] = $productID;
+ if($product->type == 'normal' and $oldProduct->type != 'normal') $unlinkProducts[] = $productID;
+ if($product->type != 'normal' and $oldProduct->type == 'normal') $linkProducts[] = $productID;
$allChanges[$productID] = common::createChanges($oldProduct, $product);
}
- if(!empty($unlinkProducts)) $this->loadModel('branch')->unlinkBranch4Project($unlinkProducts);
- if(!empty($linkProducts)) $this->loadModel('branch')->linkBranch4Project($linkProducts);
+ /* 对标记的产品,批量做对应的后续处理。*/
+ if(!empty($updateViewProducts)) $this->loadModel('user')->updateUserView($updateViewProducts, 'product');
+ if(!empty($unlinkProducts)) $this->loadModel('branch')->unlinkBranch4Project($unlinkProducts);
+ if(!empty($linkProducts)) $this->loadModel('branch')->linkBranch4Project($linkProducts);
return $allChanges;
}
@@ -1729,12 +1696,19 @@ class productModel extends model
/*
* Get all lines.
+ *
+ * @param array $programIdList
* @access public
* @return array
*/
- public function getLines()
+ public function getLines(array $programIdList = array()): array
{
- return $this->dao->select('*')->from(TABLE_MODULE)->where('type')->eq('line')->andWhere('deleted')->eq(0)->orderBy('`order`')->fetchAll();
+ return $this->dao->select('*')->from(TABLE_MODULE)
+ ->where('type')->eq('line')
+ ->beginIF($programIdList)->andWhere('root')->in($programIdList)->fi()
+ ->andWhere('deleted')->eq(0)
+ ->orderBy('`order`')
+ ->fetchAll();
}
/**
diff --git a/module/product/tao.php b/module/product/tao.php
index bb04178ba9..ecf050d6ac 100644
--- a/module/product/tao.php
+++ b/module/product/tao.php
@@ -562,15 +562,27 @@ class productTao extends productModel
}
/**
- * 从module表中查询所有产品线。
- * Get all product lines from module table.
- * TODO move to the MODULE module.
+ * 执行SQL,更新到对应的产品信息。
+ * Do update this product.
*
+ * @param object $product
+ * @param int $productID
+ * @param int $programID
* @access protected
- * @return array
+ * @return bool
*/
- protected function getProductLinesTODO(): array
+ protected function doUpdate(object $product, int $productID, int $programID): bool
{
- return $this->dao->select('*')->from(TABLE_MODULE)->where('type')->eq('line')->andWhere('deleted')->eq(0)->orderBy('`order` asc')->fetchAll();
+ if(empty($productID)) return false;
+ if(count(get_object_vars($product)) == 0) return false;
+
+ $this->dao->update(TABLE_PRODUCT)->data($product)->autoCheck()
+ ->checkIF(!empty($product->name), 'name', 'unique', "id != {$productID} and `program` = {$programID} and `deleted` = '0'")
+ ->checkIF(!empty($product->code), 'code', 'unique', "id != {$productID} and `deleted` = '0'")
+ ->checkFlow()
+ ->where('id')->eq($productID)
+ ->exec();
+
+ return !dao::isError();
}
}
diff --git a/module/product/test/model/batchupdate.php b/module/product/test/model/batchupdate.php
index f2e98c1c55..0875a62ed9 100755
--- a/module/product/test/model/batchupdate.php
+++ b/module/product/test/model/batchupdate.php
@@ -3,28 +3,53 @@
include dirname(__FILE__, 5) . "/test/lib/init.php";
include dirname(__FILE__, 2) . '/product.class.php';
+zdTable('product')->gen(10);
+
/**
title=测试 productModel->batchUpdate();
cid=1
pid=1
-批量修改product名称 >> name,正常产品1,批量修改产品1
-批量修改produc测试负责人 >> QD,test2,test1
-批量修改product状态 >> status,normal,closed
-
*/
-$names = array('1' => '批量修改产品1', '2' => '正常产品2', '3' => '正常产品3');
-$QDs = array('1' => 'test1', '2' => 'test1', '3' => 'test3');
-$status = array('1' => 'normal', '2' => 'normal', '3' => 'closed');
-
-$changeName = array('names' => $names);
-$changeQDs = array('QDs' => $QDs);
-$changeStatus = array('statuses' => $status);
-
$product = new productTest('admin');
-r($product->batchUpdateTest($changeName, '1')) && p('0:field,old,new') && e('name,正常产品1,批量修改产品1'); // 批量修改product名称
-r($product->batchUpdateTest($changeQDs, '2')) && p('0:field,old,new') && e('QD,test2,test1'); // 批量修改produc测试负责人
-r($product->batchUpdateTest($changeStatus, '3')) && p('0:field,old,new') && e('status,normal,closed'); // 批量修改product状态
+$products = array();
+$products[1] = new stdclass();
+$products[1]->program = 1;
+$products[1]->name = '批量修改产品1';
+$products[1]->type = 'branch';
+$products[1]->acl = 'private';
+
+$changes = $product->batchUpdateTest($products);
+$changes = $changes[1];
+r(array_shift($changes)) && p('field,old,new') && e('program,0,1');
+r(array_shift($changes)) && p('field,old,new') && e('name,正常产品1,批量修改产品1');
+r(array_shift($changes)) && p('field,old,new') && e('type,normal,branch');
+r(array_shift($changes)) && p('field,old,new') && e('acl,open,private');
+
+$products = array();
+$products[2] = new stdclass();
+$products[2]->program = 1;
+$products[2]->name = '批量修改产品1';
+$products[2]->type = 'branch';
+$products[2]->acl = 'private';
+
+$changes = $product->batchUpdateTest($products);
+$changes['message'] = str_replace('product#', 'product:', $changes['message']);
+r($changes) && p('result,message') && e('fail,product:2『产品名称』已经有『批量修改产品1』这条记录了。\n'); //验证唯一。
+
+r($product->batchUpdateTest(array())) && p() && e('0'); //不传任何数据。
+
+$products = array();
+$products[1] = new stdclass();
+$products[1]->program = 1;
+$products[1]->name = '批量修改产品1';
+$products[1]->type = 'normal';
+$products[1]->acl = 'open';
+
+$changes = $product->batchUpdateTest($products);
+$changes = $changes[1];
+r(array_shift($changes)) && p('field,old,new') && e('type,branch,normal');
+r(array_shift($changes)) && p('field,old,new') && e('acl,private,open');
diff --git a/module/product/test/product.class.php b/module/product/test/product.class.php
index ac8734e644..085c6364cc 100644
--- a/module/product/test/product.class.php
+++ b/module/product/test/product.class.php
@@ -564,40 +564,31 @@ class productTest
/**
* Test batch update products.
*
- * @param array $param
- * @param int $productID
+ * @param array $products
* @access public
- * @return void
+ * @return array
*/
- public function batchUpdateTest($param, $productID)
+ public function batchUpdateTest(array $products): array
{
- $batchUpdateFields['productIDList'] = array('1' => '1', '2' => '2', '3' => '3');
- $batchUpdateFields['programs'] = array('1' => '', '2' => '1', '3' => '2');
- $batchUpdateFields['names'] = array('1' => '正常产品1', '2' => '正常产品2', '3' => '正常产品3');
- $batchUpdateFields['lines'] = array('1' => '0', '2' => '1', '3' => '2');
- $batchUpdateFields['POs'] = array('1' => 'po1', '2' => 'po2', '3' => 'po3');
- $batchUpdateFields['QDs'] = array('1' => 'test1', '2' => 'test2', '3' => 'test3');
- $batchUpdateFields['RDs'] = array('1' => 'dev1', '2' => 'dev2', '3' => 'dev3');
- $batchUpdateFields['types'] = array('1' => 'normal', '2' => 'normal', '3' => 'normal');
- $batchUpdateFields['statuses'] = array('1' => 'normal', '2' => 'normal', '3' => 'normal');
- $batchUpdateFields['descs'] = array('1' => '<div> <p><h1>一、禅道项目管理软件是做什么的?</h1> 禅道由 青岛易软天创网络科技有限公司开发,国产开源项目管理软件。它集产品管理、项目管理、质量管理、文档管理、组织管理和事务管理于一体,是一款专业的研发项目管理软件,完整覆盖了研发项目管理的核心流程。禅道管理思想注重实效,功能完备丰富,操作简洁高效,界面美观大方,搜索功能强大,统计报表丰富多样,软件架构合理,扩展灵活,有完善的API可以调用。禅道,专注研发项目管理 </p> <p>我是数字符号23@#$%#^$ </p> <p>我是英文dashcuscbrewg </p> </div>', '2' => '<div> <p><h1>一、禅道项目管理软件是做什么的?</h1> 禅道由 青岛易软天创网络科技有限公司开发,国产开源项目管理软件。它集产品管理、项目管理、质量管理、文档管理、组织管理和事务管理于一体,是一款专业的研发项目管理软件,完整覆盖了研发项目管理的核心流程。禅道管理思想注重实效,功能完备丰富,操作简洁高效,界面美观大方,搜索功能强大,统计报表丰富多样,软件架构合理,扩展灵活,有完善的API可以调用。禅道,专注研发项目管理 </p> <p>我是数字符号23@#$%#^$ </p> <p>我是英文dashcuscbrewg </p> </div>', '3' => 'i<div> <p><h1>一、禅道项目管理软件是做什么的?</h1> 禅道由 青岛易软天创网络科技有限公司开发,国产开源项目管理软件。它集产品管理、项目管理、质量管理、文档管理、组织管理和事务管理于一体,是一款专业的研发项目管理软件,完整覆盖了研发项目管理的核心流程。禅道管理思想注重实效,功能完备丰富,操作简洁高效,界面美观大方,搜索功能强大,统计报表丰富多样,软件架构合理,扩展灵活,有完善的API可以调用。禅道,专注研发项目管理 </p> <p>我是数字符号23@#$%#^$ </p> <p>我是英文dashcuscbrewg </p> </div>');
- $batchUpdateFields['acls'] = array('1' => 'open', '2' => 'open', '3' => 'open');
+ return $this->objectModel->batchUpdate($products);
+ }
- foreach($batchUpdateFields as $field => $defaultValue) $_POST[$field] = $defaultValue;
+ /**
+ * 测试doUpdate方法
+ * Test doUpdate method
+ *
+ * @param object $product
+ * @param int $productID
+ * @param int $programID
+ * @access public
+ * @return object|array|null
+ */
+ public function doUpdateTest(object $product, int $productID, int $programID): object|array|false
+ {
+ $this->objectModel->doUpdate($product, $productID, $programID);
- foreach($param as $key => $value) $_POST[$key] = $value;
-
- $changes = $this->objectModel->batchUpdate();
- unset($_POST);
-
- if(dao::isError())
- {
- return dao::getError();
- }
- else
- {
- return $changes[$productID];
- }
+ if(dao::isError()) return dao::getError();
+ return $this->objectModel->getById($productID);
}
/**
diff --git a/module/product/test/tao/doupdate.php b/module/product/test/tao/doupdate.php
new file mode 100755
index 0000000000..670fd729bf
--- /dev/null
+++ b/module/product/test/tao/doupdate.php
@@ -0,0 +1,51 @@
+#!/usr/bin/env php
+gen(10);
+
+/**
+
+title=测试productModel->fetchPairs();
+cid=1
+pid=1
+
+*/
+
+$product = new productTest('admin');
+
+$productID = 1;
+$programID = 0;
+$data = new stdclass();
+$data->program = 1;
+$data->name = '修改产品1';
+$data->code = 'newcode1';
+$data->type = 'branch';
+$data->acl = 'private';
+
+r($product->doUpdateTest($data, $productID, $programID)) && p('program,name,code,type,acl') && e('1,修改产品1,newcode1,branch,private');
+
+$data->name = '修改产品2';
+$data->code = 'newcode2';
+r($product->doUpdateTest($data, 0, 1)) && p() && e('0');
+r($product->doUpdateTest($data, 0, 0)) && p() && e('0');
+r($product->doUpdateTest($data, 0, -1)) && p() && e('0');
+r($product->doUpdateTest($data, -1, 1)) && p() && e('0');
+r($product->doUpdateTest($data, -1, 0)) && p() && e('0');
+r($product->doUpdateTest($data, -1, -1)) && p() && e('0');
+r($product->doUpdateTest(new stdclass(), 3, 2)) && p('name,code') && e('正常产品3,code3');
+
+$productID = 2;
+$programID = 1;
+$data = new stdclass();
+$data->program = 1;
+$data->name = '修改产品1';
+$data->code = 'newcode1';
+$data->type = 'branch';
+$data->acl = 'private';
+$result = $product->doUpdateTest($data, $productID, $programID);
+
+r(array_shift($result['name'])) && p() && e('『产品名称』已经有『修改产品1』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。');
+r(array_shift($result['code'])) && p() && e('『产品代号』已经有『newcode1』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。');
+
diff --git a/module/product/view/batchedit.html.php b/module/product/view/batchedit.html.php
index 9f2efa2e6a..a2e8987737 100755
--- a/module/product/view/batchedit.html.php
+++ b/module/product/view/batchedit.html.php
@@ -73,19 +73,19 @@