Merge branch 'master' of https://git.zcorp.cc/easycorp/zentaopms
This commit is contained in:
@@ -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());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
namespace zin;
|
||||
|
||||
class dataGroup extends wg
|
||||
{
|
||||
protected static $defineProps = array(
|
||||
'label:string',
|
||||
'labelClass?:string'
|
||||
);
|
||||
|
||||
private function label(string $text)
|
||||
{
|
||||
$className = $this->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(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
+12
-9
@@ -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);
|
||||
|
||||
@@ -409,6 +409,7 @@ class branchModel extends model
|
||||
if(is_array($productID))
|
||||
{
|
||||
foreach($productID as $id) $this->linkBranch4Project($id);
|
||||
return;
|
||||
}
|
||||
|
||||
$linkedBranchProject = array();
|
||||
|
||||
@@ -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']);
|
||||
|
||||
+39
-77
@@ -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] = '建立公司企业网站,可以更好对外展示。<br />';
|
||||
$_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;
|
||||
|
||||
+40
-66
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+18
-6
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
include dirname(__FILE__, 2) . '/product.class.php';
|
||||
|
||||
zdTable('product')->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』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。');
|
||||
|
||||
@@ -73,19 +73,19 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($productIDList as $productID):?>
|
||||
<?php foreach(array_keys($products) as $productID):?>
|
||||
<?php
|
||||
if(!empty($this->config->moreLinks["PO"])) $this->config->moreLinks["POs[$productID]"] = $this->config->moreLinks["PO"];
|
||||
if(!empty($this->config->moreLinks["QD"])) $this->config->moreLinks["QDs[$productID]"] = $this->config->moreLinks["QD"];
|
||||
if(!empty($this->config->moreLinks["RD"])) $this->config->moreLinks["RDs[$productID]"] = $this->config->moreLinks["RD"];
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo sprintf('%03d', $productID) . html::hidden("productIDList[$productID]", $productID);?></td>
|
||||
<td><?php echo sprintf('%03d', $productID) . html::hidden("productIdList[$productID]", $productID);?></td>
|
||||
<?php if($this->config->systemMode == 'ALM'):?>
|
||||
<?php if(isset($unauthorizedPrograms[$products[$productID]->program])):?>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'program', ' hidden')?>' style='overflow:visible'><?php echo html::select("programs[$productID]", $unauthorizedPrograms, $products[$productID]->program, "class='form-control' disabled");?></td>
|
||||
<?php if(isset($unauthPrograms[$products[$productID]->program])):?>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'program', ' hidden')?>' style='overflow:visible'><?php echo html::select("programs[$productID]", $unauthPrograms, $products[$productID]->program, "class='form-control' disabled");?></td>
|
||||
<?php else:?>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'program', ' hidden')?>' style='overflow:visible'><?php echo html::select("programs[$productID]", $programs, $products[$productID]->program, "class='form-control picker-select' onchange='loadProductLines(this.value, $productID)'");?></td>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'program', ' hidden')?>' style='overflow:visible'><?php echo html::select("programs[$productID]", $authPrograms, $products[$productID]->program, "class='form-control picker-select' onchange='loadProductLines(this.value, $productID)'");?></td>
|
||||
<?php endif;?>
|
||||
<?php endif;?>
|
||||
<td title='<?php echo $products[$productID]->name?>'><?php echo html::input("names[$productID]", $products[$productID]->name, "class='form-control'");?></td>
|
||||
|
||||
+183
-23
@@ -201,28 +201,29 @@ class productZen extends product
|
||||
*/
|
||||
private function getFormFields4Create(int $programID = 0, array $fields = array()): array
|
||||
{
|
||||
if(empty($fields)) $fields = $this->config->product->form->create;
|
||||
if(empty($fields)) $fields = $this->appendFlowFields($this->config->product->form->create);
|
||||
|
||||
/* 准备数据。*/
|
||||
$this->loadModel('user');
|
||||
$poUsers = $this->user->getPairs('nodeleted|pofirst|noclosed');
|
||||
$qdUsers = $this->user->getPairs('nodeleted|qdfirst|noclosed');
|
||||
$rdUsers = $this->user->getPairs('nodeleted|devfirst|noclosed');
|
||||
$users = $this->user->getPairs('nodeleted|noclosed');
|
||||
|
||||
/* 追加字段的name、title属性,展开user数据。 */
|
||||
foreach($fields as $field => $attr)
|
||||
{
|
||||
if(isset($attr['options']) and $attr['options'] == 'users') $fields[$field]['options'] = $users;
|
||||
$fields[$field]['name'] = $field;
|
||||
$fields[$field]['title'] = zget($this->lang->product, $field);
|
||||
if(!isset($fields[$field]['name'])) $fields[$field]['name'] = $field;
|
||||
if(!isset($fields[$field]['title'])) $fields[$field]['title'] = zget($this->lang->product, $field);
|
||||
}
|
||||
|
||||
$fields['program']['options'] = array('') + $this->loadModel('program')->getTopPairs('', 'noclosed');
|
||||
$fields['PO']['options'] = $poUsers;
|
||||
$fields['QD']['options'] = $qdUsers;
|
||||
$fields['RD']['options'] = $rdUsers;
|
||||
|
||||
if($programID) $fields['line']['options'] = array('') + $this->product->getLinePairs($programID);
|
||||
if(empty($programID) or $this->config->systemMode != 'ALM') unset($fields['line'], $fields['lineName']);
|
||||
/* 设置下拉菜单内容。 */
|
||||
$fields['PO']['options'] = $poUsers;
|
||||
$fields['QD']['options'] = $qdUsers;
|
||||
$fields['RD']['options'] = $rdUsers;
|
||||
if(isset($fields['program'])) $fields['program']['options'] = array('') + $this->loadModel('program')->getTopPairs('', 'noclosed');
|
||||
if($programID and isset($fields['line'])) $fields['line']['options'] = array('') + $this->product->getLinePairs($programID);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
@@ -239,12 +240,13 @@ class productZen extends product
|
||||
{
|
||||
/* Init fields. */
|
||||
$programID = (int)$product->program;
|
||||
$fields = $this->getFormFields4Create($programID, $this->config->product->form->edit);
|
||||
$fields = $this->getFormFields4Create($programID, $this->appendFlowFields($this->config->product->form->edit));
|
||||
$fields['changeProjects'] = array('type' => 'string', 'control' => 'hidden', 'required' => false, 'default' => '');
|
||||
|
||||
/* Check program priv, and append to program list that is not exist product's program. */
|
||||
$hasPrivPrograms = $this->app->user->view->programs;
|
||||
if($programID and strpos(",{$hasPrivPrograms},", ",{$programID},") === false) $fields['program']['control'] = 'hidden';
|
||||
if(!isset($fields['program']['options'][$programID]) and $programID)
|
||||
if(isset($fields['program']) and !isset($fields['program']['options'][$programID]) and $programID)
|
||||
{
|
||||
$program = $this->program->getByID($programID);
|
||||
$fields['program']['options'] += array($programID => $program->name);
|
||||
@@ -255,7 +257,28 @@ class productZen extends product
|
||||
{
|
||||
if(isset($product->{$field})) $fields[$field]['default'] = $product->{$field};
|
||||
}
|
||||
$fields['changeProjects'] = array('type' => 'string', 'control' => 'hidden', 'required' => false, 'default' => '');
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取批量编辑产品页面的表单配置。
|
||||
* Get form fields config for batch edit page.
|
||||
*
|
||||
* @access private
|
||||
* @return array
|
||||
*/
|
||||
private function getFormFields4BatchEdit(): array
|
||||
{
|
||||
/* Init fields. */
|
||||
$fields = $this->getFormFields4Create(0, $this->appendFlowFields($this->config->product->form->batchEdit, 'batch'));
|
||||
|
||||
/* Remove not show fields. */
|
||||
$showFields = explode(',', $this->config->product->custom->batchEditFields);
|
||||
foreach($fields as $field => $attr)
|
||||
{
|
||||
if(!in_array($field, $showFields) and !$attr['required']) unset($fields[$field]);
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
@@ -263,23 +286,45 @@ class productZen extends product
|
||||
/**
|
||||
* Get product lines and product lines of program.
|
||||
*
|
||||
* @param array $programIdList
|
||||
* @param string $params hasempty
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function getProductLines(): array
|
||||
protected function getProductLines(array $programIdList = array(), string $params = ''): array
|
||||
{
|
||||
/* Get all product lines. */
|
||||
$productLines = $this->product->getProductLinesTODO();
|
||||
$productLines = $this->product->getLines($programIdList);
|
||||
|
||||
/* Collect product lines of program lines. */
|
||||
$programLines = array();
|
||||
foreach($productLines as $productLine)
|
||||
{
|
||||
if(!isset($programLines[$productLine->root])) $programLines[$productLine->root] = array();
|
||||
$programLines[$productLine->root][$productLine->id] = $productLine->name;
|
||||
}
|
||||
$initArray = strpos($params, 'hasempty') !== false ? array('') : array();
|
||||
$linePairs = $initArray;
|
||||
foreach($programIdList as $programID) $linePairs[$programID] = $initArray;
|
||||
foreach($productLines as $line) $linePairs[$programID][$line->id] = $line->name;
|
||||
|
||||
return array($productLines, $programLines);
|
||||
return array($productLines, $linePairs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据产品和已授权项目集,获取关联产品的未授权项目集。
|
||||
* Get unauthorized programs by products and authorized programs.
|
||||
*
|
||||
* @param array $products
|
||||
* @param array $authPrograms
|
||||
* @access private
|
||||
* @return array
|
||||
*/
|
||||
private function getUnauthProductPrograms(array $products, array $authPrograms): array
|
||||
{
|
||||
$unauthPrograms = array();
|
||||
$programIdList = array();
|
||||
foreach($products as $product)
|
||||
{
|
||||
if($product->program and !isset($authPrograms[$product->program])) $programIdList[$product->program] = $product->program;
|
||||
}
|
||||
if($programIdList) $unauthPrograms = $this->program->getPairsByList($programIdList);
|
||||
|
||||
return $unauthPrograms;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -378,6 +423,45 @@ class productZen extends product
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建批量编辑产品页面数据。
|
||||
* Build form for batch edit page
|
||||
*
|
||||
* @param int $programID
|
||||
* @param array $productIdList
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function buildBatchEditForm(int $programID, array $productIdList)
|
||||
{
|
||||
$products = $this->product->getByIdList($productIdList);
|
||||
|
||||
/* 获取项目集和产品线,并将项目集分成授权和非授权。以便view的下拉菜单使用对应的数据。 */
|
||||
$authPrograms = array();
|
||||
$unauthPrograms = array();
|
||||
$lines = array();
|
||||
if($this->config->systemMode == 'ALM')
|
||||
{
|
||||
$authPrograms = $this->loadModel('program')->getTopPairs();
|
||||
$unauthPrograms = $this->getUnauthProductPrograms($products, $authPrograms);
|
||||
|
||||
/* Get product lines by programs.*/
|
||||
$programIdList = array_merge(array_keys($authPrograms), array_keys($unauthPrograms));
|
||||
list(, $lines) = $this->getProductLines($programIdList);
|
||||
}
|
||||
|
||||
/* 给view层赋值。 */
|
||||
$this->view->title = $this->lang->product->batchEdit;
|
||||
$this->view->lines = $lines;
|
||||
$this->view->products = $products;
|
||||
$this->view->programID = $programID;
|
||||
$this->view->authPrograms = array('' => '') + $authPrograms;
|
||||
$this->view->unauthPrograms = $unauthPrograms;
|
||||
|
||||
unset($this->lang->product->typeList['']);
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* 为view层设置要用数据。
|
||||
* Set view variables and display for project page.
|
||||
@@ -448,13 +532,56 @@ class productZen extends product
|
||||
*/
|
||||
protected function prepareEditExtras(form $data, string $acl, string $uid = ''): object
|
||||
{
|
||||
$product = fixer::input('post')->setIF($acl == 'open', 'whitelist', '')
|
||||
$product = $data->setIF($acl == 'open', 'whitelist', '')
|
||||
->stripTags($this->config->product->editor->edit['id'], $this->config->allowedTags)
|
||||
->get();
|
||||
|
||||
return $this->loadModel('file')->processImgURL($product, $this->config->product->editor->edit['id'], $uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 预处理批量编辑产品数据,将按字段为分组数据重组为产品分组的数据。
|
||||
* Prepare batch edit extras.
|
||||
*
|
||||
* @param form $data
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareBatchEditExtras(form $data): array
|
||||
{
|
||||
$formConfig = $data->rawconfig;
|
||||
$editForm = $this->config->product->form->edit;
|
||||
$data = $data->get();
|
||||
$products = array();
|
||||
|
||||
/* 将按字段为分组数据重组为产品分组的数据。*/
|
||||
foreach($data->name as $productID => $productName)
|
||||
{
|
||||
$productID = (int)$productID;
|
||||
|
||||
/* 根据表单配置构造产品数据。*/
|
||||
$product = new stdClass();
|
||||
$product->id = $productID;
|
||||
foreach($formConfig as $field => $attr)
|
||||
{
|
||||
/* 获取对应的字段数据。*/
|
||||
$product->{$field} = zget($data->{$field}, $productID, $attr['default']);
|
||||
|
||||
/* 根据配置规则,格式化字段数据。 */
|
||||
if(isset($editForm[$field]) and $editForm[$field]['type'] == 'int') $product->{$field} = (int)$product->{$field};
|
||||
if(!empty($attr['filter']) and $attr['filter'] == 'trim') $product->{$field} = trim($product->{$field});
|
||||
if(is_array($product->$field)) $product->{$field} = implode(',', $product->{$field});
|
||||
|
||||
/* 检查必填项。 */
|
||||
if(!empty($attr['required']) and validater::checkEmpty($product->{$field})) dao::$errors[] = 'product #' . $productID . sprintf($this->lang->error->notempty, zget($attr, 'title', zget($this->lang->product, $field)));
|
||||
}
|
||||
|
||||
$products[$productID] = $product;
|
||||
}
|
||||
|
||||
return $products;
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功插入产品数据后,其他的额外操作。
|
||||
* Process after create product.
|
||||
@@ -596,4 +723,37 @@ class productZen extends product
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 追加工作流配置字段。
|
||||
* Append flow fields.
|
||||
*
|
||||
* @param array $fields
|
||||
* @param string $type single|batch
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function appendFlowFields(array $fields, string $type = 'single'): array
|
||||
{
|
||||
$extendFields = $this->product->getFlowExtendFields();
|
||||
if(empty($extendFields)) return $fields;
|
||||
|
||||
/* 构造表单属性,并追加到表单配置中。 */
|
||||
foreach($extendFields as $extendField)
|
||||
{
|
||||
$control = $extendField->control;
|
||||
if($control == 'richtext') $control = 'editor';
|
||||
if($control == 'input') $control = 'text';
|
||||
|
||||
$field = $extendField;
|
||||
$fields[$field] = array();
|
||||
$fields[$field]['type'] = $type == 'single' ? 'string' : 'array';
|
||||
$fields[$field]['control'] = $control;
|
||||
$fields[$field]['title'] = $extendField->name;
|
||||
$fields[$field]['default'] = $extendField->default;
|
||||
$fields[$field]['options'] = $extendField->options;
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -136,13 +136,13 @@ fields:
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: finishedDate
|
||||
note: "完成时间"
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
#- field: finishedDate
|
||||
# note: "完成时间"
|
||||
# range: ""
|
||||
# prefix: ""
|
||||
# postfix: ""
|
||||
# loop: 0
|
||||
# format: ""
|
||||
- field: closedBy
|
||||
note: "由谁关闭"
|
||||
range: ""
|
||||
@@ -150,6 +150,6 @@ fields:
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: closedDate
|
||||
note: "关闭时间"
|
||||
range: ""
|
||||
#- field: closedDate
|
||||
# note: "关闭时间"
|
||||
# range: ""
|
||||
|
||||
Reference in New Issue
Block a user