diff --git a/db/update20.0.sql b/db/update20.0.sql
index 50ed330a85..334b6ef21a 100644
--- a/db/update20.0.sql
+++ b/db/update20.0.sql
@@ -1,5 +1,4 @@
ALTER TABLE `zt_block` ADD `dashboard` varchar(20) NOT NULL DEFAULT '' AFTER `account`;
-ALTER TABLE `zt_block` ADD `createdDate` date NULL AFTER `height`;
ALTER TABLE `zt_block` CHANGE `block` `code` varchar(30) NOT NULL DEFAULT '' AFTER `module`;
ALTER TABLE `zt_block` MODIFY `vision` varchar(10) NOT NULL DEFAULT 'rnd' AFTER `hidden`;
diff --git a/module/block/control.php b/module/block/control.php
index a0a3bee531..81edf396e2 100755
--- a/module/block/control.php
+++ b/module/block/control.php
@@ -180,7 +180,7 @@ class block extends control
/* 永久关闭区块。 */
$block = $this->block->getByID($blockID);
- $this->block->deleteBlock(0, $block->module, $block->code);
+ $this->block->deleteBlock($blockID);
/* 将关闭的区块保存到配置信息。 */
$closedBlock = isset($this->config->block->closed) ? $this->config->block->closed : '';
diff --git a/module/block/lang/zh-cn.php b/module/block/lang/zh-cn.php
index 09c2f0bd7f..2a8b921da9 100644
--- a/module/block/lang/zh-cn.php
+++ b/module/block/lang/zh-cn.php
@@ -34,7 +34,6 @@ $lang->block->lblModule = '模块';
$lang->block->lblBlock = '区块';
$lang->block->lblNum = '条数';
$lang->block->lblHtml = 'HTML内容';
-$lang->block->html = 'HTML';
$lang->block->dynamic = '最新动态';
$lang->block->assignToMe = '待处理';
$lang->block->wait = '未开始';
@@ -422,18 +421,12 @@ $lang->block->availableBlocks['meeting'] = '会议';
$lang->block->availableBlocks['feedback'] = '反馈';
$lang->block->availableBlocks['ticket'] = '工单';
-$lang->block->moduleList['product'] = $lang->productCommon;
-$lang->block->moduleList['project'] = $lang->projectCommon;
-$lang->block->moduleList['execution'] = $lang->execution->common;
-$lang->block->moduleList['qa'] = '测试';
-$lang->block->moduleList['todo'] = '待办';
-$lang->block->moduleList['doc'] = '文档';
-$lang->block->moduleList['assigntome'] = $lang->block->assignToMe;
-$lang->block->moduleList['dynamic'] = $lang->block->dynamic;
-$lang->block->moduleList['guide'] = $lang->block->guide;
-$lang->block->moduleList['welcome'] = $lang->block->welcome;
-$lang->block->moduleList['html'] = $lang->block->html;
-$lang->block->moduleList['contribute'] = $lang->block->contribute;
+$lang->block->moduleList['product'] = $lang->productCommon;
+$lang->block->moduleList['project'] = $lang->projectCommon;
+$lang->block->moduleList['execution'] = $lang->execution->common;
+$lang->block->moduleList['qa'] = '测试';
+$lang->block->moduleList['todo'] = '待办';
+$lang->block->moduleList['doc'] = '文档';
$lang->block->modules['project'] = new stdclass();
$lang->block->modules['project']->availableBlocks['project'] = "{$lang->projectCommon}列表";
@@ -452,8 +445,8 @@ $lang->block->modules['waterfallProject'] = new stdclass();
$lang->block->modules['waterfallProject']->availableBlocks['waterfallgantt'] = "{$lang->projectCommon}计划";
$lang->block->modules['waterfallProject']->availableBlocks['projectdynamic'] = '最新动态';
-$lang->block->modules['agileplus'] = $lang->block->modules['scrumProject'];
-$lang->block->modules['waterfallplus'] = $lang->block->modules['waterfallProject'];
+$lang->block->modules['agileplus']['index'] = $lang->block->modules['scrumProject'];
+$lang->block->modules['waterfallplus']['index'] = $lang->block->modules['waterfallProject'];
$lang->block->modules['product'] = new stdclass();
$lang->block->modules['product']->availableBlocks['statistic'] = $lang->productCommon . '统计';
diff --git a/module/block/model.php b/module/block/model.php
index 77b12629a3..a824516fb5 100644
--- a/module/block/model.php
+++ b/module/block/model.php
@@ -13,8 +13,8 @@ declare(strict_types=1);
class blockModel extends model
{
/**
- * 检查ZDOO请求时发起的哈希值是否匹配。
- * Check if the hash value matches when requesting ZDOO.
+ * 检查然之请求时发起的hash是否匹配。
+ * Check API for ranzhi.
*
* @param string $hash
* @access public
@@ -34,8 +34,8 @@ class blockModel extends model
}
/**
- * 根据区块ID获取区块信息。
- * Get a block by id.
+ * 根据区块ID获取区块信息.
+ * Get a block by blockID.
*
* @param int $blockID
* @access public
@@ -54,68 +54,13 @@ class blockModel extends model
}
/**
- * 获取被永久关闭的区块数据。
- * getClosedBlockPairs
- *
- * @param int $closedBlock
- * @access public
- * @return void
- */
- public function getClosedBlockPairs($closedBlock)
- {
- $blockPairs = array();
- if(empty($closedBlock)) return $blockPairs;
-
- foreach(explode(',', $closedBlock) as $block)
- {
- $block = trim($block);
- if(empty($block)) continue;
-
- list($moduleName, $blockKey) = explode('|', $block);
- if($moduleName == $blockKey)
- {
- $blockPairs[$block] = $this->lang->block->moduleList[$moduleName];
- }
- else
- {
- $blockName = $blockKey;
- if(isset($this->lang->block->modules[$moduleName]->availableBlocks[$blockKey])) $blockName = $this->lang->block->modules[$moduleName]->availableBlocks[$blockKey];
- if(isset($this->lang->block->availableBlocks[$blockKey])) $blockName = $this->lang->block->availableBlocks[$blockKey];
- $blockPairs[$block] = "{$this->lang->block->moduleList[$moduleName]}|{$blockName}";
- }
- }
-
- return $blockPairs;
- }
-
- /**
- * 获取后台信息区块参数信息。
- * get admin information block parameter information.
- *
- * @param string $startDate
- * @access public
- * @return array|false
- */
- public function getAdminBlockList(string $startDate = ''): array|false
- {
- return $this->dao->select('code,params')->from(TABLE_BLOCK)
- ->where('account')->eq('system')
- ->andWhere('vision')->eq('rnd')
- ->andWhere('dashboard')->eq('zentao')
- ->andWhere('module')->eq('zentao')
- ->andWhere('code')->in('plugin,patch,publicclass,news')
- ->beginIF($startDate)->andWhere('createdDate')->ge($startDate)->fi()
- ->fetchPairs();
- }
-
- /**
- * 获取当前用户的区块列表。
* Get block list of current user.
+ * 获取区块列表.
*
* @param string $module
* @param int $hidden
* @access public
- * @return array|false
+ * @return int[]|false
*/
public function getMyDashboard(string $dashboard, int $hidden = 0): array|false
{
@@ -123,12 +68,12 @@ class blockModel extends model
}
/**
- * 获取隐藏的区块列表。
- * Get hidden blocks.
+ * 获取隐藏的区块列表.
+ * Get hidden blocks
*
* @param string $module
* @access public
- * @return array|false
+ * @return int[]|false
*/
public function getMyHiddenBlocks(string $dashboard): array|false
{
@@ -136,8 +81,8 @@ class blockModel extends model
}
/**
- * 获取对应仪表盘下区块的最大排序号。
- * Get block max order number by dashboard.
+ * 获取对应仪表盘下区块的最大排序号.
+ * Get max order number by block dashboard.
*
* @param string $dashboard
* @access public
@@ -242,11 +187,11 @@ class blockModel extends model
/**
* 根据区块索引获取排序靠后的一个区块ID。
- * Get the last block order on the block index,
- *
- * @param string $dashboard
- * @param string $module
- * @param string $code
+ * Get my block id by block code,
+ *
+ * @param string $dashboard
+ * @param string $module
+ * @param string $code
* @access public
* @return int|false
*/
@@ -265,7 +210,7 @@ class blockModel extends model
}
/**
- * 获取区块是否已经初始化的状态。
+ * 获取区块是否已经初始化的状态.
* get block is initiated or not.
*
* @param string $dashboard
@@ -274,7 +219,7 @@ class blockModel extends model
*/
public function getBlockInitStatus(string $dashboard): bool
{
- $result = $this->dao->select('value')->from(TABLE_CONFIG)
+ $result = $this->dao->select('*')->from(TABLE_CONFIG)
->where('module')->eq($dashboard)
->andWhere('owner')->eq($this->app->user->account)
->andWhere('`section`')->eq('common')
@@ -282,24 +227,24 @@ class blockModel extends model
->andWhere('vision')->eq($this->config->vision)
->fetch('value');
- return !empty($result);
+ return $result ? true : false;
}
/**
* 检查此区块是否为长区块。
* Check whether long block.
*
- * @param object $block
+ * @param object $block
* @access public
* @return bool
*/
public function isLongBlock(object $block): bool
{
- return (!empty($block->grid) and $block->grid >= 6);
+ return (!empty($block->grid) and $block->grid >= 6) ? true : false;
}
/**
- * 初始化用户某个仪表盘下的区块数据。
+ * 初始化用户某个仪表盘下的区块数据.
* Init block when account use first.
*
* @param string $dashboard
@@ -341,7 +286,7 @@ class blockModel extends model
*
* @param object $formData
* @access public
- * @return int
+ * @return void
*/
public function create(object $formData): int|false
{
@@ -360,7 +305,7 @@ class blockModel extends model
*
* @param object $formData
* @access public
- * @return int|false
+ * @return void
*/
public function update(object $formData): int|false
{
@@ -381,7 +326,7 @@ class blockModel extends model
* 对应仪表盘删除所有区块并更新为待初始化状态。
* Reset dashboard blocks.
*
- * @param string $dashboard
+ * @param string $dashboard
* @access public
* @return bool
*/
@@ -400,33 +345,26 @@ class blockModel extends model
->andWhere('`key`')->eq('blockInited')
->exec();
- return !dao::isError();
+ return true;
}
/**
- * 根据ID删除一个区块或者根据代号删除多个区块。
- * Delete a block based on id or multiple blocks based on code.
+ * 删除一个区块。
+ * Delete a block.
*
* @param int $blockID
* @access public
* @return bool
*/
- public function deleteBlock(int $blockID = 0, string $module = '', string $code = ''): bool
+ public function deleteBlock(int $blockID): bool
{
$this->dao->delete()->from(TABLE_BLOCK)
- ->where('1=1')
- ->beginIF($blockID)
- ->andWhere('id')->eq($blockID)
+ ->where('id')->eq($blockID)
->andWhere('account')->eq($this->app->user->account)
->andWhere('vision')->eq($this->config->vision)
- ->fi()
- ->beginIF($module and $code)
- ->andWhere('module')->eq($module)
- ->andWhere('code')->eq($code)
- ->fi()
->exec();
- return !dao::isError();
+ return true;
}
/**
@@ -441,7 +379,6 @@ class blockModel extends model
public function setOrder(int $blockID, int $order): bool
{
$this->dao->update(TABLE_BLOCK)->set('order')->eq($order)->where('id')->eq($blockID)->exec();
-
- return !dao::isError();
+ return true;
}
}
diff --git a/module/block/tao.php b/module/block/tao.php
index 1b386c18ab..1cbb176fd7 100644
--- a/module/block/tao.php
+++ b/module/block/tao.php
@@ -3,13 +3,13 @@ declare(strict_types=1);
class blockTao extends blockModel
{
/**
- * 获取当前用户的区块列表。
+ * 获取当前用户的区块列表.
* Get block list of current user.
*
* @param string $dashboard
* @param int $hidden 0|1
* @access protected
- * @return array|false
+ * @return int[]|false
*/
protected function fetchMyBlocks(string $dashboard, int $hidden = 0): array|false
{
@@ -23,7 +23,6 @@ class blockTao extends blockModel
}
/**
- * 新增一个区块。
* Insert a block data.
*
* @param object $formData
@@ -37,6 +36,6 @@ class blockTao extends blockModel
->batchCheck($this->config->block->create->requiredFields, 'notempty')
->exec();
- return !dao::isError();
+ return true;
}
}
diff --git a/module/block/test/model/checkapi.php b/module/block/test/model/checkapi.php
index b9b93889a6..3bc2f809af 100755
--- a/module/block/test/model/checkapi.php
+++ b/module/block/test/model/checkapi.php
@@ -1,6 +1,6 @@
#!/usr/bin/env php
loadModel('block');
initData();
$blockTest = new blockTest();
-r($tester->block->getByID(2)) && p('id') && e('2'); // 测试ID为2的区块是否存在
-r($tester->block->deleteBlock(2, '', '')) && p('') && e('1'); // 测试ID为2的区块删除后的返回结果
-r($tester->block->getByID(2)) && p('id') && e('0'); // 测试ID为2的区块的是否存在
-r($tester->block->getByID(3)) && p('id') && e('3'); // 测试ID为3的区块的是否存在
-r($tester->block->deleteBlock(0, 'project', 'statistic')) && p('') && e('1'); // 测试根据代号删除区块后的返回结果
-r($tester->block->getByID(3)) && p('id') && e('0'); // 测试ID为3的区块的是否存在
+r($tester->block->getByID(2)) && p('id') && e("2"); // 测试ID为2的区块是否存在
+r($tester->block->deleteBlock(2)) && p('') && e('1'); // 测试ID为2的区块删除后的返回结果
+r($tester->block->getByID(2)) && p('id') && e("0"); // 测试ID为2的区块的是否存在
r($tester->block->deleteBlock(22)) && p('') && e('1'); // 测试ID为22的区块删除后的返回结果
\ No newline at end of file
diff --git a/module/block/test/model/getadminblocklist.php b/module/block/test/model/getadminblocklist.php
deleted file mode 100644
index e9b3a783eb..0000000000
--- a/module/block/test/model/getadminblocklist.php
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env php
-id->range('2-5');
- $block->account->range('system');
- $block->vision->range('rnd');
- $block->dashboard->range('zentao');
- $block->module->range('zentao');
- $block->code->range('plugin,patch,publicclass,news');
- $block->createdDate->range('`2020-01-01`,`2021-01-01`');
- $block->title->prefix('区块')->range('2-5');
- $block->order->range('2-5');
-
- $block->gen(4);
-}
-
-/**
-
-title=测试 block 模块 model下的 getMyDashboard 方法
-timeout=0
-cid=39
-
-- 查询admin用户在我的地盘仪表盘的区块列表数量 @4
-
-- 查询admin用户在我的地盘仪表盘的区块列表数量 @2
-
-*/
-
-global $tester;
-$tester->loadModel('block');
-
-initData();
-
-r(count($tester->block->getAdminBlockList())) && p('') && e('4'); // 查询admin用户在我的地盘仪表盘的区块列表数量
-r(count($tester->block->getAdminBlockList('2021-01-01'))) && p('') && e('2'); // 查询admin用户在我的地盘仪表盘的区块列表数量
\ No newline at end of file
diff --git a/module/block/test/model/getblockinitstatus.php b/module/block/test/model/getblockinitstatus.php
index a73782de0a..8241221aed 100644
--- a/module/block/test/model/getblockinitstatus.php
+++ b/module/block/test/model/getblockinitstatus.php
@@ -22,12 +22,6 @@ title=测试 blockModel->getBlockInitStatus();
timeout=0
cid=1
-- 测试 my 模块下返回为 1 @1
-
-- 测试 product 模块下返回为 0 @0
-
-- 测试不存在模块返回为 0 @0
-
*/
global $tester;
@@ -37,4 +31,4 @@ initData();
r($tester->block->getBlockInitStatus('my')) && p('') && e('1'); // 测试 my 模块下返回为 1
r($tester->block->getBlockInitStatus('product')) && p('') && e('0'); // 测试 product 模块下返回为 0
-r($tester->block->getBlockInitStatus('asda??')) && p('') && e('0'); // 测试不存在模块返回为 0
\ No newline at end of file
+r($tester->block->getBlockInitStatus('asda??')) && p('') && e('0'); // 测试不存在模块返回为 0
diff --git a/module/block/test/model/getbyid.php b/module/block/test/model/getbyid.php
index b320b62cf8..b1bbbba46a 100755
--- a/module/block/test/model/getbyid.php
+++ b/module/block/test/model/getbyid.php
@@ -1,6 +1,6 @@
#!/usr/bin/env php
loadModel('block');
initData();
-r($tester->block->getByID(2)) && p('account,vision,dashboard,module,code,title,order') && e('admin,rnd,my,project,list,区块名称2,1'); // 测试获取正常的block的内容
-r($tester->block->getByID(4)) && p('order') && e('3'); // 测试获取正常的block的内容
-r($tester->block->getByID(6)) && p('') && e('0'); // 测试获取不存在的block的内容
\ No newline at end of file
+r($tester->block->getByID(2)) && p('account,vision,dashboard,module,code,title,order') && e('admin,rnd,my,project,list,区块名称2,1'); // 测试获取正常的block的内容
+r($tester->block->getByID(4)) && p('order') && e('3'); // 测试获取正常的block的内容
+r($tester->block->getByID(6)) && p('') && e('0'); // 测试获取不存在的block的内容
\ No newline at end of file
diff --git a/module/block/test/model/getclosedblockpairs.php b/module/block/test/model/getclosedblockpairs.php
deleted file mode 100755
index c2d6f886ed..0000000000
--- a/module/block/test/model/getclosedblockpairs.php
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env php
-getClosedBlockPairs();
-timeout=0
-cid=1
-
-- 测试获取关闭的区块键值对属性product|list @产品|产品列表
-
-- 测试获取关闭的区块键值对属性assigntome|assigntome @待处理
-
-*/
-
-global $tester;
-$tester->loadModel('block');
-$data = $tester->block->getClosedBlockPairs('product|list,assigntome|assigntome');
-r($data) && p('product|list') && e('产品|产品列表'); //测试获取关闭的区块键值对
-r($data) && p('assigntome|assigntome') && e('待处理'); //测试获取关闭的区块键值对
\ No newline at end of file
diff --git a/module/block/test/model/getmaxorderbydashboard.php b/module/block/test/model/getmaxorderbydashboard.php
index dcb3212979..37642b47d5 100644
--- a/module/block/test/model/getmaxorderbydashboard.php
+++ b/module/block/test/model/getmaxorderbydashboard.php
@@ -1,6 +1,6 @@
#!/usr/bin/env php
loadModel('block');
initData();
-r($tester->block->getMaxOrderByDashboard('my')) && p('') && e('4'); // 测试 my 模块下最大order 为 4
-r($tester->block->getMaxOrderByDashboard('my')) && p('') && e('4'); // 测试 my 模块下最大order 为 4
+r($tester->block->getMaxOrderByDashboard('my')) && p('') && e('4'); // 测试 my 模块下最大order 为 4
+r($tester->block->getMaxOrderByDashboard('my')) && p('') && e('4'); // 测试 my 模块下最大order 为 4
r($tester->block->getMaxOrderByDashboard('bug')) && p('') && e('0'); // 测试数据库中不存在 模块的最大排序 为 0
\ No newline at end of file
diff --git a/module/block/test/model/getmydashboard.php b/module/block/test/model/getmydashboard.php
index 6bdf5933b9..9d3e690b35 100644
--- a/module/block/test/model/getmydashboard.php
+++ b/module/block/test/model/getmydashboard.php
@@ -1,6 +1,6 @@
#!/usr/bin/env php
loadModel('block');
initData();
-r(count($tester->block->getMyDashboard('my'))) && p('') && e('1'); // 查询admin用户在我的地盘仪表盘的区块列表数量
-r($tester->block->getMyDashboard('my')) && p('2:title') && e('区块2'); // 查询admin用户在我的地盘仪表盘的区块标题第2条的title属性
-r(count($tester->block->getMyDashboard('my', 1))) && p('') && e('0'); // 查询admin用户在我的地盘仪表盘的隐藏区块列表数量
-r(count($tester->block->getMyDashboard('asdas?'))) && p('') && e('0'); // 查询admin用户在不存在仪表盘的区块列表数量
-r($tester->block->getMyDashboard('my')) && p('2:vision') && e('rnd'); // 查询admin用户在我的地盘仪表盘区块的vision第2条的vision属性
\ No newline at end of file
+r(count($tester->block->getMyDashboard('my'))) && p('') && e('1'); // 查询admin用户在我的地盘仪表盘的区块列表数量
+r($tester->block->getMyDashboard('my')) && p('2:title') && e('区块2'); // 查询admin用户在我的地盘仪表盘的区块标题第2条的title属性
+r(count($tester->block->getMyDashboard('my', 1))) && p('') && e('0'); // 查询admin用户在我的地盘仪表盘的隐藏区块列表数量
+r(count($tester->block->getMyDashboard('asdas?'))) && p('') && e('0'); // 查询admin用户在不存在仪表盘的区块列表数量
+r($tester->block->getMyDashboard('my')) && p('2:vision') && e('rnd'); // 查询admin用户在我的地盘仪表盘区块的vision第2条的vision属性
\ No newline at end of file
diff --git a/module/block/test/model/getspecifiedblockid.php b/module/block/test/model/getspecifiedblockid.php
index f5342ec4f6..4824c6437d 100644
--- a/module/block/test/model/getspecifiedblockid.php
+++ b/module/block/test/model/getspecifiedblockid.php
@@ -1,6 +1,6 @@
#!/usr/bin/env php
loadModel('block');
initData();
r($tester->block->getSpecifiedBlockID('my', 'assingtome', 'assingtome')) && p('') && e('2'); // 测试 assingtome 区块的 区块ID是否为2
-r($tester->block->getSpecifiedBlockID('qa', 'bug', 'list')) && p('') && e('3'); // 测试 buglist 区块的 区块ID是否为2
-r($tester->block->getSpecifiedBlockID('my', 'welcome', 'welcome')) && p('') && e('0'); // 测试 找不到的区块的 区块ID 是否为 false
\ No newline at end of file
+r($tester->block->getSpecifiedBlockID('qa', 'bug', 'list')) && p('') && e('3'); // 测试 buglist 区块的 区块ID是否为2
+r($tester->block->getSpecifiedBlockID('my', 'welcome', 'welcome')) && p('') && e('0'); // 测试 找不到的区块的 区块ID 是否为 false
\ No newline at end of file
diff --git a/module/block/test/model/initblock.php b/module/block/test/model/initblock.php
index 090be20f6a..28b1e2f6a9 100755
--- a/module/block/test/model/initblock.php
+++ b/module/block/test/model/initblock.php
@@ -1,6 +1,6 @@
#!/usr/bin/env php
initBlock();
timeout=0
cid=1
-- 测试获取初始化后第一个的block的内容
+- 测试获取正常的block的内容
- 属性account @admin
- 属性dashboard @my
- 属性module @welcome
- 属性code @welcome
- 属性title @欢迎
-- 测试获取初始化后最后一个的block的内容
+- 测试获取正常的block的内容
- 属性account @admin
- 属性dashboard @my
- 属性module @project
@@ -33,5 +33,5 @@ $tester->block->reset('my');
$tester->block->initBlock('my');
$newBlcoks = $tester->block->getMyDashboard('my');
-r(reset($newBlcoks)) && p('account,dashboard,module,code,title') && e('admin,my,welcome,welcome,欢迎'); // 测试获取初始化后第一个的block的内容
-r(end($newBlcoks)) && p('account,dashboard,module,code,title') && e('admin,my,project,project,项目列表'); // 测试获取初始化后最后一个的block的内容
\ No newline at end of file
+r(reset($newBlcoks)) && p('account,dashboard,module,code,title') && e('admin,my,welcome,welcome,欢迎'); // 测试获取正常的block的内容
+r(end($newBlcoks)) && p('account,dashboard,module,code,title') && e('admin,my,project,project,项目列表'); // 测试获取正常的block的内容
\ No newline at end of file
diff --git a/module/block/test/model/islongblock.php b/module/block/test/model/islongblock.php
index acf4db8874..7f6c32e76c 100755
--- a/module/block/test/model/islongblock.php
+++ b/module/block/test/model/islongblock.php
@@ -1,6 +1,6 @@
#!/usr/bin/env php
isLongBlock();
timeout=0
cid=1
-- 测试空对象是否为长区块 @0
+- 测试 空 对象 检查是否为长区块 @0
-- 测试ID为2的对象是否为长区块 @0
+- 测试 空 对象 检查是否为长区块 @0
-- 测试ID为3的对象是否为长区块 @1
+- 测试 空 对象 检查是否为长区块 @1
*/
@@ -42,6 +42,6 @@ initData();
$emptyObject = new stdclass();
-r($tester->block->isLongBlock($emptyObject)) && p() && e('0'); // 测试空对象是否为长区块
-r($tester->block->isLongBlock($tester->block->getByID(2))) && p() && e('0'); // 测试ID为2的对象是否为长区块
-r($tester->block->isLongBlock($tester->block->getByID(3))) && p() && e('1'); // 测试ID为3的对象是否为长区块
\ No newline at end of file
+r($tester->block->isLongBlock($emptyObject)) && p() && e('0'); // 测试 空 对象 检查是否为长区块
+r($tester->block->isLongBlock($tester->block->getByID(2))) && p() && e('0'); // 测试 空 对象 检查是否为长区块
+r($tester->block->isLongBlock($tester->block->getByID(3))) && p() && e('1'); // 测试 空 对象 检查是否为长区块
\ No newline at end of file
diff --git a/module/block/test/model/reset.php b/module/block/test/model/reset.php
index d26fbdd4b6..6afe36b26f 100644
--- a/module/block/test/model/reset.php
+++ b/module/block/test/model/reset.php
@@ -1,6 +1,6 @@
#!/usr/bin/env php
block->reset('my');
$tester->block->initBlock('my');
r($tester->block->getBlockInitStatus('my')) && p('') && e('1'); // 检查初始化前的区块初始化状态返回结果
-
-$resetBeforeBlocks = $tester->block->getMyDashboard('my');
-r(reset($resetBeforeBlocks)) && p('account,dashboard,module,code,title') && e('admin,my,welcome,welcome,欢迎'); // 检查初始化前是否存在区块数据
-
+$myDashboard = $tester->block->getMyDashboard('my');
+r(reset($myDashboard)) && p('account,dashboard,module,code,title') && e('admin,my,welcome,welcome,欢迎'); // 检查初始化前是否存在区块数据
r($tester->block->reset('my')) && p('') && e('1'); // 检查初始化后的返回结果
r($tester->block->getBlockInitStatus('my')) && p('') && e('0'); // 检查初始化后的区块初始化状态返回结果
-
-$resetAfterBlocks = $tester->block->getMyDashboard('my');
-r(reset($resetAfterBlocks)) && p('account') && e('0'); // 检查初始化后是否存在区块数据
\ No newline at end of file
+$myDashboard2 = $tester->block->getMyDashboard('my');
+r(reset($myDashboard2)) && p('account') && e('0'); // 检查初始化前是否存在区块数据
\ No newline at end of file
diff --git a/module/block/test/model/setorder.php b/module/block/test/model/setorder.php
index 9dd4759244..64aafc8e00 100644
--- a/module/block/test/model/setorder.php
+++ b/module/block/test/model/setorder.php
@@ -1,6 +1,6 @@
#!/usr/bin/env php
order = '1';
$blockTest = new blockTest();
r($tester->block->setOrder($block1->id, $block1->order)) && p('') && e('1'); // 测试ID为2的区块变更排序后的返回结果
-r($tester->block->getByID($block1->id)) && p('id,order') && e('2,3'); // 测试ID为2的区块的序号
+r($tester->block->getByID($block1->id)) && p('id,order') && e("2,3"); // 测试ID为2的区块的序号
r($tester->block->setOrder($block2->id, $block2->order)) && p('') && e('1'); // 测试ID为2的区块变更排序后的返回结果
-r($tester->block->getByID($block2->id)) && p('id,order') && e('3,1'); // 测试ID为3的区块的序号
\ No newline at end of file
+r($tester->block->getByID($block2->id)) && p('id,order') && e("3,1"); // 测试ID为3的区块的序号
\ No newline at end of file
diff --git a/module/block/test/model/update.php b/module/block/test/model/update.php
index 57b98ecb38..abfbd75d78 100644
--- a/module/block/test/model/update.php
+++ b/module/block/test/model/update.php
@@ -1,6 +1,6 @@
#!/usr/bin/env php
title = '';
$blockTest = new blockTest();
$newBlockID = $blockTest->updateTest($block);
-r($tester->block->getByID($newBlockID)) && p('account,vision,dashboard,module,code,title,order') && e('admin2,lite,scrumproject,project,statistic,项目统计区块,1'); // 测试获取正常的block的内容
+r($tester->block->getByID($newBlockID)) && p('account,vision,dashboard,module,code,title,order') && e("admin2,lite,scrumproject,project,statistic,项目统计区块,1"); // 测试获取正常的block的内容
r($blockTest->updateTest($emptyModuleBlock)) && p('module:0') && e('『所属模块』不能为空。'); // 测试所属模块为空
r($blockTest->updateTest($emptyCodeBlock)) && p('code:0') && e('『区块』不能为空。'); // 测试所属区块为空
r($blockTest->updateTest($emptyTitleBlock)) && p('title:0') && e('『区块名称』不能为空。'); // 测试区块名称为空
diff --git a/module/block/ui/productstatisticblock.html.php b/module/block/ui/productstatisticblock.html.php
index 90d78f129f..6e2207cc4f 100644
--- a/module/block/ui/productstatisticblock.html.php
+++ b/module/block/ui/productstatisticblock.html.php
@@ -23,7 +23,7 @@ namespace zin;
function getProductTabs($products, $blockNavCode): array
{
$navTabs = array();
- $selected = key($products);
+ $selected = key($products);
foreach($products as $product)
{
$navTabs[] = li
@@ -65,7 +65,7 @@ function getProductInfo($products, $blockNavID): array
{
global $lang;
- $selected = key($products);
+ $selected = key($products);
$tabItems = array();
foreach($products as $product)
{
diff --git a/module/block/ui/projectstatisticblock.html.php b/module/block/ui/projectstatisticblock.html.php
index 6cb03fd933..01e7b99a49 100644
--- a/module/block/ui/projectstatisticblock.html.php
+++ b/module/block/ui/projectstatisticblock.html.php
@@ -23,7 +23,7 @@ namespace zin;
function getProjectTabs($projects, $blockNavCode): array
{
$navTabs = array();
- $selected = key($projects);
+ $selected = key($projects);
foreach($projects as $project)
{
$navTabs[] = li
@@ -63,7 +63,7 @@ function getProjectTabs($projects, $blockNavCode): array
*/
function getProjectInfo($projects, $blockNavID): array
{
- $selected = key($projects);
+ $selected = key($projects);
$tabItems = array();
foreach($projects as $project)
{
diff --git a/module/block/ui/qastatisticblock.html.php b/module/block/ui/qastatisticblock.html.php
index 51b090d2a0..4dd1edd378 100644
--- a/module/block/ui/qastatisticblock.html.php
+++ b/module/block/ui/qastatisticblock.html.php
@@ -23,7 +23,7 @@ namespace zin;
function getProductTabs($products, $blockNavCode): array
{
$navTabs = array();
- $selected = key($products);
+ $selected = key($products);
foreach($products as $product)
{
$navTabs[] = li
@@ -65,7 +65,7 @@ function getProductInfo($products, $blockNavID): array
{
global $lang;
- $selected = key($products);
+ $selected = key($products);
$tabItems = array();
foreach($products as $product)
{
diff --git a/module/block/zen.php b/module/block/zen.php
index a96c276032..96322d4469 100644
--- a/module/block/zen.php
+++ b/module/block/zen.php
@@ -16,13 +16,9 @@ class blockZen extends block
if($dashboard != 'my') return array();
$modules = $this->lang->block->moduleList;
-
/* Unable to display the doc module on my dashboard. */
unset($modules['doc']);
- if($this->config->global->flow != 'full') unset($modules['guide']);
- if($this->config->vision != 'rnd') unset($modules['contribute']);
-
/* 从配置项中取出不同模块的首页对应的控制器方法。*/
/* Retrieve the controller method corresponding to the homepage of different modules from the configuration item.*/
list($programModule, $programMethod) = explode('-', $this->config->programLink);
@@ -30,7 +26,6 @@ class blockZen extends block
list($projectModule, $projectMethod) = explode('-', $this->config->projectLink);
list($executionModule, $executionMethod) = explode('-', $this->config->executionLink);
- $closedBlock = isset($this->config->block->closed) ? $this->config->block->closed : '';
foreach($modules as $moduleKey => $moduleName)
{
if($moduleKey == 'todo') continue;
@@ -45,12 +40,18 @@ class blockZen extends block
/* After obtaining module permissions, it is necessary to verify whether there is permission for the module homepage. */
if(!common::hasPriv($moduleKey, $method)) unset($modules[$moduleKey]);
-
- /* 被永久关闭的区块删除对应选项。 */
- /* Delete corresponding options for blocks that have been permanently closed. */
- if(strpos(",$closedBlock,", ",$moduleKey|$moduleKey,") !== false) unset($modules[$moduleKey]);
}
+ /* 判断区块是否被永久关闭,如果未被永久关闭则添加相应选项。*/
+ /* Determine whether the block has been permanently closed, and add corresponding options if it has not been permanently closed.*/
+ $closedBlock = isset($this->config->block->closed) ? $this->config->block->closed : '';
+ if(strpos(",$closedBlock,", ",|assigntome,") === false) $modules['assigntome'] = $this->lang->block->assignToMe;
+ if(strpos(",$closedBlock,", ",|dynamic,") === false) $modules['dynamic'] = $this->lang->block->dynamic;
+ if(strpos(",$closedBlock,", ",|guide,") === false and $this->config->global->flow == 'full') $modules['guide'] = $this->lang->block->guide;
+ if(strpos(",$closedBlock,", ",|welcome,") === false and $this->config->global->flow == 'full') $modules['welcome'] = $this->lang->block->welcome;
+ if(strpos(",$closedBlock,", ",|html,") === false) $modules['html'] = 'HTML';
+ if(strpos(",$closedBlock,", ",|contribute,") === false and $this->config->vision == 'rnd') $modules['contribute'] = $this->lang->block->contribute;
+
return array('' => '') + $modules;
}
diff --git a/module/programplan/model.php b/module/programplan/model.php
index faf0bff7ad..d27f174dd5 100755
--- a/module/programplan/model.php
+++ b/module/programplan/model.php
@@ -100,8 +100,7 @@ class programplanModel extends model
}
/**
- * 获取项目中的阶段数据键值对。
- * Get plan pairs in the project.
+ * Get pairs.
*
* @param int $executionID
* @param int $productID
@@ -109,7 +108,7 @@ class programplanModel extends model
* @access public
* @return array
*/
- public function getPairs(int $executionID, int $productID = 0, string $type = 'all'): array
+ public function getPairs($executionID, $productID = 0, $type = 'all')
{
$plans = $this->getStage($executionID, $productID, $type);
@@ -125,14 +124,12 @@ class programplanModel extends model
{
if(strpos($type, 'leaf') !== false and isset($parents[$plan->id])) continue;
- $paths = array_slice(explode(',', trim($plan->path, ',')), 1);
+ $paths = array_slice(explode(',', trim($plan->path, ',')), 1);
$planName = '';
-
foreach($paths as $path)
{
if(isset($plans[$path])) $planName .= '/' . $plans[$path]->name;
}
-
$pairs[$planID] = $planName;
}
@@ -158,176 +155,34 @@ class programplanModel extends model
$plans = $this->getStage($executionID, $productID, 'all', 'order');
- if($baselineID) $plans = $this->setBaseline($baselineID, $plans);
-
- $today = helper::today();
- $datas = array();
- $planIdList = array();
- $isMilestone = " ";
- $stageIndex = array();
- foreach($plans as $plan)
+ if($baselineID)
{
- $planIdList[$plan->id] = $plan->id;
-
- $start = helper::isZeroDate($plan->begin) ? '' : $plan->begin;
- $end = helper::isZeroDate($plan->end) ? '' : $plan->end;
- $realBegan = helper::isZeroDate($plan->realBegan) ? '' : $plan->realBegan;
- $realEnd = helper::isZeroDate($plan->realEnd) ? '' : $plan->realEnd;
-
- $data = new stdclass();
- $data->id = $plan->id;
- $data->type = 'plan';
- $data->text = empty($plan->milestone) ? $plan->name : $plan->name . $isMilestone ;
- $data->name = $plan->name;
- if(isset($this->config->setPercent) and $this->config->setPercent == 1) $data->percent = $plan->percent;
- $data->attribute = zget($this->lang->stage->typeList, $plan->attribute);
- $data->milestone = zget($this->lang->programplan->milestoneList, $plan->milestone);
- $data->owner_id = $plan->PM;
- $data->status = $this->processStatus('execution', $plan);
- $data->begin = $start;
- $data->deadline = $end;
- $data->realBegan = $realBegan ? substr($realBegan, 0, 10) : '';
- $data->realEnd = $realEnd ? substr($realEnd, 0, 10) : '';;
- $data->parent = $plan->grade == 1 ? 0 :$plan->parent;
- $data->open = true;
- $data->start_date = $realBegan ? $realBegan : $start;
- $data->endDate = $realEnd ? $realEnd : $end;
- $data->duration = 1;
- $data->color = $this->lang->execution->gantt->stage->color;
- $data->progressColor = $this->lang->execution->gantt->stage->progressColor;
- $data->textColor = $this->lang->execution->gantt->stage->textColor;
- $data->bar_height = $this->lang->execution->gantt->bar_height;
-
- /* Determines if the object is delay. */
- $data->delay = $this->lang->programplan->delayList[0];
- $data->delayDays = 0;
- if($today > $end)
- {
- $data->delay = $this->lang->programplan->delayList[1];
- $data->delayDays = helper::diffDate($today, substr($end, 0, 10));
- }
-
- if($data->endDate > $data->start_date) $data->duration = helper::diffDate(substr($data->endDate, 0, 10), substr($data->start_date, 0, 10)) + 1;
- if($data->start_date) $data->start_date = date('d-m-Y', strtotime($data->start_date));
- if($data->start_date == '' or $data->endDate == '') $data->duration = 1;
-
- $datas['data'][$plan->id] = $data;
- $stageIndex[$plan->id] = array('planID' => $plan->id, 'parent' => $plan->parent, 'progress' => array('totalEstimate' => 0, 'totalConsumed' => 0, 'totalReal' => 0));
+ /* Set plan baseline. */
+ $baseline = $this->loadModel('cm')->getByID($baselineID);
+ $oldData = json_decode($baseline->data);
+ $oldPlans = $oldData->stage;
+ $plans = $this->programplanTao->setPlanBaseline($oldPlans, $plans);
}
- $taskPri = "%s ";
+ $datas = $planIdList = $stageIndex = array();
+
+ /* Set plan for gantt view. */
+ $this->programplanTao->setPlan($plans, $datas, $stageIndex, $planIdList);
/* Judge whether to display tasks under the stage. */
- $owner = $this->app->user->account;
- $module = 'programplan';
- $section = 'browse';
- $object = 'stageCustom';
+ $owner = $this->app->user->account;
+ if(empty($selectCustom)) $selectCustom = $this->loadModel('setting')->getItem("owner={$owner}&module=programplan§ion=browse&key=stageCustom");
- if(empty($selectCustom)) $selectCustom = $this->loadModel('setting')->getItem("owner={$owner}&module={$module}§ion={$section}&key={$object}");
-
- $tasks = $this->dao->select('*')->from(TABLE_TASK)->where('deleted')->eq(0)->andWhere('execution')->in($planIdList)->orderBy('execution_asc, order_asc, id_desc')->fetchAll('id');
- $taskTeams = $this->dao->select('task,account')->from(TABLE_TASKTEAM)->where('task')->in(array_keys($tasks))->fetchGroup('task', 'account');
- $users = $this->loadModel('user')->getPairs('noletter');
+ $tasks = $this->dao->select('*')->from(TABLE_TASK)->where('deleted')->eq(0)->andWhere('execution')->in($planIdList)->orderBy('execution_asc, order_asc, id_desc')->fetchAll('id');
if($baselineID)
{
$oldTasks = $oldData->task;
- foreach($oldTasks as $id => $oldTask)
- {
- if(!isset($tasks[$id])) continue;
- $tasks[$id]->version = $oldTask->version;
- $tasks[$id]->name = $oldTask->name;
- $tasks[$id]->estStarted = $oldTask->estStarted;
- $tasks[$id]->deadline = $oldTask->deadline;
- }
+ $this->programplanTao->setTaskBaseline($oldTasks, $tasks); // Set task baseline.
}
- foreach($tasks as $task)
- {
- $execution = zget($plans, $task->execution, array());
- $priIcon = sprintf($taskPri, $task->pri, $task->pri, $task->pri);
-
- $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 : '';
-
- $start = $realBegan ? $realBegan : $estStart;
- $end = $realEnd ? $realEnd : $estEnd;
- if(empty($start) and $execution) $start = $execution->begin;
- if(empty($end) and $execution) $end = $execution->end;
- if($start > $end) $end = $start;
-
- $data = new stdclass();
- $data->id = $task->execution . '-' . $task->id;
- $data->type = 'task';
- $data->text = $priIcon . $task->name;
- $data->percent = '';
- $data->status = $this->processStatus('task', $task);
- $data->owner_id = $task->assignedTo;
- $data->attribute = '';
- $data->milestone = '';
- $data->begin = $start;
- $data->deadline = $end;
- $data->realBegan = $realBegan ? substr($realBegan, 0, 10) : '';
- $data->realEnd = $realEnd ? substr($realEnd, 0, 10) : '';
- $data->pri = $task->pri;
- $data->parent = $task->parent > 0 ? $task->execution . '-' . $task->parent : $task->execution;
- $data->open = true;
- $progress = $task->consumed ? round($task->consumed / ($task->left + $task->consumed), 3) : 0;
- $data->progress = $progress;
- $data->taskProgress = ($progress * 100) . '%';
- $data->start_date = $start;
- $data->endDate = $end;
- $data->duration = 1;
- $data->estimate = $task->estimate;
- $data->consumed = $task->consumed;
- $data->color = zget($this->lang->execution->gantt->color, $task->pri, $this->lang->execution->gantt->defaultColor);
- $data->progressColor = zget($this->lang->execution->gantt->progressColor, $task->pri, $this->lang->execution->gantt->defaultProgressColor);
- $data->textColor = zget($this->lang->execution->gantt->textColor, $task->pri, $this->lang->execution->gantt->defaultTextColor);
- $data->bar_height = $this->lang->execution->gantt->bar_height;
-
- /* Determines if the object is delay. */
- $data->delay = $this->lang->programplan->delayList[0];
- $data->delayDays = 0;
- if($today > $end)
- {
- $data->delay = $this->lang->programplan->delayList[1];
- $data->delayDays = helper::diffDate($today, substr($end, 0, 10));
- }
-
- /* If multi task then show the teams. */
- if($task->mode == 'multi' and !empty($taskTeams[$task->id]))
- {
- $teams = array_keys($taskTeams[$task->id]);
- $assigneds = array();
- foreach($teams as $assignedTo) $assigneds[] = zget($users, $assignedTo);
- $data->owner_id = join(',', $assigneds);
- }
-
- if($data->endDate > $data->start_date) $data->duration = helper::diffDate(substr($data->endDate, 0, 10), substr($data->start_date, 0, 10)) + 1;
- if($data->start_date) $data->start_date = date('d-m-Y', strtotime($data->start_date));
- if($data->start_date == '' or $data->endDate == '') $data->duration = 1;
-
- if(strpos($selectCustom, 'task') !== false) $datas['data'][$data->id] = $data;
- foreach($stageIndex as $index => $stage)
- {
- if($stage['planID'] == $task->execution)
- {
- $stageIndex[$index]['progress']['totalEstimate'] += $task->estimate;
- $stageIndex[$index]['progress']['totalConsumed'] += $task->parent == '-1' ? 0 : $task->consumed;
- $stageIndex[$index]['progress']['totalReal'] += ($task->left + $task->consumed);
-
- $parent = $stage['parent'];
- if(isset($stageIndex[$parent]))
- {
- $stageIndex[$parent]['progress']['totalEstimate'] += $task->estimate;
- $stageIndex[$parent]['progress']['totalConsumed'] += $task->parent == '-1' ? 0 : $task->consumed;
- $stageIndex[$parent]['progress']['totalReal'] += ($task->left + $task->consumed);
- }
- }
- }
- }
+ /* Set task for gantt view. */
+ $this->programplanTao->setTask($tasks, $plans, $selectCustom, $datas, $stageIndex);
/* Calculate the progress of the phase. */
foreach($stageIndex as $index => $stage)
@@ -341,50 +196,12 @@ class programplanModel extends model
$datas['data'][$index]->consumed = $stage['progress']['totalConsumed'];
}
- $datas['links'] = array();
- if($this->config->edition != 'open')
- {
- $relations = $this->dao->select('*')->from(TABLE_RELATIONOFTASKS)->where('execution')->in($planIdList)->orderBy('task,pretask')->fetchAll();
- foreach($relations as $relation)
- {
- $link['source'] = $relation->execution . '-' . $relation->pretask;
- $link['target'] = $relation->execution . '-' . $relation->task;
- $link['type'] = $this->config->execution->gantt->linkType[$relation->condition][$relation->action];
- $datas['links'][] = $link;
- }
- }
+ $datas = $this->setRelationTask($planIdList, $datas);
$datas['data'] = isset($datas['data']) ? array_values($datas['data']) : array();
return $returnJson ? json_encode($datas) : $datas;
}
- /**
- * 获取基线数据。
- * Get baseline data.
- *
- * @param int $baselineID
- * @param array $plans
- * @access private
- * @return array
- */
- private function setBaseline(int $baselineID, array $plans): array
- {
- $baseline = $this->loadModel('cm')->getByID($baselineID);
- $oldData = json_decode($baseline->data);
- $oldPlans = $oldData->stage;
- foreach($oldPlans as $id => $oldPlan)
- {
- if(!isset($plans[$id])) continue;
- $plans[$id]->version = $oldPlan->version;
- $plans[$id]->name = $oldPlan->name;
- $plans[$id]->milestone = $oldPlan->milestone;
- $plans[$id]->begin = $oldPlan->begin;
- $plans[$id]->end = $oldPlan->end;
- }
-
- return $plans;
- }
-
/**
* Get gantt data group by assigned.
*
@@ -1253,6 +1070,8 @@ class programplanModel extends model
common::printIcon('execution', 'delete', "planID=$plan->id&confirm=no", $plan, 'list', 'trash', 'hiddenwin' , $disabled, '', '', $this->lang->programplan->delete);
}
break;
+ default:
+ break;
}
echo '';
}
@@ -1546,13 +1365,14 @@ class programplanModel extends model
}
/**
+ * 检查是否为顶级。
* Check whether it is the top stage.
*
* @param int $planID
* @access public
* @return bool
*/
- public function checkTopStage($planID)
+ public function checkTopStage(int $planID): bool
{
$parentID = $this->dao->select('parent')->from(TABLE_EXECUTION)->where('id')->eq($planID)->fetch('parent');
$parentType = $this->dao->select('type')->from(TABLE_EXECUTION)->where('id')->eq($parentID)->fetch('type');
diff --git a/module/programplan/test/model/yaml/getpairs/getpairs.yaml b/module/programplan/test/model/yaml/getpairs/getpairs.yaml
deleted file mode 100644
index ff22cd7204..0000000000
--- a/module/programplan/test/model/yaml/getpairs/getpairs.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
-title: zt_getpairs
-author: shenshulong
-version: '1.0'
-fields:
- - field: id
- range: 11-20
- - field: project
- range: 11-15
- - field: name
- range: 11-20
- prefix: '项目'
- - field: code
- range: 11-20
- prefix: 'project'
- - field: model
- range: 'scrum,waterfallplus'
- - field: parent
- range: 0-3
- - field: milestone
- range: 0-1
- - field: auth
- range: '[]'
- - field: type
- range: 'stage,project'
- - field: grade
- range: 1
- - field: days
- range: 1
- - field: status
- range: 'wait'
- - field: desc
- range: 11-20
- prefix: '项目描述'
- - field: budget
- range: '100000,200000'
- - field: budgetUnit
- range: 'CNY'
- - field: percent
- range: '0-0'
diff --git a/module/programplan/test/model/yaml/getpairs/getprojectproduct.yaml b/module/programplan/test/model/yaml/getpairs/getprojectproduct.yaml
deleted file mode 100644
index 8693087b04..0000000000
--- a/module/programplan/test/model/yaml/getpairs/getprojectproduct.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-title: zt_getprojectproduct
-author: shenshulong
-version: '1.0'
-fields:
- - field: project
- range: 11-15
- - field: product
- range: 11-15
- - field: branch
- range: 31-49
- - field: plan
- range: 11-15
- prefix: '计划'