diff --git a/db/zentao.sql b/db/zentao.sql
index dec33843dd..f33e71ebcd 100755
--- a/db/zentao.sql
+++ b/db/zentao.sql
@@ -14,7 +14,7 @@ CREATE TABLE IF NOT EXISTS `zt_acl` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_action`;
CREATE TABLE IF NOT EXISTS `zt_action` (
- `id` int(9) unsigned NOT NULL AUTO_INCREMENT,
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`objectType` varchar(30) NOT NULL DEFAULT '',
`objectID` mediumint(8) unsigned NOT NULL DEFAULT '0',
`product` text NULL,
@@ -37,8 +37,8 @@ CREATE TABLE IF NOT EXISTS `zt_action` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_api_lib_release`;
CREATE TABLE IF NOT EXISTS `zt_api_lib_release` (
- `id` int UNSIGNED NOT NULL AUTO_INCREMENT,
- `lib` int UNSIGNED NOT NULL DEFAULT 0,
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `lib` int(11) UNSIGNED NOT NULL DEFAULT 0,
`desc` varchar(255) NOT NULL DEFAULT '',
`version` varchar(255) NOT NULL DEFAULT '',
`snap` mediumtext NULL,
@@ -48,10 +48,10 @@ CREATE TABLE IF NOT EXISTS `zt_api_lib_release` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_api`;
CREATE TABLE IF NOT EXISTS `zt_api` (
- `id` int UNSIGNED NOT NULL AUTO_INCREMENT,
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`product` varchar(255) NOT NULL DEFAULT '',
- `lib` int UNSIGNED NOT NULL DEFAULT 0,
- `module` int UNSIGNED NOT NULL DEFAULT 0,
+ `lib` int(11) UNSIGNED NOT NULL DEFAULT 0,
+ `module` int(11) UNSIGNED NOT NULL DEFAULT 0,
`title` varchar(100) NOT NULL DEFAULT '',
`path` varchar(255) NOT NULL DEFAULT '',
`protocol` varchar(10) NOT NULL DEFAULT '',
@@ -61,7 +61,7 @@ CREATE TABLE IF NOT EXISTS `zt_api` (
`status` varchar(20) NOT NULL DEFAULT '',
`owner` varchar(30) NOT NULl DEFAULT 0,
`desc` mediumtext NULL,
- `version` smallint UNSIGNED NOT NULL DEFAULT 0,
+ `version` smallint(6) UNSIGNED NOT NULL DEFAULT 0,
`params` text NULL,
`paramsExample` text NUll,
`responseExample` text NUll,
@@ -76,9 +76,9 @@ CREATE TABLE IF NOT EXISTS `zt_api` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_apispec`;
CREATE TABLE IF NOT EXISTS `zt_apispec` (
- `id` int UNSIGNED NOT NULL AUTO_INCREMENT,
- `doc` int UNSIGNED NOT NULL DEFAULT 0,
- `module` int UNSIGNED NOT NULL DEFAULT 0,
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `doc` int(11) UNSIGNED NOT NULL DEFAULT 0,
+ `module` int(11) UNSIGNED NOT NULL DEFAULT 0,
`title` varchar(100) NOT NULL DEFAULT '',
`path` varchar(255) NOT NULL DEFAULT '',
`protocol` varchar(10) NOT NULL DEFAULT '',
@@ -88,7 +88,7 @@ CREATE TABLE IF NOT EXISTS `zt_apispec` (
`status` varchar(20) NOT NULL DEFAULT '',
`owner` varchar(255) NOT NULl DEFAULT 0,
`desc` mediumtext NULL,
- `version` smallint UNSIGNED NOT NULL DEFAULT 0,
+ `version` smallint(6) UNSIGNED NOT NULL DEFAULT 0,
`params` text NULL,
`paramsExample` text NUll,
`responseExample` text NUll,
@@ -99,12 +99,12 @@ CREATE TABLE IF NOT EXISTS `zt_apispec` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_apistruct`;
CREATE TABLE IF NOT EXISTS `zt_apistruct` (
- `id` int unsigned NOT NULL AUTO_INCREMENT,
- `lib` int UNSIGNED NOT NULL DEFAULT 0,
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+ `lib` int(11) UNSIGNED NOT NULL DEFAULT 0,
`name` varchar(30) NOT NULL DEFAULT '',
`type` varchar(50) NOT NULL DEFAULT '',
`desc` mediumtext NULL,
- `version` smallint unsigned NOT NULL DEFAULT 0,
+ `version` smallint(6) unsigned NOT NULL DEFAULT 0,
`attribute` text NULL,
`addedBy` varchar(30) NOT NULL DEFAULT 0,
`addedDate` datetime NULL,
@@ -115,12 +115,12 @@ CREATE TABLE IF NOT EXISTS `zt_apistruct` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_apistruct_spec`;
CREATE TABLE IF NOT EXISTS `zt_apistruct_spec` (
- `id` int UNSIGNED NOT NULL AUTO_INCREMENT,
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '',
`type` varchar(50) NOT NULL DEFAULT '',
`desc` varchar(255) NOT NULL DEFAULT '',
`attribute` text NULL,
- `version` smallint unsigned NOT NULL DEFAULT 0,
+ `version` smallint(6) unsigned NOT NULL DEFAULT 0,
`addedBy` varchar(30) NOT NULL DEFAULT 0,
`addedDate` datetime NULL,
primary key (`id`)
@@ -142,7 +142,7 @@ CREATE TABLE IF NOT EXISTS `zt_approval` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_approvalflow`;
CREATE TABLE IF NOT EXISTS `zt_approvalflow` (
- `id` int(8) NOT NULL AUTO_INCREMENT,
+ `id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '',
`code` varchar(100) NOT NULL DEFAULT '',
`desc` mediumtext NULL,
@@ -243,7 +243,7 @@ CREATE TABLE IF NOT EXISTS `zt_branch` (
`desc` varchar(255) NOT NULL DEFAULT '',
`createdDate` date NULL,
`closedDate` date NULL,
- `order` smallint unsigned NOT NULL DEFAULT '0',
+ `order` smallint(6) unsigned NOT NULL DEFAULT '0',
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `product` (`product`)
@@ -418,7 +418,7 @@ CREATE TABLE IF NOT EXISTS `zt_casestep` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`parent` mediumint(8) unsigned NOT NULL default '0',
`case` mediumint(8) unsigned NOT NULL default '0',
- `version` smallint(3) unsigned NOT NULL default '0',
+ `version` smallint(6) unsigned NOT NULL default '0',
`type` varchar(10) NOT NULL DEFAULT 'step',
`desc` text NULL,
`expect` text NULL,
@@ -432,14 +432,14 @@ CREATE TABLE IF NOT EXISTS `zt_cfd` (
`execution` int(8) NOT NULL DEFAULT '0',
`type` char(30) NOT NULL DEFAULT '',
`name` char(30) NOT NULL DEFAULT '',
- `count` smallint NOT NULL DEFAULT '0',
+ `count` smallint(6) NOT NULL DEFAULT '0',
`date` date NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE UNIQUE INDEX `execution_type_name_date` ON `zt_cfd`(`execution`,`type`,`name`,`date`);
-- DROP TABLE IF EXISTS `zt_chart`;
CREATE TABLE IF NOT EXISTS `zt_chart` (
- `id` mediumint unsigned NOT NULL AUTO_INCREMENT,
+ `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '',
`dimension` mediumint(8) unsigned NOT NULL DEFAULT '0',
`type` varchar(30) NOT NULL DEFAULT '',
@@ -448,7 +448,7 @@ CREATE TABLE IF NOT EXISTS `zt_chart` (
`desc` text NULL,
`settings` mediumtext NULL,
`filters` mediumtext NULL,
- `step` tinyint(1) unsigned NOT NULL DEFAULT '0',
+ `step` tinyint(3) unsigned NOT NULL DEFAULT '0',
`fields` mediumtext NULL,
`langs` text NULL,
`sql` mediumtext NULL,
@@ -459,7 +459,7 @@ CREATE TABLE IF NOT EXISTS `zt_chart` (
`createdDate` datetime NULL,
`editedBy` varchar(30) NOT NULL DEFAULT '',
`editedDate` datetime NULL,
- `deleted` tinyint NOT NULL DEFAULT '0',
+ `deleted` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_screen`;
@@ -560,25 +560,25 @@ CREATE TABLE `zt_dashboard` (
`id` mediumint(8) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '',
`dimension` int(8) NOT NULL default 0,
- `module` mediumint NOT NULL DEFAULT '0',
+ `module` mediumint(8) NOT NULL DEFAULT '0',
`desc` mediumtext NULL,
`layout` mediumtext NULL,
`filters` mediumtext NULL,
`createdBy` varchar(30) NOT NULL DEFAULT '',
`createdDate` datetime NULL,
- `deleted` tinyint NOT NULL DEFAULT '0',
+ `deleted` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_dataset`;
CREATE TABLE `zt_dataset` (
- `id` mediumint unsigned NOT NULL AUTO_INCREMENT,
+ `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(155) NOT NULL DEFAULT '',
`sql` text NULL,
`fields` mediumtext NULL,
`objects` mediumtext NULL,
`createdBy` varchar(30) NOT NULL DEFAULT '',
`createdDate` datetime NULL,
- `deleted` tinyint NOT NULL DEFAULT '0',
+ `deleted` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_dataview`;
@@ -596,7 +596,7 @@ CREATE TABLE IF NOT EXISTS `zt_dataview` (
`createdDate` datetime NULL,
`editedBy` varchar(30) NULL DEFAULT '',
`editedDate` datetime NULL,
- `deleted` tinyint NOT NULL DEFAULT '0',
+ `deleted` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_dept`;
@@ -778,7 +778,7 @@ CREATE TABLE IF NOT EXISTS `zt_entry` (
`desc` mediumtext NULL,
`createdBy` varchar(30) NOT NULL DEFAULT '',
`createdDate` datetime NULL,
- `calledTime` int(10) unsigned NOT NULL DEFAULT '0',
+ `calledTime` int(11) unsigned NOT NULL DEFAULT '0',
`editedBy` varchar(30) NOT NULL DEFAULT '',
`editedDate` datetime NULL,
`deleted` enum('0', '1') NOT NULL DEFAULT '0',
@@ -824,7 +824,7 @@ CREATE TABLE IF NOT EXISTS `zt_file` (
`pathname` char(100) NOT NULL DEFAULT '',
`title` varchar(255) NOT NULL DEFAULT '',
`extension` char(30) NOT NULL DEFAULT '',
- `size` int(10) unsigned NOT NULL DEFAULT '0',
+ `size` int(11) unsigned NOT NULL DEFAULT '0',
`objectType` char(30) NOT NULL DEFAULT '',
`objectID` mediumint(9) NOT NULL DEFAULT '0',
`addedBy` char(30) NOT NULL DEFAULT '',
@@ -869,7 +869,7 @@ CREATE TABLE IF NOT EXISTS `zt_holiday` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_history`;
CREATE TABLE IF NOT EXISTS `zt_history` (
- `id` int(9) unsigned NOT NULL auto_increment,
+ `id` int(11) unsigned NOT NULL auto_increment,
`action` mediumint(8) unsigned NOT NULL default '0',
`field` varchar(30) NOT NULL default '',
`old` text NULL,
@@ -1119,7 +1119,7 @@ CREATE TABLE IF NOT EXISTS `zt_mr` (
`sourceBranch` varchar(100) NOT NULL DEFAULT '',
`targetProject` varchar(50) NOT NULL DEFAULT '',
`targetBranch` varchar(100) NOT NULL DEFAULT '',
- `mriid` int unsigned NOT NULL DEFAULT '0',
+ `mriid` int(11) unsigned NOT NULL DEFAULT '0',
`title` varchar(255) NOT NULL DEFAULT '',
`description` text NULL,
`assignee` varchar(255) NOT NULL DEFAULT '',
@@ -1159,10 +1159,10 @@ CREATE TABLE IF NOT EXISTS `zt_mrapproval` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_notify`;
CREATE TABLE IF NOT EXISTS `zt_notify` (
- `id` mediumint unsigned NOT NULL AUTO_INCREMENT,
+ `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`objectType` varchar(50) NOT NULL DEFAULT '',
- `objectID` mediumint unsigned NOT NULL DEFAULT '0',
- `action` mediumint NOT NULL DEFAULT '0',
+ `objectID` mediumint(8) unsigned NOT NULL DEFAULT '0',
+ `action` mediumint(9) NOT NULL DEFAULT '0',
`toList` varchar(255) NOT NULL DEFAULT '',
`ccList` text NULL,
`subject` varchar(255) NOT NULL DEFAULT '',
@@ -1484,7 +1484,7 @@ CREATE TABLE IF NOT EXISTS `zt_repo` (
`desc` text NULL,
`extra` char(30) NOT NULL DEFAULT '',
`preMerge` enum('0','1') COLLATE 'utf8_general_ci' NOT NULL DEFAULT '0',
- `job` mediumint unsigned NOT NULL DEFAULT '0',
+ `job` mediumint(8) unsigned NOT NULL DEFAULT '0',
`fileServerUrl` text COLLATE 'utf8_general_ci' NULL,
`fileServerAccount` varchar(40) NOT NULL default '',
`fileServerPassword` varchar(100) NOT NULL default '',
@@ -1502,7 +1502,7 @@ CREATE TABLE IF NOT EXISTS `zt_repobranch` (
CREATE UNIQUE INDEX `repo_revision_branch` ON `zt_repobranch`(`repo`,`revision`,`branch`);
-- DROP TABLE IF EXISTS `zt_repofiles`;
CREATE TABLE IF NOT EXISTS `zt_repofiles` (
- `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`repo` mediumint(8) unsigned NOT NULL DEFAULT '0',
`revision` mediumint(8) unsigned NOT NULL DEFAULT '0',
`path` varchar(255) NOT NULL DEFAULT '',
@@ -1553,7 +1553,7 @@ CREATE TABLE IF NOT EXISTS `zt_searchdict` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_searchindex`;
CREATE TABLE IF NOT EXISTS `zt_searchindex` (
- `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`vision` varchar(10) NOT NULL DEFAULT 'rnd',
`objectType` char(20) NOT NULL DEFAULT '',
`objectID` mediumint(9) NOT NULL DEFAULT '0',
@@ -1889,7 +1889,7 @@ CREATE TABLE IF NOT EXISTS `zt_testsuite` (
`name` varchar(255) NOT NULL DEFAULT '',
`desc` mediumtext NULL,
`type` varchar(20) NOT NULL DEFAULT '',
- `order` smallint unsigned NOT NULL DEFAULT '0',
+ `order` smallint(6) unsigned NOT NULL DEFAULT '0',
`addedBy` char(30) NOT NULL DEFAULT '',
`addedDate` datetime NULL,
`lastEditedBy` char(30) NOT NULL DEFAULT '',
@@ -1992,7 +1992,7 @@ CREATE TABLE IF NOT EXISTS `zt_user` (
`visits` mediumint(8) unsigned NOT NULL DEFAULT '0',
`visions` varchar(20) NOT NULL DEFAULT 'rnd,lite',
`ip` char(15) NOT NULL DEFAULT '',
- `last` int(10) unsigned NOT NULL DEFAULT '0',
+ `last` int(11) unsigned NOT NULL DEFAULT '0',
`fails` tinyint(5) NOT NULL DEFAULT '0',
`locked` datetime NULL,
`feedback` enum('0','1') NOT NULL DEFAULT '0',
@@ -2397,9 +2397,9 @@ INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type
-- DROP TABLE IF EXISTS `zt_relationoftasks`;
CREATE TABLE IF NOT EXISTS `zt_relationoftasks` (
- `id` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT ,
- `execution` MEDIUMINT(8) UNSIGNED NOT NULL ,
- `pretask` MEDIUMINT(8) UNSIGNED NOT NULL ,
+ `id` mediumint(8) UNSIGNED NOT NULL AUTO_INCREMENT ,
+ `execution` mediumint(8) UNSIGNED NOT NULL ,
+ `pretask` mediumint(8) UNSIGNED NOT NULL ,
`condition` ENUM( 'begin', 'end' ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`task` MEDIUMINT( 8 ) UNSIGNED NOT NULL ,
`action` ENUM( 'begin', 'end' ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
@@ -2470,7 +2470,7 @@ CREATE TABLE IF NOT EXISTS `zt_feedback` (
`type` char(30) NOT NULL DEFAULT '',
`solution` char(30) NOT NULL DEFAULT '',
`desc` text NULL,
- `pri` tinyint unsigned NOT NULL DEFAULT 2,
+ `pri` tinyint(3) unsigned NOT NULL DEFAULT 2,
`status` varchar(30) NOT NULL DEFAULT '',
`subStatus` varchar(30) NOT NULL default '',
`public` enum('0','1') NOT NULL DEFAULT '0',
@@ -2518,13 +2518,13 @@ CREATE TABLE IF NOT EXISTS `zt_ticket` (
`startedBy` varchar(255) NOT NULL DEFAULT '',
`startedDate` datetime NULL,
`deadline` date NULL,
- `pri` tinyint unsigned NOT NULL DEFAULT '0',
+ `pri` tinyint(3) unsigned NOT NULL DEFAULT '0',
`estimate` float unsigned NOT NULL,
`left` float unsigned NOT NULL,
`status` varchar(30) NOT NULL DEFAULT '',
`openedBy` varchar(30) NOT NULL DEFAULT '',
`openedDate` datetime NULL,
- `activatedCount` int(10) NOT NULL DEFAULT '0',
+ `activatedCount` int(11) NOT NULL DEFAULT '0',
`activatedBy` varchar(30) NOT NULL DEFAULT '',
`activatedDate` datetime NULL,
`closedBy` varchar(30) NOT NULL DEFAULT '',
@@ -2559,9 +2559,9 @@ CREATE TABLE IF NOT EXISTS `zt_ticketsource` (
-- DROP TABLE IF EXISTS `zt_ticketrelation`;
CREATE TABLE IF NOT EXISTS `zt_ticketrelation` (
- `id` mediumint unsigned NOT NULL AUTO_INCREMENT,
- `ticketId` mediumint unsigned NOT NULL DEFAULT '0',
- `objectId` mediumint NOT NULL DEFAULT '0',
+ `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
+ `ticketId` mediumint(8) unsigned NOT NULL DEFAULT '0',
+ `objectId` mediumint(9) NOT NULL DEFAULT '0',
`objectType` varchar(100) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `ticketId` (`ticketId`)
@@ -12632,7 +12632,7 @@ CREATE TABLE IF NOT EXISTS `zt_auditcl` (
`type` char(30) NOT NULL DEFAULT '',
`title` varchar(255) NOT NULL DEFAULT '',
`objectType` char(30) NOT NULL DEFAULT '',
- `objectID` int(10) NOT NULL DEFAULT '0',
+ `objectID` int(11) NOT NULL DEFAULT '0',
`assignedTo` varchar(30) NOT NULL DEFAULT '',
`status` varchar(30) NOT NULL DEFAULT '',
`createdBy` varchar(30) NOT NULL DEFAULT '',
@@ -12919,7 +12919,7 @@ CREATE TABLE IF NOT EXISTS `zt_meeting` (
`host` varchar(30) NOT NULL DEFAULT '',
`participant` text NULL,
`date` date NULL,
- `room` int NOT NULL DEFAULT '0',
+ `room` int(11) NOT NULL DEFAULT '0',
`minutes` text NULL,
`minutedBy` varchar(30) NOT NULL DEFAULT '',
`minutedDate` datetime NULL,
@@ -12938,7 +12938,7 @@ CREATE TABLE IF NOT EXISTS `zt_meetingroom` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '',
`position` varchar(30) NOT NULL DEFAULT '',
- `seats` int NOT NULL DEFAULT '0',
+ `seats` int(11) NOT NULL DEFAULT '0',
`equipment` varchar(255) NOT NULL DEFAULT '',
`openTime` varchar(255) NOT NULL DEFAULT '',
`createdBy` varchar(30) NOT NULL DEFAULT '',
@@ -12955,7 +12955,7 @@ CREATE TABLE IF NOT EXISTS `zt_assetlib` (
`name` varchar(255) NOT NULL DEFAULT '',
`type` varchar(255) NOT NULL DEFAULT '',
`desc` mediumtext NULL,
- `order` SMALLINT UNSIGNED NOT NULL DEFAULT '0',
+ `order` smallint(6) UNSIGNED NOT NULL DEFAULT '0',
`createdBy` varchar(30) NOT NULL DEFAULT '',
`createdDate` datetime NULL,
`editedBy` varchar(30) NOT NULL DEFAULT '',
@@ -14222,7 +14222,7 @@ CREATE TABLE IF NOT EXISTS `zt_pivot` (
`objects` mediumtext NULL,
`settings` mediumtext NULL,
`filters` mediumtext NULL,
- `step` tinyint(1) unsigned NOT NULL DEFAULT '0',
+ `step` tinyint(3) unsigned NOT NULL DEFAULT '0',
`stage` enum('draft','published') NOT NULL DEFAULT 'draft',
`builtin` enum('0', '1') NOT NULL DEFAULT '0',
`createdBy` varchar(30) NOT NULL DEFAULT '',
diff --git a/lib/form/form.class.php b/lib/form/form.class.php
index a59953175b..b1c8f96ee3 100644
--- a/lib/form/form.class.php
+++ b/lib/form/form.class.php
@@ -15,14 +15,32 @@ helper::import(dirname(dirname(__FILE__)) . '/base/filter/filter.class.php');
class form extends baseFixer
{
/**
- * @var object 原始 $_POST 数据。The raw $_POST data.
+ * 原始 $_POST 数据。
+ * The raw $_POST data.
+ *
+ * @var object
*/
public $rawdata;
+ /**
+ * 错误信息列表。
+ * Error list.
+ *
+ * @var object
+ */
+ public $errors;
+
+ /**
+ * 构造方法。
+ * The construct function.
+ *
+ * @return void
+ */
public function __construct()
{
$this->rawdata = (object)$_POST;
$this->data = (object)array();
+ $this->errors = array();
}
/**
@@ -51,6 +69,11 @@ class form extends baseFixer
$this->rawconfig = $config;
foreach($this->rawconfig as $key => $value) $this->convertField($key, $value);
+ if(!empty($this->errors))
+ {
+ $response = array('result' => 'fail', 'message' => $this->errors);
+ helper::end(json_encode($response));
+ }
return $this;
}
@@ -77,19 +100,22 @@ class form extends baseFixer
*/
public function convertField(string $field, array $config)
{
- if(isset($config['required']) && $config['required'] && !isset($this->rawdata->$field))
- {
- throw new InvalidArgumentException("Field $field is required");
- }
-
- if(isset($config['required']) && !$config['required'] && !isset($config['default']))
- {
- throw new InvalidArgumentException("Field $field is not required, but need default value");
- }
+ global $app;
if(!isset($config['type']))
{
- throw new InvalidArgumentException("Field $field need defined type");
+ if(!isset($this->errors[$field])) $this->errors[$field] = array();
+ $this->errors[$field][] = "Field '$field' need defined type";
+ }
+
+ if(isset($config['required']) && $config['required'])
+ {
+ if(!isset($config['default']) && (!isset($this->rawdata->$field) || $this->rawdata->$field === ''))
+ {
+ if(!isset($this->errors[$field])) $this->errors[$field] = array();
+ $fieldName = isset($app->lang->{$app->rawModule}->$field) ? $app->lang->{$app->rawModule}->$field : $field;
+ $this->errors[$field][] = sprintf($lang->error->notempty, $fieldName);
+ }
}
if(isset($this->rawdata->$field))
diff --git a/module/block/config.php b/module/block/config.php
index e9279b4376..807630839c 100644
--- a/module/block/config.php
+++ b/module/block/config.php
@@ -47,7 +47,7 @@ $config->block->params['default']->count['name'] = $lang->block->count;
$config->block->params['default']->count['default'] = 20;
$config->block->params['default']->count['control'] = 'input';
-$config->block->params['task'] = clone $config->block->params['default'];
+$config->block->params['task'] = new stdclass();
$config->block->params['task']->type['name'] = $lang->block->type;
$config->block->params['task']->type['options'] = $lang->block->typeList->task;
$config->block->params['task']->type['control'] = 'select';
@@ -55,8 +55,9 @@ $config->block->params['task']->orderBy['name'] = $lang->block->orderBy;
$config->block->params['task']->orderBy['default'] = 'id_desc';
$config->block->params['task']->orderBy['options'] = $lang->block->orderByList->task;
$config->block->params['task']->orderBy['control'] = 'select';
+$config->block->params['task']->count = $config->block->params['default']->count;
-$config->block->params['bug'] = clone $config->block->params['default'];
+$config->block->params['bug'] = new stdclass();
$config->block->params['bug']->type['name'] = $lang->block->type;
$config->block->params['bug']->type['options'] = $lang->block->typeList->bug;
$config->block->params['bug']->type['control'] = 'select';
@@ -64,8 +65,9 @@ $config->block->params['bug']->orderBy['name'] = $lang->block->orderBy;
$config->block->params['bug']->orderBy['default'] = 'id_desc';
$config->block->params['bug']->orderBy['options'] = $lang->block->orderByList->bug;
$config->block->params['bug']->orderBy['control'] = 'select';
+$config->block->params['bug']->count = $config->block->params['default']->count;
-$config->block->params['case'] = clone $config->block->params['default'];
+$config->block->params['case'] = new stdclass();
$config->block->params['case']->type['name'] = $lang->block->type;
$config->block->params['case']->type['options'] = $lang->block->typeList->case;
$config->block->params['case']->type['control'] = 'select';
@@ -73,13 +75,15 @@ $config->block->params['case']->orderBy['name'] = $lang->block->orderBy;
$config->block->params['case']->orderBy['default'] = 'id_desc';
$config->block->params['case']->orderBy['options'] = $lang->block->orderByList->case;
$config->block->params['case']->orderBy['control'] = 'select';
+$config->block->params['case']->count = $config->block->params['default']->count;
-$config->block->params['testtask'] = clone $config->block->params['default'];
-$config->block->params['testtask']->type['name'] = $lang->block->type;
-$config->block->params['testtask']->type['options'] = $lang->block->typeList->testtask;
-$config->block->params['testtask']->type['control'] = 'select';
+$config->block->params['testtask'] = new stdclass();
+$config->block->params['testtask']->type['name'] = $lang->block->type;
+$config->block->params['testtask']->type['options'] = $lang->block->typeList->testtask;
+$config->block->params['testtask']->type['control'] = 'select';
+$config->block->params['testtask']->count = $config->block->params['default']->count;
-$config->block->params['story'] = clone $config->block->params['default'];
+$config->block->params['story'] = new stdclass();;
$config->block->params['story']->type['name'] = $lang->block->type;
$config->block->params['story']->type['options'] = $lang->block->typeList->story;
$config->block->params['story']->type['control'] = 'select';
@@ -87,153 +91,169 @@ $config->block->params['story']->orderBy['name'] = $lang->block->orderBy;
$config->block->params['story']->orderBy['default'] = 'id_desc';
$config->block->params['story']->orderBy['options'] = $lang->block->orderByList->story;
$config->block->params['story']->orderBy['control'] = 'select';
+$config->block->params['story']->count = $config->block->params['default']->count;
-$config->block->params['plan'] = clone $config->block->params['default'];
+$config->block->params['plan'] = $config->block->params['default'];
-$config->block->params['release'] = clone $config->block->params['default'];
+$config->block->params['release'] = $config->block->params['default'];
-$config->block->params['project'] = clone $config->block->params['default'];
+$config->block->params['project'] = new stdclass();
$config->block->params['project']->type['name'] = $lang->block->type;
$config->block->params['project']->type['options'] = $lang->block->typeList->projectAll;
$config->block->params['project']->type['control'] = 'select';
$config->block->params['project']->orderBy['name'] = $lang->block->orderBy;
$config->block->params['project']->orderBy['options'] = $lang->block->orderByList->product;
$config->block->params['project']->orderBy['control'] = 'select';
+$config->block->params['project']->count = $config->block->params['default']->count;
-$config->block->params['projectteam'] = clone $config->block->params['default'];
+$config->block->params['projectteam'] = new stdclass();
$config->block->params['projectteam']->type['name'] = $lang->block->type;
$config->block->params['projectteam']->type['options'] = $lang->block->typeList->projectAll;
$config->block->params['projectteam']->type['control'] = 'select';
$config->block->params['projectteam']->orderBy['name'] = $lang->block->orderBy;
$config->block->params['projectteam']->orderBy['options'] = $lang->block->orderByList->project;
$config->block->params['projectteam']->orderBy['control'] = 'select';
+$config->block->params['projectteam']->count = $config->block->params['default']->count;
-$config->block->params['build'] = clone $config->block->params['default'];
+$config->block->params['build'] = $config->block->params['default'];
-$config->block->params['product'] = clone $config->block->params['default'];
+$config->block->params['product'] = new stdclass();
$config->block->params['product']->type['name'] = $lang->block->type;
$config->block->params['product']->type['options'] = $lang->block->typeList->product;
$config->block->params['product']->type['control'] = 'select';
+$config->block->params['product']->count = $config->block->params['default']->count;
-$config->block->params['productstatistic'] = clone $config->block->params['default'];
+$config->block->params['productstatistic'] = new stdclass();
$config->block->params['productstatistic']->type['name'] = $lang->block->type;
$config->block->params['productstatistic']->type['options'] = $lang->block->typeList->product;
$config->block->params['productstatistic']->type['control'] = 'select';
+$config->block->params['productstatistic']->count = $config->block->params['default']->count;
-$config->block->params['projectstatistic'] = clone $config->block->params['default'];
+$config->block->params['projectstatistic'] = new stdclass();
$config->block->params['projectstatistic']->type['name'] = $lang->block->type;
$config->block->params['projectstatistic']->type['options'] = $lang->block->typeList->project;
$config->block->params['projectstatistic']->type['control'] = 'select';
+$config->block->params['projectstatistic']->count = $config->block->params['default']->count;
-$config->block->params['executionstatistic'] = clone $config->block->params['default'];
+$config->block->params['executionstatistic'] = new stdclass();
$config->block->params['executionstatistic']->type['name'] = $lang->block->type;
$config->block->params['executionstatistic']->type['options'] = $lang->block->typeList->execution;
$config->block->params['executionstatistic']->type['control'] = 'select';
+$config->block->params['executionstatistic']->count = $config->block->params['default']->count;
-$config->block->params['qaStatistic'] = clone $config->block->params['default'];
-$config->block->params['qaStatistic']->type['name'] = $lang->block->type;
-$config->block->params['qaStatistic']->type['options'] = $lang->block->typeList->product;
-$config->block->params['qaStatistic']->type['control'] = 'select';
+$config->block->params['qastatistic'] = new stdclass();
+$config->block->params['qastatistic']->type['name'] = $lang->block->type;
+$config->block->params['qastatistic']->type['options'] = $lang->block->typeList->product;
+$config->block->params['qastatistic']->type['control'] = 'select';
+$config->block->params['qastatistic']->count = $config->block->params['default']->count;
-$config->block->params['waterfallissue'] = clone $config->block->params['default'];
+$config->block->params['waterfallissue'] = new stdclass();
$config->block->params['waterfallissue']->type['name'] = $lang->block->type;
$config->block->params['waterfallissue']->type['options'] = $lang->block->typeList->issue;
$config->block->params['waterfallissue']->type['control'] = 'select';
$config->block->params['waterfallissue']->orderBy['name'] = $lang->block->orderBy;
$config->block->params['waterfallissue']->orderBy['options'] = $lang->block->orderByList->product;
$config->block->params['waterfallissue']->orderBy['control'] = 'select';
+$config->block->params['waterfallissue']->count = $config->block->params['default']->count;
-$config->block->params['waterfallRisk'] = clone $config->block->params['default'];
-$config->block->params['waterfallRisk']->type['name'] = $lang->block->type;
-$config->block->params['waterfallRisk']->type['options'] = $lang->block->typeList->risk;
-$config->block->params['waterfallRisk']->type['control'] = 'select';
-$config->block->params['waterfallRisk']->orderBy['name'] = $lang->block->orderBy;
-$config->block->params['waterfallRisk']->orderBy['options'] = $lang->block->orderByList->product;
-$config->block->params['waterfallRisk']->orderBy['control'] = 'select';
+$config->block->params['waterfallrisk'] = new stdclass();
+$config->block->params['waterfallrisk']->type['name'] = $lang->block->type;
+$config->block->params['waterfallrisk']->type['options'] = $lang->block->typeList->risk;
+$config->block->params['waterfallrisk']->type['control'] = 'select';
+$config->block->params['waterfallrisk']->orderBy['name'] = $lang->block->orderBy;
+$config->block->params['waterfallrisk']->orderBy['options'] = $lang->block->orderByList->product;
+$config->block->params['waterfallrisk']->orderBy['control'] = 'select';
+$config->block->params['waterfallrisk']->count = $config->block->params['default']->count;
-$config->block->params['scrumIssue'] = clone $config->block->params['default'];
-$config->block->params['scrumIssue']->type['name'] = $lang->block->type;
-$config->block->params['scrumIssue']->type['options'] = $lang->block->typeList->issue;
-$config->block->params['scrumIssue']->type['control'] = 'select';
-$config->block->params['scrumIssue']->orderBy['name'] = $lang->block->orderBy;
-$config->block->params['scrumIssue']->orderBy['options'] = $lang->block->orderByList->product;
-$config->block->params['scrumIssue']->orderBy['control'] = 'select';
+$config->block->params['scrumissue'] = new stdclass();
+$config->block->params['scrumissue']->type['name'] = $lang->block->type;
+$config->block->params['scrumissue']->type['options'] = $lang->block->typeList->issue;
+$config->block->params['scrumissue']->type['control'] = 'select';
+$config->block->params['scrumissue']->orderBy['name'] = $lang->block->orderBy;
+$config->block->params['scrumissue']->orderBy['options'] = $lang->block->orderByList->product;
+$config->block->params['scrumissue']->orderBy['control'] = 'select';
+$config->block->params['scrumissue']->count = $config->block->params['default']->count;
-$config->block->params['scrumRisk'] = clone $config->block->params['default'];
-$config->block->params['scrumRisk']->type['name'] = $lang->block->type;
-$config->block->params['scrumRisk']->type['options'] = $lang->block->typeList->risk;
-$config->block->params['scrumRisk']->type['control'] = 'select';
-$config->block->params['scrumRisk']->orderBy['name'] = $lang->block->orderBy;
-$config->block->params['scrumRisk']->orderBy['options'] = $lang->block->orderByList->product;
-$config->block->params['scrumRisk']->orderBy['control'] = 'select';
+$config->block->params['scrumrisk'] = new stdclass();
+$config->block->params['scrumrisk']->type['name'] = $lang->block->type;
+$config->block->params['scrumrisk']->type['options'] = $lang->block->typeList->risk;
+$config->block->params['scrumrisk']->type['control'] = 'select';
+$config->block->params['scrumrisk']->orderBy['name'] = $lang->block->orderBy;
+$config->block->params['scrumrisk']->orderBy['options'] = $lang->block->orderByList->product;
+$config->block->params['scrumrisk']->orderBy['control'] = 'select';
+$config->block->params['scrumrisk']->count = $config->block->params['default']->count;
-$config->block->params['execution'] = clone $config->block->params['default'];
-$config->block->params['execution']->type['name'] = $lang->block->type;
-$config->block->params['execution']->type['options'] = $lang->block->typeList->execution;
-$config->block->params['execution']->type['control'] = 'select';
+$config->block->params['execution'] = new stdclass();
+$config->block->params['execution']->type['name'] = $lang->block->type;
+$config->block->params['execution']->type['options'] = $lang->block->typeList->execution;
+$config->block->params['execution']->type['control'] = 'select';
+$config->block->params['execution']->count = $config->block->params['default']->count;
-$config->block->params['assignToMe'] = new stdclass();
-$config->block->params['assignToMe']->todoCount['name'] = $this->lang->block->todoCount;
-$config->block->params['assignToMe']->todoCount['default'] = 20;
-$config->block->params['assignToMe']->todoCount['control'] = 'input';
-$config->block->params['assignToMe']->taskCount['name'] = $this->lang->block->taskCount;
-$config->block->params['assignToMe']->taskCount['default'] = 20;
-$config->block->params['assignToMe']->taskCount['control'] = 'input';
-$config->block->params['assignToMe']->bugCount['name'] = $this->lang->block->bugCount;
-$config->block->params['assignToMe']->bugCount['default'] = 20;
-$config->block->params['assignToMe']->bugCount['control'] = 'input';
+$config->block->params['assigntome'] = new stdclass();
+$config->block->params['assigntome']->todoCount['name'] = $this->lang->block->todoCount;
+$config->block->params['assigntome']->todoCount['default'] = 20;
+$config->block->params['assigntome']->todoCount['control'] = 'input';
+$config->block->params['assigntome']->taskCount['name'] = $this->lang->block->taskCount;
+$config->block->params['assigntome']->taskCount['default'] = 20;
+$config->block->params['assigntome']->taskCount['control'] = 'input';
+$config->block->params['assigntome']->bugCount['name'] = $this->lang->block->bugCount;
+$config->block->params['assigntome']->bugCount['default'] = 20;
+$config->block->params['assigntome']->bugCount['control'] = 'input';
if($config->edition == 'max')
{
if(helper::hasFeature('risk'))
{
- $config->block->params['assignToMe']->riskCount['name'] = $this->lang->block->riskCount;
- $config->block->params['assignToMe']->riskCount['default'] = 20;
- $config->block->params['assignToMe']->riskCount['control'] = 'input';
+ $config->block->params['assigntome']->riskCount['name'] = $this->lang->block->riskCount;
+ $config->block->params['assigntome']->riskCount['default'] = 20;
+ $config->block->params['assigntome']->riskCount['control'] = 'input';
}
if(helper::hasFeature('issue'))
{
- $config->block->params['assignToMe']->issueCount['name'] = $this->lang->block->issueCount;
- $config->block->params['assignToMe']->issueCount['default'] = 20;
- $config->block->params['assignToMe']->issueCount['control'] = 'input';
+ $config->block->params['assigntome']->issueCount['name'] = $this->lang->block->issueCount;
+ $config->block->params['assigntome']->issueCount['default'] = 20;
+ $config->block->params['assigntome']->issueCount['control'] = 'input';
}
if(helper::hasFeature('meeting'))
{
- $config->block->params['assignToMe']->meetingCount['name'] = $this->lang->block->meetingCount;
- $config->block->params['assignToMe']->meetingCount['default'] = 20;
- $config->block->params['assignToMe']->meetingCount['control'] = 'input';
+ $config->block->params['assigntome']->meetingCount['name'] = $this->lang->block->meetingCount;
+ $config->block->params['assigntome']->meetingCount['default'] = 20;
+ $config->block->params['assigntome']->meetingCount['control'] = 'input';
}
- $config->block->params['assignToMe']->feedbackCount['name'] = $this->lang->block->feedbackCount;
- $config->block->params['assignToMe']->feedbackCount['default'] = 20;
- $config->block->params['assignToMe']->feedbackCount['control'] = 'input';
+ $config->block->params['assigntome']->feedbackCount['name'] = $this->lang->block->feedbackCount;
+ $config->block->params['assigntome']->feedbackCount['default'] = 20;
+ $config->block->params['assigntome']->feedbackCount['control'] = 'input';
}
-$config->block->params['assignToMe']->storyCount['name'] = $this->lang->block->storyCount;
-$config->block->params['assignToMe']->storyCount['default'] = 20;
-$config->block->params['assignToMe']->storyCount['control'] = 'input';
-$config->block->params['assignToMe']->reviewCount['name'] = $this->lang->block->reviewCount;
-$config->block->params['assignToMe']->reviewCount['default'] = 20;
-$config->block->params['assignToMe']->reviewCount['control'] = 'input';
+$config->block->params['assigntome']->storyCount['name'] = $this->lang->block->storyCount;
+$config->block->params['assigntome']->storyCount['default'] = 20;
+$config->block->params['assigntome']->storyCount['control'] = 'input';
+$config->block->params['assigntome']->reviewCount['name'] = $this->lang->block->reviewCount;
+$config->block->params['assigntome']->reviewCount['default'] = 20;
+$config->block->params['assigntome']->reviewCount['control'] = 'input';
+$config->block->params['assigntome']->count = $config->block->params['default']->count;
-$config->block->params['scrumTest'] = clone $config->block->params['default'];
-$config->block->params['scrumTest']->type['name'] = $lang->block->type;
-$config->block->params['scrumTest']->type['options'] = $lang->block->typeList->testtask;
-$config->block->params['scrumTest']->type['control'] = 'select';
+$config->block->params['scrumtest'] = new stdclass();
+$config->block->params['scrumtest']->type['name'] = $lang->block->type;
+$config->block->params['scrumtest']->type['options'] = $lang->block->typeList->testtask;
+$config->block->params['scrumtest']->type['control'] = 'select';
+$config->block->params['scrumtest']->count = $config->block->params['default']->count;
-$config->block->params['scrumList'] = clone $config->block->params['default'];
-$config->block->params['scrumList']->type['name'] = $lang->block->type;
-$config->block->params['scrumList']->type['options'] = $lang->block->typeList->scrum;
-$config->block->params['scrumList']->type['control'] = 'select';
+$config->block->params['scrumlist'] = new stdclass();
+$config->block->params['scrumlist']->type['name'] = $lang->block->type;
+$config->block->params['scrumlist']->type['options'] = $lang->block->typeList->scrum;
+$config->block->params['scrumlist']->type['control'] = 'select';
+$config->block->params['scrumlist']->count = $config->block->params['default']->count;
-$config->block->params['scrumProduct'] = clone $config->block->params['default'];
+$config->block->params['scrumProduct'] = $config->block->params['default']->count;
-$config->block->params['projectDynamic'] = clone $config->block->params['default'];
+$config->block->params['projectDynamic'] = $config->block->params['default']->count;
-$config->block->params['productDoc'] = clone $config->block->params['default'];
+$config->block->params['productDoc'] = $config->block->params['default']->count;
-$config->block->params['projectDoc'] = clone $config->block->params['default'];
+$config->block->params['projectDoc'] = $config->block->params['default']->count;
$config->block->modules['project'] = new stdclass();
$config->block->modules['project']->moreLinkList = new stdclass();
@@ -279,19 +299,3 @@ $config->block->modules['doc']->moreLinkList = new stdclass();
$config->block->modules['doc']->moreLinkList->docmycollection = 'doc|myspace|type=collect&libID=0&moduleID=0&browseType=all¶m=0&orderBy=editedDate_desc';
$config->block->modules['doc']->moreLinkList->productdoc = 'doc|productspace|';
$config->block->modules['doc']->moreLinkList->projectdoc = 'doc|projectspace|';
-
-$config->block->form = new stdclass();
-$config->block->form->create = array();
-$config->block->form->create['module'] = array('type' => 'string', 'required' => false, 'default' => '');
-$config->block->form->create['code'] = array('type' => 'string', 'required' => false, 'default' => '');
-$config->block->form->create['title'] = array('type' => 'string', 'required' => false, 'default' => '');
-$config->block->form->create['grid'] = array('type' => 'int', 'required' => false, 'default' => '4');
-$config->block->form->create['hidden'] = array('type' => 'int', 'required' => false, 'default' => '0');
-$config->block->form->create['params'] = array('type' => 'array', 'required' => false, 'default' => array());
-
-$config->block->form->edit = array();
-$config->block->form->edit['module'] = array('type' => 'string', 'required' => false, 'default' => '');
-$config->block->form->edit['code'] = array('type' => 'string', 'required' => false, 'default' => '');
-$config->block->form->edit['title'] = array('type' => 'string', 'required' => false, 'default' => '');
-$config->block->form->edit['grid'] = array('type' => 'int', 'required' => false, 'default' => '4');
-$config->block->form->edit['params'] = array('type' => 'array', 'required' => false, 'default' => array());
diff --git a/module/block/config/form.php b/module/block/config/form.php
new file mode 100644
index 0000000000..23308d04bf
--- /dev/null
+++ b/module/block/config/form.php
@@ -0,0 +1,22 @@
+block->create = new stdclass();
+$config->block->create->requiredFields = 'module,code,title';
+
+$config->block->edit = new stdclass();
+$config->block->edit->requiredFields = 'module,code,title';
+
+$config->block->form = new stdclass();
+$config->block->form->create = array();
+$config->block->form->create['module'] = array('type' => 'string', 'required' => false, 'default' => '');
+$config->block->form->create['code'] = array('type' => 'string', 'required' => false, 'default' => '');
+$config->block->form->create['title'] = array('type' => 'string', 'required' => false, 'default' => '');
+$config->block->form->create['grid'] = array('type' => 'int', 'required' => false, 'default' => '4');
+$config->block->form->create['hidden'] = array('type' => 'int', 'required' => false, 'default' => '0');
+$config->block->form->create['params'] = array('type' => 'array', 'required' => false, 'default' => array());
+
+$config->block->form->edit = array();
+$config->block->form->edit['module'] = array('type' => 'string', 'required' => false, 'default' => '');
+$config->block->form->edit['code'] = array('type' => 'string', 'required' => false, 'default' => '');
+$config->block->form->edit['title'] = array('type' => 'string', 'required' => false, 'default' => '');
+$config->block->form->edit['grid'] = array('type' => 'int', 'required' => false, 'default' => '4');
+$config->block->form->edit['params'] = array('type' => 'array', 'required' => false, 'default' => array());
diff --git a/module/block/control.php b/module/block/control.php
index c1f1946be2..63208c93b1 100755
--- a/module/block/control.php
+++ b/module/block/control.php
@@ -27,10 +27,10 @@ class block extends control
/**
* Create a block under a dashboard.
- *
- * @param string $dashboard
+ *
+ * @param string $dashboard
* @param string $module
- * @param string $code
+ * @param string $code
* @access public
* @return void
*/
@@ -47,7 +47,7 @@ class block extends control
$this->block->create($formData);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true, 'closeModal' => true, 'callback' => 'loadCurrentPage()'));
+ return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true, 'closeModal' => true));
}
$this->view->title = $this->lang->block->createBlock;
@@ -61,11 +61,11 @@ class block extends control
}
/**
- * Update a block.
- *
- * @param string $dashboard
- * @param string $module
- * @param string $code
+ * Update a block.
+ *
+ * @param string $dashboard
+ * @param string $module
+ * @param string $code
* @access public
* @return void
*/
@@ -80,7 +80,7 @@ class block extends control
$this->block->update($formData);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true, 'closeModal' => true, 'callback' => 'loadCurrentPage()'));
+ return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true, 'closeModal' => true));
}
$block = $this->block->getByID($blockID);
@@ -97,81 +97,39 @@ class block extends control
$this->display();
}
- public function set($id, $type, $module = '')
- {
- $block = $this->block->getByID($id);
- if($block and empty($type)) $type = $block->code;
- if(isset($block->params->num) and !isset($block->params->count))
- {
- $block->params->count = $block->params->num;
- unset($block->params->num);
- }
-
- if(isset($this->lang->block->moduleList[$module]))
- {
- $params = $this->block->getParams($type, $module);
- $this->view->params = json_decode($params, true);
- }
- elseif($type == 'assigntome')
- {
- $params = $this->block->getParams('assignedToMe');
- $this->view->params = json_decode($params, true);
- }
-
- $this->view->source = $module;
- $this->view->type = $type;
- $this->view->id = $id;
- $this->view->block = ($block) ? $block : array();
- $this->display();
- }
-
/**
- * Delete block
+ * Delete or hidd block by blockid.
*
* @param int $id
- * @param string $sys
* @param string $type
* @access public
* @return void
*/
- public function delete($id, $module = 'my', $type = 'delete')
+ public function delete($blockID, $type = 'delete')
{
- if($type == 'hidden')
- {
- $this->dao->update(TABLE_BLOCK)->set('hidden')->eq(1)->where('`id`')->eq($id)->andWhere('account')->eq($this->app->user->account)->andWhere('module')->eq($module)->exec();
- }
- else
- {
- $this->dao->delete()->from(TABLE_BLOCK)->where('`id`')->eq($id)->andWhere('account')->eq($this->app->user->account)->andWhere('module')->eq($module)->exec();
- }
+ $blockID = (int)$blockID;
+ if($type == 'delete') $this->block->deleteBlock($blockID);
+ if($type == 'hidden') $this->block->hidden($blockID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
+
$this->loadModel('score')->create('block', 'set');
return $this->send(array('result' => 'success'));
}
/**
- * Sort block.
+ * Sort dashboard blocks.
*
- * @param string $oldOrder
- * @param string $newOrder
- * @param string $module
+ * @param string $orders
* @access public
* @return void
*/
- public function sort($orders, $module = 'my')
+ public function sort($orders)
{
- $orders = explode(',', $orders);
- $blockList = $this->block->getMyDashboard($module);
-
- foreach ($orders as $order => $blockID)
- {
- $block = $blockList[$blockID];
- if(!isset($block)) continue;
- $block->order = $order;
- $this->dao->replace(TABLE_BLOCK)->data($block)->exec();
- }
+ $orders = explode(',', $orders);
+ foreach($orders as $order => $blockID) $this->block->setOrder($blockID, $order);
if(dao::isError()) return $this->send(array('result' => 'fail'));
+
$this->loadModel('score')->create('block', 'set');
return $this->send(array('result' => 'success'));
}
@@ -182,26 +140,22 @@ class block extends control
* @access public
* @return void
*/
- public function resize($id, $type, $data)
+ public function resize($blockID, $type, $data)
{
- $block = $this->block->getByID($id);
- if($block)
- {
- $field = '';
- if($type == 'vertical') $field = 'height';
- if($type == 'horizontal') $field = 'grid';
- if(empty($field)) return $this->send(array('result' => 'fail', 'code' => 400));
+ $block = $this->block->getByID($blockID);
+ if(!$block) return $this->send(array('result' => 'fail', 'code' => 404));
- $block->$field = $data;
- $block->params = helper::jsonEncode($block->params);
- $this->dao->replace(TABLE_BLOCK)->data($block)->exec();
- if(dao::isError()) return $this->send(array('result' => 'fail', 'code' => 500));
- return $this->send(array('result' => 'success'));
- }
- else
- {
- return $this->send(array('result' => 'fail', 'code' => 404));
- }
+ $field = '';
+ if($type == 'vertical') $field = 'height';
+ if($type == 'horizontal') $field = 'grid';
+ if(empty($field)) return $this->send(array('result' => 'fail', 'code' => 400));
+
+ $block->$field = $data;
+ $block->params = helper::jsonEncode($block->params);
+ $this->block->update($block);
+
+ if(dao::isError()) return $this->send(array('result' => 'fail', 'code' => 500));
+ return $this->send(array('result' => 'success'));
}
/**
@@ -1862,7 +1816,7 @@ class block extends control
/* load pager. */
$this->app->loadClass('pager', $static = true);
$pager = new pager(0, 3, 1);
- $this->view->projects = $this->loadModel('project')->getInfoList('all', 'id_desc', $pager, 1);
+ $this->view->projects = $this->loadModel('project')->getList('all', 'id_desc', true, $pager);
}
/**
@@ -2155,30 +2109,18 @@ class block extends control
}
/**
- * Ajax reset.
+ * Reset dashboard blocks.
*
- * @param string $module
- * @param string $confirm
+ * @param string $dashboard
* @access public
* @return void
*/
- public function ajaxReset($module, $confirm = 'no')
+ public function reset($dashboard)
{
- if($confirm != 'yes') return print(js::confirm($this->lang->block->confirmReset, inlink('ajaxReset', "module=$module&confirm=yes")));
+ $this->block->reset($dashboard);
+ if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- $this->dao->delete()->from(TABLE_BLOCK)
- ->where('module')->eq($module)
- ->andWhere('vision')->eq($this->config->vision)
- ->andWhere('account')->eq($this->app->user->account)
- ->exec();
-
- $this->dao->delete()->from(TABLE_CONFIG)
- ->where('module')->eq($module)
- ->andWhere('vision')->eq($this->config->vision)
- ->andWhere('owner')->eq($this->app->user->account)
- ->andWhere('`key`')->eq('blockInited')
- ->exec();
- return print(js::reload('parent'));
+ return $this->send(array('result' => 'success'));
}
/**
diff --git a/module/block/css/welcome.ui.css b/module/block/css/welcome.ui.css
index 39ca83a150..8ba8d8a1f2 100644
--- a/module/block/css/welcome.ui.css
+++ b/module/block/css/welcome.ui.css
@@ -1,3 +1,7 @@
.welcome-block {background-image: linear-gradient( 90deg, #EDF7FE 0%, #FFF 20%);}
.border-right {position: relative;}
.border-right::after {content: ''; position: absolute; right: 0px; width: 1px; height: 40px; background: #EEE; top: 50%; margin-top: -20px;}
+.avatar-border-one {width: 4.2rem; height: 4.2rem; background: #f4f5f3; position: relative;}
+.avatar-border-two {width: 3.6rem; height: 3.6rem; background: #F5EBDE; position: absolute;}
+.welcome-avatar {border: 2px solid #FBC962; position: absolute;}
+.tile-amount {font-size: 32px; font-weight: 700; line-height: 56px; }
diff --git a/module/block/js/create.ui.js b/module/block/js/create.ui.js
index 89c5d6418e..7a157fefdf 100644
--- a/module/block/js/create.ui.js
+++ b/module/block/js/create.ui.js
@@ -4,5 +4,29 @@ function getForm(event)
const module = $('#module').val();
const code = field == 'module' ? '' : $('#code').val();
const url = $.createLink('block', 'create', 'dashboard='+ dashboard +'&module=' + module + '&code=' + (code ? code : ''));
- loadPage(url, '#codeRow, #paramsRow');
+ loadPage(url, '#codesRow, #paramsRow');
+}
+
+function onParamsTypeChange(event)
+{
+ const lang = config.clientLang;
+ const $code = document.querySelector('#code');
+
+ if($('#module').val() == 'scrumtest' && $('#paramstype').val() != 'all')
+ {
+ $('#title').val($code.options[$code.selectedIndex].text);
+ }
+ else
+ {
+ if(lang.indexOf('zh') >= 0)
+ {
+ const $paramstype = document.querySelector('#paramstype');
+ const blockTitle = $paramstype.options[$paramstype.selectedIndex].text + of + $code.options[$code.selectedIndex].text;
+ $('#title').val(blockTitle);
+ }
+ else
+ {
+ /* TODO */
+ }
+ }
}
diff --git a/module/block/lang/de.php b/module/block/lang/de.php
index 049d13ed37..fd034a1752 100644
--- a/module/block/lang/de.php
+++ b/module/block/lang/de.php
@@ -23,10 +23,9 @@ $lang->block->estimate = 'Estimate';
$lang->block->last = 'Last';
$lang->block->account = 'Konto';
-$lang->block->module = 'Modul';
$lang->block->title = 'Titel';
-$lang->block->source = 'Source module';
-$lang->block->block = 'Source block';
+$lang->block->module = 'Modul';
+$lang->block->code = 'InfoBlock';
$lang->block->order = 'Sortierung';
$lang->block->height = 'Höhe';
$lang->block->role = 'Rolle';
diff --git a/module/block/lang/en.php b/module/block/lang/en.php
index 4ffc769ec7..e3f3fb1982 100644
--- a/module/block/lang/en.php
+++ b/module/block/lang/en.php
@@ -23,10 +23,9 @@ $lang->block->estimate = 'Estimate';
$lang->block->last = 'Last';
$lang->block->account = 'Account';
-$lang->block->module = 'Module';
$lang->block->title = 'Title';
-$lang->block->source = 'Source Module';
-$lang->block->block = 'Source Block';
+$lang->block->module = 'Module';
+$lang->block->code = 'Block';
$lang->block->order = 'Order';
$lang->block->height = 'Height';
$lang->block->role = 'Role';
diff --git a/module/block/lang/fr.php b/module/block/lang/fr.php
index ba99bccd03..a877027442 100644
--- a/module/block/lang/fr.php
+++ b/module/block/lang/fr.php
@@ -23,10 +23,9 @@ $lang->block->estimate = 'Estimate';
$lang->block->last = 'Last';
$lang->block->account = 'Compte';
-$lang->block->module = 'Module';
$lang->block->title = 'Titre';
-$lang->block->source = 'Source Module';
-$lang->block->block = 'Source Bloc';
+$lang->block->module = 'Module';
+$lang->block->code = 'Bloc';
$lang->block->order = 'Ordre';
$lang->block->height = 'Hauteur';
$lang->block->role = 'Rôle';
diff --git a/module/block/lang/vi.php b/module/block/lang/vi.php
index bf8f790dd8..6ba1156736 100644
--- a/module/block/lang/vi.php
+++ b/module/block/lang/vi.php
@@ -21,10 +21,9 @@ $lang->block->estimate = 'Estimate';
$lang->block->last = 'Last';
$lang->block->account = 'Tài khoản';
-$lang->block->module = 'Module';
$lang->block->title = 'Tiêu đề';
-$lang->block->source = 'Nguồn Module';
-$lang->block->block = 'Nguồn Block';
+$lang->block->module = 'Module';
+$lang->block->code = 'Block';
$lang->block->order = 'Sắp xếp';
$lang->block->height = 'Chiều cao';
$lang->block->role = 'Vai trò';
diff --git a/module/block/lang/zh-cn.php b/module/block/lang/zh-cn.php
index 764f5c1ac0..6efc436e2a 100644
--- a/module/block/lang/zh-cn.php
+++ b/module/block/lang/zh-cn.php
@@ -23,10 +23,9 @@ $lang->block->estimate = '预计工时';
$lang->block->last = '近期';
$lang->block->account = '所属用户';
-$lang->block->module = '所属模块';
$lang->block->title = '区块名称';
-$lang->block->source = '来源模块';
-$lang->block->block = '来源区块';
+$lang->block->module = '所属模块';
+$lang->block->code = '区块';
$lang->block->order = '排序';
$lang->block->height = '高度';
$lang->block->role = '角色';
diff --git a/module/block/model.php b/module/block/model.php
index a293659c2b..2c20cb4e5f 100644
--- a/module/block/model.php
+++ b/module/block/model.php
@@ -120,51 +120,6 @@ class blockModel extends model
return $this->blockTao->fetchMyBlocks($dashboard, $hidden = 1);
}
- /**
- * Get block json that user can add.
- * 获取允许用户添加的区块列表.
- *
- * @param string $dashboard
- * @param string $module
- * @access public
- * @return string[]
- */
- public function getAvailableBlocks(string $dashboard, string $module = ''): array
- {
- if($dashboard == 'my')
- {
- if($module and isset($this->lang->block->modules[$module]))
- {
- $blocks = $this->lang->block->modules[$module]->availableBlocks;
- }
- else
- {
- $blocks = array();
- }
- }
- else
- {
- if($dashboard and isset($this->lang->block->modules[$dashboard]))
- {
- $blocks = $this->lang->block->modules[$dashboard]->availableBlocks;
- }
- else
- {
- $blocks = $this->lang->block->availableBlocks;
- }
- }
-
- if(isset($this->config->block->closed))
- {
- foreach($blocks as $blockKey => $blockName)
- {
- if(strpos(",{$this->config->block->closed},", ",{$module}|{$blockKey},") !== false) unset($blocks[$blockKey]);
- }
- }
-
- return $blocks;
- }
-
/**
* Get max order number by block dashboard.
* 获取对应仪表盘下区块的最大排序号.
@@ -175,31 +130,12 @@ class blockModel extends model
*/
public function getMaxOrderByDashboard(string $dashboard): int
{
- return $this->blockTao->fetchMaxOrderByDashboard($dashboard);
- }
+ $order = $this->dao->select('MAX(`order`) as `order`')->from(TABLE_BLOCK)
+ ->where('dashboard')->eq($dashboard)
+ ->andWhere('account')->eq($this->app->user->account)
+ ->fetch('order');
- /**
- * Get block set form params.
- * 获取不同区块所需的参数配置.
- *
- * @param string $type
- * @param string $module
- * @access public
- * @return string
- */
- public function getParams(string $code, string $module): string
- {
- if($code == 'todo' || $code == 'list')
- {
- $code = $module;
- }
- elseif($code == 'statistic')
- {
- $code = $module . $code;
- }
-
- $params = zget($this->config->block->params, $code, '');
- return json_encode($params);
+ return (int)$order;
}
/**
@@ -346,7 +282,12 @@ class blockModel extends model
*/
public function update(object $formData): int|false
{
- $this->dao->update(TABLE_BLOCK)->data($formData)->where('id')->eq($formData->id)->autoCheck()->exec();
+ $this->dao->update(TABLE_BLOCK)->data($formData)
+ ->where('id')->eq($formData->id)
+ ->autoCheck()
+ ->batchCheck($this->config->block->edit->requiredFields, 'notempty')
+ ->exec();
+
if(dao::isError()) return false;
$this->loadModel('score')->create('block', 'set');
@@ -354,6 +295,81 @@ class blockModel extends model
return (int)$formData->id;
}
+ /**
+ * Reset dashboard blocks.
+ *
+ * @param string $dashboard
+ * @access public
+ * @return bool
+ */
+ public function reset(string $dashboard): bool
+ {
+ $this->dao->delete()->from(TABLE_BLOCK)
+ ->where('dashboard')->eq($dashboard)
+ ->andWhere('vision')->eq($this->config->vision)
+ ->andWhere('account')->eq($this->app->user->account)
+ ->exec();
+
+ $this->dao->delete()->from(TABLE_CONFIG)
+ ->where('module')->eq($dashboard)
+ ->andWhere('vision')->eq($this->config->vision)
+ ->andWhere('owner')->eq($this->app->user->account)
+ ->andWhere('`key`')->eq('blockInited')
+ ->exec();
+
+ return true;
+ }
+
+ /**
+ * Hidden a block.
+ *
+ * @param int $blockID
+ * @access public
+ * @return bool
+ */
+ public function hidden(int $blockID): bool
+ {
+ $this->dao->update(TABLE_BLOCK)->set('hidden')->eq(1)
+ ->where('id')->eq($blockID)
+ ->andWhere('account')->eq($this->app->user->account)
+ ->andWhere('vision')->eq($this->config->vision)
+ ->exec();
+
+ return true;
+ }
+
+ /**
+ * Delete a block.
+ *
+ * @param int $blockID
+ * @access public
+ * @return bool
+ */
+ public function deleteBlock(int $blockID = 0): bool
+ {
+ $this->dao->delete()->from(TABLE_BLOCK)
+ ->where('id')->eq($blockID)
+ ->andWhere('account')->eq($this->app->user->account)
+ ->andWhere('vision')->eq($this->config->vision)
+ ->exec();
+
+ return true;
+ }
+
+ /**
+ * Set block order.
+ *
+ * @param int $blockID
+ * @param int $order
+ * @access public
+ * @return bool
+ */
+ public function setOrder(int $blockID, int $order): bool
+ {
+ $this->dao->update(TABLE_BLOCK)->set('order')->eq($order)->where('id')->eq($blockID)->exec();
+ return true;
+ }
+
/**
* Save a block.
*
diff --git a/module/block/tao.php b/module/block/tao.php
index 6bb98db45c..bbc9191f0a 100644
--- a/module/block/tao.php
+++ b/module/block/tao.php
@@ -2,24 +2,6 @@
declare(strict_types=1);
class blockTao extends blockModel
{
- /**
- * Get max order number by block dashboard.
- * 获取对应仪表盘下区块的最大排序号.
- *
- * @param string $module
- * @access protected
- * @return int
- */
- protected function fetchMaxOrderByDashboard(string $dashboard): int
- {
- $order = $this->dao->select('MAX(`order`) as `order`')->from(TABLE_BLOCK)
- ->where('dashboard')->eq($dashboard)
- ->andWhere('account')->eq($this->app->user->account)
- ->fetch('order');
-
- return (int)$order;
- }
-
/**
* Get block list of current user.
* 获取当前用户的区块列表.
@@ -49,7 +31,11 @@ class blockTao extends blockModel
*/
protected function insert($formData): bool
{
- $this->dao->insert(TABLE_BLOCK)->data($formData)->autoCheck()->exec();
+ $this->dao->insert(TABLE_BLOCK)->data($formData)
+ ->autoCheck()
+ ->batchCheck($this->config->block->create->requiredFields, 'notempty')
+ ->exec();
+
return true;
}
}
diff --git a/module/block/ui/create.html.php b/module/block/ui/create.html.php
index a1f7aa04c6..5f0836a951 100644
--- a/module/block/ui/create.html.php
+++ b/module/block/ui/create.html.php
@@ -13,20 +13,23 @@ namespace zin;
set::title($title);
jsVar('dashboard', $dashboard);
+jsVar('of', $lang->block->of);
-$paramsRows = array();
-$isMyDashboard = $dashboard == 'my';
+$paramsRows = array();
+$showModules = ($dashboard == 'my' and $modules);
+$showCodes = (($showModules and $module and $codes) or $dashboard != 'my');
foreach($params as $key => $row)
{
$paramsRows[] = formGroup
(
set::label($row['name']),
- set::name('params'),
+ set::name("params[$key]"),
set::class('form-row'),
- set::value($block->params->{$key}),
+ set::value(zget($row, 'default', '')),
set::control(array
(
+ 'id' => "params$key",
'type' => $row['control'],
'items' => isset($row['options']) ? $row['options'] : null
))
@@ -37,60 +40,62 @@ form
(
on::change('#module', 'getForm'),
on::change('#code', 'getForm'),
+ on::change('#paramstype', 'onParamsTypeChange'),
formGroup
(
- set::class($isMyDashboard ? '' : 'hidden'),
- set::value($isMyDashboard ? '' : $dashboard),
+ set::class($showModules ? '' : 'hidden'),
+ set::value($showModules ? $code : $dashboard),
set::label($lang->block->lblModule),
set::name('module'),
- set::control(array
+ set::control($showModules ? array
(
'type' => 'select',
'items' => $modules
- ))
+ ) : 'input')
),
div
(
- set::id('codeRow'),
- $codes
- ? formGroup
+ set::id('codesRow'),
+ formGroup
(
set::label($lang->block->lblBlock),
set::name('code'),
- set::value($code),
- set::control(array
+ set::class($showCodes ? '' : 'hidden'),
+ set::value($showCodes ? $code : $module),
+ set::control($showCodes ? array
(
'type' => 'select',
'items' => array('') + $codes
- ))
- ) : null
+ ) : 'input')
+ )
),
div
(
set::id('paramsRow'),
- set::class('form-grid'),
- $paramsRows,
- (($module and $code) or ($module and !$codes))
- ? formGroup
+ div
(
- set::label($lang->block->name),
- set::name('title'),
- set::value(zget($modules, $module, '') . zget($codes, $code, '')),
- set::class('form-row'),
- set::control('input')
- ) : null,
- (($module and $code) or ($module and !$codes))
- ? formGroup
- (
- set::label($lang->block->grid),
- set::name("grid"),
- set::class('form-row'),
- set::control(array
+ set::class('form-grid'),
+ formGroup
(
- 'type' => 'select',
- 'items' => $lang->block->gridOptions
- ))
- ) : null,
+ set::label($lang->block->name),
+ set::name('title'),
+ set::value(zget($codes, $code)),
+ set::class('form-row'),
+ set::control('input')
+ ),
+ $paramsRows,
+ formGroup
+ (
+ set::label($lang->block->grid),
+ set::name("grid"),
+ set::class('form-row'),
+ set::control(array
+ (
+ 'type' => 'select',
+ 'items' => $lang->block->gridOptions
+ ))
+ )
+ )
)
);
diff --git a/module/block/ui/dashboard.html.php b/module/block/ui/dashboard.html.php
index c4979b4900..62b02dd635 100644
--- a/module/block/ui/dashboard.html.php
+++ b/module/block/ui/dashboard.html.php
@@ -30,9 +30,9 @@ foreach($longBlocks as $index => $block)
([
['text' => $lang->block->refresh, 'url' => ''],
['text' => $lang->edit, 'url' => $this->createLink("block", "edit", "blockID=$block->id"), 'data-toggle' => 'modal'],
- ['text' => $lang->block->hidden, 'url' => ''],
+ ['text' => $lang->block->hidden, 'url' => $this->createLink("block", "delete", "blockID=$block->id&type=hidden")],
['text' => $lang->block->createBlock, 'url' => $this->createLink("block", "create", "dashboard=$dashboard"), 'data-toggle' => 'modal'],
- ['text' => $lang->block->reset, 'url' => ''],
+ ['text' => $lang->block->reset, 'url' => $this->createLink("block", "reset", "dashboard=$dashboard")],
]),
)
)
@@ -78,9 +78,9 @@ foreach($shortBlocks as $index => $block)
([
['text' => $lang->block->refresh, 'url' => ''],
['text' => $lang->edit, 'url' => $this->createLink("block", "edit", "blockID=$block->id"), 'data-toggle' => 'modal'],
- ['text' => $lang->block->hidden, 'url' => ''],
+ ['text' => $lang->block->hidden, 'url' => $this->createLink("block", "delete", "blockID=$block->id&type=hidden")],
['text' => $lang->block->createBlock, 'url' => $this->createLink("block", "create", "dashboard=$dashboard"), 'data-toggle' => 'modal'],
- ['text' => $lang->block->reset, 'url' => ''],
+ ['text' => $lang->block->reset, 'url' => $this->createLink("block", "reset", "dashboard=$dashboard")],
]),
)
)
diff --git a/module/block/ui/edit.html.php b/module/block/ui/edit.html.php
index 3e8e4c3dd5..50ed77b6eb 100644
--- a/module/block/ui/edit.html.php
+++ b/module/block/ui/edit.html.php
@@ -16,15 +16,14 @@ jsVar('blockID', $block->id);
$paramsRows = array();
$showModules = ($dashboard == 'my' and $modules);
-$showCodes = ($module and $codes);
-$showParams = ($code);
+$showCodes = (($showModules and $module and $codes) or $dashboard != 'my');
foreach($params as $key => $row)
{
$paramsRows[] = formGroup
(
set::label($row['name']),
- set::name('params'),
+ set::name("params[$key]"),
set::class('form-row'),
set::value($block->params->{$key}),
set::control(array
@@ -41,10 +40,10 @@ form
on::change('#code', 'getForm'),
formGroup
(
+ set::class($showModules ? '' : 'hidden'),
+ set::value($showModules ? $block->module : $dashboard),
set::label($lang->block->lblModule),
set::name('module'),
- set::class($showModules ? '' : 'hidden'),
- set::value($showModules ? $module : $dashboard),
set::control($showModules ? array
(
'type' => 'select',
@@ -72,8 +71,7 @@ form
set::id('paramsRow'),
div
(
- set::class('form-grid' . ($showParams ? '' : ' hidden')),
- $paramsRows,
+ set::class('form-grid'),
formGroup
(
set::label($lang->block->name),
@@ -82,6 +80,7 @@ form
set::value($block->title),
set::control('input')
),
+ $paramsRows,
formGroup
(
set::label($lang->block->grid),
diff --git a/module/block/ui/welcome.html.php b/module/block/ui/welcome.html.php
new file mode 100644
index 0000000000..fea5226879
--- /dev/null
+++ b/module/block/ui/welcome.html.php
@@ -0,0 +1,146 @@
+
+* @package block
+* @link https://www.zentao.net
+*/
+
+namespace zin;
+
+panel
+(
+ set('class', 'welcome-block'),
+ div
+ (
+ setClass('flex'),
+ col
+ (
+ setStyle(['width' => '20%', 'height' => '176px']),
+ set('class', 'border-right p-3'),
+ set('align', 'center'),
+ center
+ (
+ set('class', 'font-bold'),
+ sprintf($lang->block->welcomeList[$welcomeType], $app->user->realname)
+ ),
+ center
+ (
+ set('class', 'rounded-full avatar-border-one m-5'),
+ center
+ (
+ set('class', 'rounded-full avatar-border-two'),
+ userAvatar
+ (
+ set('size', 'lg'),
+ set('class', 'welcome-avatar'),
+ set('user', $this->app->user)
+ )
+ )
+ )
+ ),
+ cell
+ (
+ set('width', '45%'),
+ set('class', 'border-right p-3'),
+ div
+ (
+ set('class', 'font-bold'),
+ '待我评审:'
+ ),
+ div
+ (
+ setClass('flex items-center justify-around pt-6'),
+ center
+ (
+ col
+ (
+ set('justify', 'center'),
+ set('class', 'text-center'),
+ span
+ (
+ set('class', 'tile-amount text-primary'),
+ 81
+ ),
+ span('研发需求数')
+ )
+ ),
+ center
+ (
+ col
+ (
+ set('justify', 'center'),
+ set('class', 'text-center'),
+ span
+ (
+ set('class', 'tile-amount text-primary'),
+ 81
+ ),
+ span('研发需求数')
+ )
+ ),
+ center
+ (
+ col
+ (
+ set('justify', 'center'),
+ set('class', 'text-center'),
+ span
+ (
+ set('class', 'tile-amount text-primary'),
+ 81
+ ),
+ span('研发需求数')
+ )
+ )
+ )
+ ),
+ cell
+ (
+ set::width('35%'),
+ set('class', 'p-3'),
+ div
+ (
+ set('class', 'font-bold'),
+ '待我评审:'
+ ),
+ div
+ (
+ setClass('flex items-center justify-around pt-6'),
+ center
+ (
+ col
+ (
+ set('justify', 'center'),
+ set('class', 'text-center'),
+ span
+ (
+ set('class', 'tile-amount text-primary'),
+ 81
+ ),
+ span('研发需求数')
+ )
+ ),
+ center
+ (
+ col
+ (
+ set('justify', 'center'),
+ set('class', 'text-center'),
+ span
+ (
+ set('class', 'tile-amount text-primary'),
+ 81
+ ),
+ span('研发需求数')
+ )
+ )
+ )
+ )
+ )
+);
+
+render();
diff --git a/module/block/zen.php b/module/block/zen.php
index 0550be0b9a..78df03fe66 100644
--- a/module/block/zen.php
+++ b/module/block/zen.php
@@ -2,8 +2,8 @@
class blockZen extends block
{
/**
- * Get module options when adding or editing blocks.
* 添加或编辑区块时获取可使用的模块选项
+ * Get module options when adding or editing blocks.
*
* @param string $dashboard
* @access protected
@@ -51,8 +51,8 @@ class blockZen extends block
}
/**
- * Get block options when adding or editing blocks.
* 添加或编辑区块时获取可使用的区块选项
+ * Get block options when adding or editing blocks.
*
* @param string $dashboard
* @param string $module
@@ -71,7 +71,36 @@ class blockZen extends block
if(!$this->block->checkAPI($this->get->hash)) return array();
}
- $blocks = $this->block->getAvailableBlocks($dashboard, $module);
+ if($dashboard == 'my')
+ {
+ if($module and isset($this->lang->block->modules[$module]))
+ {
+ $blocks = $this->lang->block->modules[$module]->availableBlocks;
+ }
+ else
+ {
+ $blocks = array();
+ }
+ }
+ else
+ {
+ if($dashboard and isset($this->lang->block->modules[$dashboard]))
+ {
+ $blocks = $this->lang->block->modules[$dashboard]->availableBlocks;
+ }
+ else
+ {
+ $blocks = $this->lang->block->availableBlocks;
+ }
+ }
+
+ if(isset($this->config->block->closed))
+ {
+ foreach($blocks as $blockKey => $blockName)
+ {
+ if(strpos(",{$this->config->block->closed},", ",{$module}|{$blockKey},") !== false) unset($blocks[$blockKey]);
+ }
+ }
if(!$this->selfCall)
{
@@ -83,22 +112,28 @@ class blockZen extends block
}
/**
- * Get other form items when adding or editing blocks
* 添加或编辑区块时获取其他表单项
+ * Get other form items when adding or editing blocks
*
* @param string $dashboard
* @param string $module
- * @param string $block
+ * @param string $code
* @access protected
* @return array
*/
- protected function getAvailableParams(string $dashboard, string $module = '', string $block = ''): array
+ protected function getAvailableParams(string $dashboard, string $module = '', string $code = ''): array
{
- if(!isset($this->lang->block->moduleList[$module])) return array();
+ if($code == 'todo' || $code == 'list' || $module == 'assigntome')
+ {
+ $code = $module;
+ }
+ elseif($code == 'statistic')
+ {
+ $code = $module . $code;
+ }
- if(!$block) return array();
-
- $params = json_decode($this->block->getParams($block, $module), true);
+ $params = zget($this->config->block->params, $code, '');
+ $params = json_decode(json_encode($params), true);
return !empty($params) ? $params : array();
}
@@ -144,7 +179,7 @@ class blockZen extends block
* @param int $projectID
* @return void
*/
- private function getBlockMoreLink(object $block, int $project): void
+ private function getBlockMoreLink(object $block, int $projectID): void
{
$code = $block->code;
$source = empty($block->source) ? 'common' : $block->source;
diff --git a/module/bug/control.php b/module/bug/control.php
index f69e1cf777..22c6b16217 100755
--- a/module/bug/control.php
+++ b/module/bug/control.php
@@ -1466,7 +1466,7 @@ class bug extends control
{
$bugIDList = $this->post->bugIDList;
$bugIDList = array_unique($bugIDList);
- $oldBugs = $this->bug->getByList($bugIDList);
+ $oldBugs = $this->bug->getByIdList($bugIDList);
$skipBugIDList = '';
unset($_POST['bugIDList']);
@@ -2035,7 +2035,7 @@ class bug extends control
$_POST = array();
$closedBugs = array();
- $bugs = $this->bug->getByList($bugIDList);
+ $bugs = $this->bug->getByIdList($bugIDList);
foreach($bugs as $bugID => $bug)
{
if($bug->status != 'resolved')
diff --git a/module/bug/model.php b/module/bug/model.php
index 83f7e034e1..aa15daa66c 100644
--- a/module/bug/model.php
+++ b/module/bug/model.php
@@ -309,8 +309,8 @@ class bugModel extends model
}
/**
- * Get bug list by browse type.
* 根据浏览类型获取bug列表。
+ * Get bug list by browse type.
*
* @param string $browseType
* @param int|array $productIdList
@@ -337,19 +337,9 @@ class bugModel extends model
/* Get bugs by browse type. */
$bugList = array();
- if($browseType == 'all')
- {
- $bugList = $this->bugTao->getAllBugs($productIdList, $projectID, $executionIdList, $branch, $modules, $orderBy, $pager);
- $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug');
- }
- elseif($browseType == 'review')
- {
- $bugList = $this->bugTao->getListByReviewToMe($productIdList, $projectID, $executionIdList, $branch, $modules, $orderBy, $pager);
- $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug');
- }
+ if($browseType == 'bysearch') $bugList = $this->getBySearch($productIdList, $branch, $queryID, $orderBy, '', $pager, $projectID);
elseif($browseType == 'needconfirm') $bugList = $this->bugTao->getListByNeedconfirm($productIdList, $projectID, $executionIdList, $branch, $modules, $orderBy, $pager);
- elseif($browseType == 'bysearch') $bugList = $this->getBySearch($productIdList, $branch, $queryID, $orderBy, '', $pager, $projectID);
- elseif(strpos(',bymodule,assigntome,openedbyme,resolvedbyme,assigntonull,unconfirmed,unresolved,unclosed,toclosed,longlifebugs,postponedbugs,overduebugs,assignedbyme,', ",$browseType,") !== false) $bugList = $this->bugTao->getListByBrowseType($browseType, $productIdList, $projectID, $executionIdList, $branch, $modules, $orderBy, $pager);
+ elseif(strpos(',all,bymodule,assigntome,openedbyme,resolvedbyme,assigntonull,unconfirmed,unresolved,unclosed,toclosed,longlifebugs,postponedbugs,overduebugs,assignedbyme,review,', ",$browseType,") !== false) $bugList = $this->bugTao->getListByBrowseType($browseType, $productIdList, $projectID, $executionIdList, $branch, $modules, $orderBy, $pager);
return $this->bugTao->batchAppendDelayedDays($bugList);
}
@@ -432,15 +422,15 @@ class bugModel extends model
}
/**
- * Get bugs by ID list.
* 获取指定字段的bug列表。
+ * Get bugs by ID list.
*
* @param int|array|string $bugIDList
* @param string $fields
* @access public
* @return array
*/
- public function getByList(int|array|string $bugIDList = 0, string $fields = '*'): array
+ public function getByIdList(int|array|string $bugIDList = 0, string $fields = '*'): array
{
return $this->dao->select($fields)->from(TABLE_BUG)
->where('deleted')->eq('0')
diff --git a/module/bug/tao.php b/module/bug/tao.php
index eb77edfa7a..90cdfdac7a 100644
--- a/module/bug/tao.php
+++ b/module/bug/tao.php
@@ -21,36 +21,6 @@ class bugTao extends bugModel
->where('t1.id')->eq((int)$bugID)->fetch();
}
- /**
- * Get all bugs.
- * 获取所有的bug。
- *
- * @param int|array $productIdList
- * @param int|string $branch
- * @param int|array $moduleIdList
- * @param int[] $executionIdList
- * @param string $orderBy
- * @param object $pager
- * @param int $projectID
- * @access protected
- * @return array
- */
- protected function getAllBugs(int|array $productIdList, int $projectID, array $executionIdList, int|string $branch, int|array $moduleIdList, string $orderBy, object $pager = null): array
- {
- return $this->dao->select("t1.*, t2.title as planTitle, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, IF(t1.`severity` = 0, {$this->config->maxPriValue}, t1.`severity`) as severityOrder")->from(TABLE_BUG)->alias('t1')
- ->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id')
- ->where('t1.deleted')->eq('0')
- ->andWhere('t1.product')->in($productIdList)
- ->beginIF($projectID)->andWhere('t1.project')->eq($projectID)->fi()
- ->beginIF($this->app->tab !== 'qa')->andWhere('t1.execution')->in($executionIdList)->fi()
- ->beginIF($branch !== 'all')->andWhere('t1.branch')->eq($branch)->fi()
- ->beginIF($moduleIdList)->andWhere('t1.module')->in($moduleIdList)->fi()
- ->beginIF(!$this->app->user->admin)->andWhere('t1.project')->in('0,' . $this->app->user->view->projects)->fi()
- ->orderBy($orderBy)
- ->page($pager)
- ->fetchAll('id');
- }
-
/**
* Get bug list by browse type.
* 通过浏览类型获取bug列表。
@@ -100,6 +70,7 @@ class bugTao extends bugModel
->beginIF($browseType == 'unresolved')->andWhere('status')->eq('active')->fi()
->beginIF($browseType == 'toclosed')->andWhere('status')->eq('resolved')->fi()
->beginIF($browseType == 'postponedbugs')->andWhere('resolution')->eq('postponed')->fi()
+ ->beginIF($browseType == 'review')->andWhere("FIND_IN_SET('{$this->app->user->account}', reviewers)")->fi()
->beginIF($browseType == 'longlifebugs')
->andWhere('lastEditedDate')->lt($lastEditedDate)
@@ -121,6 +92,7 @@ class bugTao extends bugModel
->page($pager)
->fetchAll('id');
+ $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug');
return $bugList;
}
@@ -156,37 +128,6 @@ class bugTao extends bugModel
->fetchAll('id');
}
- /**
- * Get bug list to review.
- * 获取待我审批的bug列表。
- *
- * @param int|array $productIdList
- * @param int $projectID
- * @param int[] $executionIdList
- * @param int|string $branch
- * @param int|array $moduleIdList
- * @param string $orderBy
- * @param object $pager
- * @access public
- * @return array
- */
- protected function getListByReviewToMe(int|array $productIdList, int $projectID, array $executionIdList, int|string $branch, int|array $moduleIdList, string $orderBy, object $pager = null): array
- {
- return $this->dao->select("t1.*, t2.title as planTitle, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)->alias('t1')
- ->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id')
- ->where('t1.deleted')->eq(0)
- ->andWhere('t1.product')->in($productIdList)
- ->beginIF($projectID)->andWhere('t1.project')->eq($projectID)->fi()
- ->beginIF($this->app->tab !== 'qa')->andWhere('t1.execution')->in($executionIdList)->fi()
- ->beginIF($branch !== 'all')->andWhere('t1.branch')->eq($branch)->fi()
- ->beginIF($moduleIdList)->andWhere('t1.module')->in($moduleIdList)->fi()
- ->andWhere("FIND_IN_SET('{$this->app->user->account}', t1.reviewers)")
- ->beginIF(!$this->app->user->admin)->andWhere('t1.project')->in('0,' . $this->app->user->view->projects)->fi()
- ->orderBy($orderBy)
- ->page($pager)
- ->fetchAll('id');
- }
-
/**
* Get cases created by bug.
* 获取bug建的用例。
diff --git a/module/bug/test/bug.class.php b/module/bug/test/bug.class.php
index f3aa1221f3..0be72507e8 100644
--- a/module/bug/test/bug.class.php
+++ b/module/bug/test/bug.class.php
@@ -670,9 +670,9 @@ class bugTest
* @access public
* @return array
*/
- public function getByListTest($bugIDList)
+ public function getByIdListTest($bugIDList)
{
- $bugs = $this->objectModel->getByList($bugIDList);
+ $bugs = $this->objectModel->getByIdList($bugIDList);
foreach($bugs as $bug)
{
@@ -972,7 +972,7 @@ class bugTest
{
$this->objectModel->batchConfirm($bugIDList);
- $bugs = $this->objectModel->getByList($bugIDList);
+ $bugs = $this->objectModel->getByIdList($bugIDList);
$confirm = '';
foreach($bugs as $bug) $confirm .= ',' . $bug->confirmed;
@@ -1035,7 +1035,7 @@ class bugTest
*/
public function batchChangeBranchTest($bugIDList, $branchID, $bugID)
{
- $bugs = $this->objectModel->getByList($bugIDList);
+ $bugs = $this->objectModel->getByIdList($bugIDList);
$object = $this->objectModel->batchChangeBranch($bugIDList, $branchID, $bugs);
@@ -1060,7 +1060,7 @@ class bugTest
*/
public function batchChangeModuleTest($bugIDList, $moduleID, $bugID)
{
- $bugs = $this->objectModel->getByList($bugIDList);
+ $bugs = $this->objectModel->getByIdList($bugIDList);
$object = $this->objectModel->batchChangeModule($bugIDList, $moduleID, $bugs);
@@ -1178,7 +1178,7 @@ class bugTest
*/
public function processBuildForBugsTest($bugIDList)
{
- $bugs = $this->objectModel->getByList($bugIDList);
+ $bugs = $this->objectModel->getByIdList($bugIDList);
$array = $this->objectModel->processBuildForBugs($bugs);
if(dao::isError())
@@ -1200,7 +1200,7 @@ class bugTest
*/
public function extractAccountsFromListTest($bugIDList)
{
- $bugs = $this->objectModel->getByList($bugIDList);
+ $bugs = $this->objectModel->getByIdList($bugIDList);
$array = $this->objectModel->extractAccountsFromList($bugs);
if(dao::isError())
@@ -1861,7 +1861,7 @@ class bugTest
*/
public function formCustomedBugsTest($bugIDList)
{
- $bugs = $this->objectModel->getByList($bugIDList);
+ $bugs = $this->objectModel->getByIdList($bugIDList);
$array = $this->objectModel->formCustomedBugs($bugs);
if(dao::isError())
diff --git a/module/bug/test/model/getbyidlist.php b/module/bug/test/model/getbyidlist.php
new file mode 100755
index 0000000000..7772bad759
--- /dev/null
+++ b/module/bug/test/model/getbyidlist.php
@@ -0,0 +1,47 @@
+#!/usr/bin/env php
+getByList();
+cid=1
+pid=1
+
+*/
+function initData()
+{
+ $bug = zdTable('bug');
+ $bug->id->range('1-10');
+ $bug->status->range("resolved,active,closed");
+ $bug->title->prefix("BUG")->range('1-10');
+ $bug->plan->range('0,1,2');
+ $bug->module->range('0,1,2');
+ $bug->story->range('0,1,2');
+
+ $bug->gen(10);
+}
+
+initData();
+
+$bugIDList = array('1,2,3', '1,4', '2,7', '1000001');
+$fieldsList = array('*', 'id,title,status,plan,module,story', 'title,status', 'title');
+
+$bug = new bugTest();
+
+r($bug->getByIdListTest($bugIDList[0], $fieldsList[0])) && p('1:title') && e('BUG1'); // 查询id为1的bug title
+r($bug->getByIdListTest($bugIDList[0], $fieldsList[1])) && p('2:status') && e('active'); // 查询id为2的bug status
+r($bug->getByIdListTest($bugIDList[0], $fieldsList[1])) && p('2:module') && e('1'); // 查询id为2的bug module
+r($bug->getByIdListTest($bugIDList[0], $fieldsList[1])) && p('3:plan') && e('2'); // 查询id为2的bug plan
+r($bug->getByIdListTest($bugIDList[0], $fieldsList[1])) && p('3:story') && e('2'); // 查询id为2的bug story
+r($bug->getByIdListTest($bugIDList[0], $fieldsList[2])) && p('3:title') && e('BUG3'); // 查询id为3的bug title
+r($bug->getByIdListTest($bugIDList[0], $fieldsList[3])) && p('1:title') && e('BUG1'); // 查询id为1的bug title
+r($bug->getByIdListTest($bugIDList[1], $fieldsList[0])) && p('4:title') && e('BUG4'); // 查询id为4的bug title
+r($bug->getByIdListTest($bugIDList[1], $fieldsList[1])) && p('4:status') && e('resolved'); // 查询id为4的bug status
+r($bug->getByIdListTest($bugIDList[1], $fieldsList[3])) && p('1:title') && e('BUG1'); // 查询id为1的bug title
+r($bug->getByIdListTest($bugIDList[2], $fieldsList[0])) && p('2:title') && e('BUG2'); // 查询id为2的bug title
+r($bug->getByIdListTest($bugIDList[2], $fieldsList[1])) && p('2:status') && e('active'); // 查询id为2的bug status
+r($bug->getByIdListTest($bugIDList[2], $fieldsList[2])) && p('7:status') && e('resolved'); // 查询id为7的bug title
+r($bug->getByIdListTest($bugIDList[3], $fieldsList[0])) && p('') && e('0'); // 查询不存在的ID
diff --git a/module/bug/test/model/getbylist.php b/module/bug/test/model/getbylist.php
deleted file mode 100755
index 385c04d084..0000000000
--- a/module/bug/test/model/getbylist.php
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env php
-getByList();
-cid=1
-pid=1
-
-*/
-function initData()
-{
- $bug = zdTable('bug');
- $bug->id->range('1-10');
- $bug->status->range("resolved,active,closed");
- $bug->title->prefix("BUG")->range('1-10');
- $bug->plan->range('0,1,2');
- $bug->module->range('0,1,2');
- $bug->story->range('0,1,2');
-
- $bug->gen(10);
-}
-
-initData();
-
-$bugIDList = array('1,2,3', '1,4', '2,7', '1000001');
-$fieldsList = array('*', 'id,title,status,plan,module,story', 'title,status', 'title');
-
-$bug = new bugTest();
-
-r($bug->getByListTest($bugIDList[0], $fieldsList[0])) && p('1:title') && e('BUG1'); // 查询id为1的bug title
-r($bug->getByListTest($bugIDList[0], $fieldsList[1])) && p('2:status') && e('active'); // 查询id为2的bug status
-r($bug->getByListTest($bugIDList[0], $fieldsList[1])) && p('2:module') && e('1'); // 查询id为2的bug module
-r($bug->getByListTest($bugIDList[0], $fieldsList[1])) && p('3:plan') && e('2'); // 查询id为2的bug plan
-r($bug->getByListTest($bugIDList[0], $fieldsList[1])) && p('3:story') && e('2'); // 查询id为2的bug story
-r($bug->getByListTest($bugIDList[0], $fieldsList[2])) && p('3:title') && e('BUG3'); // 查询id为3的bug title
-r($bug->getByListTest($bugIDList[0], $fieldsList[3])) && p('1:title') && e('BUG1'); // 查询id为1的bug title
-r($bug->getByListTest($bugIDList[1], $fieldsList[0])) && p('4:title') && e('BUG4'); // 查询id为4的bug title
-r($bug->getByListTest($bugIDList[1], $fieldsList[1])) && p('4:status') && e('resolved'); // 查询id为4的bug status
-r($bug->getByListTest($bugIDList[1], $fieldsList[3])) && p('1:title') && e('BUG1'); // 查询id为1的bug title
-r($bug->getByListTest($bugIDList[2], $fieldsList[0])) && p('2:title') && e('BUG2'); // 查询id为2的bug title
-r($bug->getByListTest($bugIDList[2], $fieldsList[1])) && p('2:status') && e('active'); // 查询id为2的bug status
-r($bug->getByListTest($bugIDList[2], $fieldsList[2])) && p('7:status') && e('resolved'); // 查询id为7的bug title
-r($bug->getByListTest($bugIDList[3], $fieldsList[0])) && p('') && e('0'); // 查询不存在的ID
diff --git a/module/bug/test/model/getlist.php b/module/bug/test/model/getlist.php
index 738994a714..ece7d465f1 100755
--- a/module/bug/test/model/getlist.php
+++ b/module/bug/test/model/getlist.php
@@ -64,7 +64,6 @@ r(count($bug->getList($browseType[0], $productIdList[2], $projectID[0], $execut
r(count($bug->getList($browseType[0], $productIdList[0], $projectID[2], $executionIdList[0], $branch[0], $moduleID[0]))) && p('') && e('0'); //获取不存在项目ID的bug列表,查看数量是否正确
r(count($bug->getList($browseType[0], $productIdList[0], $projectID[0], $executionIdList[2], $branch[0], $moduleID[0]))) && p('') && e('0'); //获取不存在执行ID的bug列表,查看数量是否正确
-r($bug->getList($browseType[0], $productIdList[0], $projectID[0], $executionIdList[0], $branch[0], $moduleID[0])) && p('1:planTitle') && e('计划1'); //获取全部产品1下的全部bug列表,查看ID为1的bug的计划名称是否正确
r($bug->getList($browseType[0], $productIdList[1], $projectID[1], $executionIdList[1], $branch[1], $moduleID[0])) && p('2:title') && e('BUG2'); //获取全部产品1下的项目相关的全部bug列表,查看ID为2的bug的名称是否正确
r($bug->getList($browseType[1], $productIdList[0], $projectID[0], $executionIdList[0], $branch[0], $moduleID[1])) && p('3:module') && e('1'); //获取产品1模块下的bug列表,查看ID为3的bug的module是否正确
r($bug->getList($browseType[2], $productIdList[0], $projectID[0], $executionIdList[0], $branch[0], $moduleID[0])) && p('1:assignedTo') && e('admin'); //获取产品1下指派给我的bug列表,查看ID为1的bug的指派人是否正确
diff --git a/module/build/control.php b/module/build/control.php
index e394fc78d9..00adc6156e 100644
--- a/module/build/control.php
+++ b/module/build/control.php
@@ -723,7 +723,7 @@ class build extends control
$build = $this->build->getByID($buildID);
$oldBranch = $build->branch;
$buildStories = $build->allStories ? $this->loadModel('story')->getByList($build->allStories) : array();
- $buildBugs = $build->allBugs ? $this->loadModel('bug')->getByList($build->allBugs) : array();
+ $buildBugs = $build->allBugs ? $this->loadModel('bug')->getByIdList($build->allBugs) : array();
$branchPairs = $this->loadModel('branch')->getPairs($build->product);
$typeName = $this->lang->product->branchName[$build->productType];
@@ -798,7 +798,7 @@ class build extends control
}
$build = $this->build->getByID($buildID);
$planStories = $build->allStories ? $this->loadModel('story')->getByList($build->allStories) : '';
- $planBugs = $build->allBugs ? $this->loadModel('bug')->getByList($build->allBugs) : '';
+ $planBugs = $build->allBugs ? $this->loadModel('bug')->getByIdList($build->allBugs) : '';
if($oldBranch)
{
foreach($planStories as $storyID => $story)
diff --git a/module/execution/control.php b/module/execution/control.php
index 234acba3dc..e6dc952c14 100644
--- a/module/execution/control.php
+++ b/module/execution/control.php
@@ -77,7 +77,7 @@ class execution extends control
$this->loadModel('product');
/* Get executions and products info. */
- $executionID = $this->execution->saveState($executionID, $this->executions);
+ $executionID = $this->execution->checkAccess($executionID, $this->executions);
$execution = $this->execution->getById($executionID);
$products = $this->product->getProducts($executionID);
$childExecutions = $this->execution->getChildExecutions($executionID);
diff --git a/module/execution/model.php b/module/execution/model.php
index 734bce538a..e24c9c56cc 100755
--- a/module/execution/model.php
+++ b/module/execution/model.php
@@ -322,8 +322,7 @@ class executionModel extends model
}
/* Save session. */
- $this->session->set('execution', $executionID, $this->app->tab);
- $this->setProjectSession($executionID);
+ $this->executionTao->saveSession($executionID);
/* Return execution id. */
return $executionID;
@@ -3033,7 +3032,7 @@ class executionModel extends model
$requiredFields = trim($requiredFields, ',');
$bugToTasks = fixer::input('post')->get();
- $bugs = $this->bug->getByList(array_keys($bugToTasks->import));
+ $bugs = $this->bug->getByIdList(array_keys($bugToTasks->import));
foreach($bugToTasks->import as $key => $value)
{
$bug = zget($bugs, $key, '');
diff --git a/module/execution/tao.php b/module/execution/tao.php
new file mode 100644
index 0000000000..6939bec107
--- /dev/null
+++ b/module/execution/tao.php
@@ -0,0 +1,27 @@
+
+ * @package execution
+ * @link https://www.zentao.net
+ */
+class executionTao extends executionModel
+{
+ /**
+ * 将执行ID保存到session中。
+ * Save the execution ID to the session.
+ *
+ * @param int $executionID
+ * @access protected
+ * @return void
+ */
+ protected function saveSession(int $executionID): void
+ {
+ $this->session->set('execution', $executionID, $this->app->tab);
+ $this->setProjectSession($executionID);
+ }
+}
diff --git a/module/my/control.php b/module/my/control.php
index f3fb45f883..5dca80336c 100755
--- a/module/my/control.php
+++ b/module/my/control.php
@@ -1174,7 +1174,7 @@ EOF;
if($feedback->solution == 'totask') $taskIdList[] = $feedback->result;
if($feedback->solution == 'ticket') $ticketIdList[] = $feedback->result;
}
- $bugs = $bugIdList ? $this->loadModel('bug')->getByList($bugIdList) : array();
+ $bugs = $bugIdList ? $this->loadModel('bug')->getByIdList($bugIdList) : array();
$stories = $storyIdList ? $this->loadModel('story')->getByList($storyIdList) : array();
$todos = $todoIdList ? $this->loadModel('todo')->getByList($todoIdList) : array();
$tasks = $taskIdList ? $this->loadModel('task')->getByList($taskIdList) : array();
diff --git a/module/product/config/form.php b/module/product/config/form.php
index 5dd516371b..40fb2703ec 100644
--- a/module/product/config/form.php
+++ b/module/product/config/form.php
@@ -7,12 +7,28 @@ $config->product->form->create['line'] = array('type' => 'int', 'contro
$config->product->form->create['lineName'] = array('type' => 'string', 'control' => 'input', 'required' => false, 'default' => '', 'filter' => 'trim');
$config->product->form->create['name'] = array('type' => 'string', 'control' => 'input', 'required' => true, 'default' => '', 'filter' => 'trim');
$config->product->form->create['code'] = array('type' => 'string', 'control' => 'input', 'required' => true, 'default' => '', 'filter' => 'trim');
-$config->product->form->create['PO'] = array('type' => 'account', 'control' => 'select', 'required' => false, 'default' => '', 'options' => '');
-$config->product->form->create['QD'] = array('type' => 'account', 'control' => 'select', 'required' => false, 'default' => '', 'options' => '');
-$config->product->form->create['RD'] = array('type' => 'account', 'control' => 'select', 'required' => false, 'default' => '', 'options' => '');
+$config->product->form->create['PO'] = array('type' => 'account', 'control' => 'select', 'required' => false, 'default' => '', 'options' => array());
+$config->product->form->create['QD'] = array('type' => 'account', 'control' => 'select', 'required' => false, 'default' => '', 'options' => array());
+$config->product->form->create['RD'] = array('type' => 'account', 'control' => 'select', 'required' => false, 'default' => '', 'options' => array());
$config->product->form->create['reviewer'] = array('type' => 'array', 'control' => 'multi-select', 'required' => false, 'default' => '', 'filter' => 'join', 'options' => 'users');
$config->product->form->create['type'] = array('type' => 'string', 'control' => 'select', 'required' => false, 'default' => 'normal', 'options' => $lang->product->typeList);
$config->product->form->create['status'] = array('type' => 'string', 'control' => 'hidden', 'required' => false, 'default' => 'normal');
$config->product->form->create['desc'] = array('type' => 'string', 'control' => 'textarea', 'required' => false, 'default' => '');
-$config->product->form->create['acl'] = array('type' => 'string', 'control' => 'acl', 'required' => false, 'default' => 'private', 'options' => $lang->product->aclList);
+$config->product->form->create['acl'] = array('type' => 'string', 'control' => 'radio', 'required' => false, 'default' => 'private', 'options' => $lang->product->aclList);
$config->product->form->create['whitelist'] = array('type' => 'array', 'control' => 'multi-select', 'required' => false, 'default' => '', 'filter' => 'join', 'options' => 'users');
+
+$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' => 'input', 'required' => true, 'default' => '', 'filter' => 'trim');
+$config->product->form->edit['code'] = array('type' => 'string', 'control' => 'input', '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['changeProjects'] = array('type' => 'string', 'control' => 'hidden', 'required' => false, 'default' => '');
diff --git a/module/product/control.php b/module/product/control.php
index 4c4bad016c..47da78d20f 100755
--- a/module/product/control.php
+++ b/module/product/control.php
@@ -412,10 +412,9 @@ class product extends control
{
$data = form::data($this->config->product->form->create);
$data = $this->productZen->prepareCreateExtras($data, $this->post->acl, $this->post->uid);
- if(!$data) return $this->productZen->sendError4Create();
$productID = $this->product->create($data);
- if(!$productID) return $this->productZen->sendError4Create();
+ if(!$productID) return $this->productZen->sendDaoError();
return $this->productZen->responseAfterCreate($productID, $data, $this->post->uid, zget($_POST, 'lineName', ''));
}
@@ -434,88 +433,29 @@ class product extends control
* @access public
* @return void
*/
- public function edit($productID, $action = 'edit', $extra = '', $programID = 0)
+ public function edit(string $productID, string $action = 'edit', string $extra = '', string $programID = '0')
{
- $this->app->loadLang('custom');
+ $productID = (int)$productID;
+ $programID = (int)$programID;
if(!empty($_POST))
{
- $changes = $this->product->update($productID);
+ $data = form::data($this->config->product->form->edit);
+ $data = $this->productZen->prepareEditExtras($data, $this->post->acl, $this->post->uid);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- if($action == 'undelete')
- {
- $this->loadModel('action');
- $this->dao->update(TABLE_PRODUCT)->set('deleted')->eq(0)->where('id')->eq($productID)->exec();
- $this->dao->update(TABLE_ACTION)->set('extra')->eq(ACTIONMODEL::BE_UNDELETED)->where('id')->eq($extra)->exec();
- $this->action->create('product', $productID, 'undeleted');
- }
- if($changes)
- {
- $actionID = $this->loadModel('action')->create('product', $productID, 'edited');
- $this->action->logHistory($actionID, $changes);
- }
+ $changes = $this->product->update($productID, $data, $this->post->uid);
+ if(dao::isError()) return $this->productZen->sendDaoError();
- $message = $this->executeHooks($productID);
- if($message) $this->lang->saveSuccess = $message;
-
- $moduleName = $programID ? 'program' : 'product';
- $methodName = $programID ? 'product' : 'view';
- $param = $programID ? "programID=$programID" : "product=$productID";
- $locate = $this->createLink($moduleName, $methodName, $param);
-
- if(!$programID) $this->session->set('productList', $this->createLink('product', 'browse', $param), 'product');
- return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $locate));
+ if($action == 'undelete') $this->loadModel('action')->undelete((int)$extra);
+ return $this->productZen->responseAfterEdit($productID, $programID, $changes);
}
- $product = $this->product->getById($productID);
+ $this->productZen->setEditMenu($productID, $programID);
+
+ $product = $this->product->getByID($productID);
$productID = $this->product->saveState($productID, $this->products);
- $this->product->setMenu($productID);
- if($programID) $this->loadModel('program')->setMenu($programID);
-
- /* Get the relevant person in charge. */
- $this->loadModel('user');
- $poUsers = $this->user->getPairs('nodeleted|pofirst|noclosed', $product->PO, $this->config->maxCount);
- if(!empty($this->config->user->moreLink)) $this->config->moreLinks["PO"] = $this->config->user->moreLink;
-
- $qdUsers = $this->user->getPairs('nodeleted|qdfirst|noclosed', $product->QD, $this->config->maxCount);
- if(!empty($this->config->user->moreLink)) $this->config->moreLinks["QD"] = $this->config->user->moreLink;
-
- $rdUsers = $this->user->getPairs('nodeleted|devfirst|noclosed', $product->RD, $this->config->maxCount);
- if(!empty($this->config->user->moreLink)) $this->config->moreLinks["RD"] = $this->config->user->moreLink;
-
- $lines = array();
- if($product->program and $this->config->systemMode == 'ALM') $lines = array('') + $this->product->getLinePairs($product->program);
-
- /* Get programs. */
- $programs = $this->loadModel('program')->getTopPairs('', 'noclosed');
- if(!isset($programs[$product->program]) and $product->program)
- {
- $program = $this->program->getByID($product->program);
- $programs += array($product->program => $program->name);
- }
-
- $this->view->title = $this->lang->product->edit . $this->lang->colon . $product->name;
- $this->view->position[] = html::a($this->createLink($this->moduleName, 'browse'), $product->name);
- $this->view->position[] = $this->lang->product->edit;
-
- $this->view->product = $product;
- $this->view->groups = $this->loadModel('group')->getPairs();
- $this->view->program = $this->loadModel('program')->getParentPairs();
- $this->view->poUsers = $poUsers;
- $this->view->poUsers = $poUsers;
- $this->view->qdUsers = $qdUsers;
- $this->view->rdUsers = $rdUsers;
- $this->view->fields = $this->product->buildFormFields($this->config->product->edit->fields, $product);
- $this->view->users = $this->user->getPairs('nodeleted|noclosed');
- $this->view->programs = array('') + $programs;
- $this->view->lines = $lines;
- $this->view->URSRPairs = $this->loadModel('custom')->getURSRPairs();
-
- unset($this->lang->product->typeList['']);
- //$this->display();
- $this->render();
+ $this->productZen->buildEditForm($product);
}
/**
@@ -860,281 +800,6 @@ class product extends control
$this->display();
}
- /**
- * Ajax get products.
- *
- * @param int $executionID
- * @access public
- * @return void
- */
- public function ajaxGetProducts($executionID)
- {
- $this->loadModel('build');
- if(!$executionID) return print(html::select('product', array(), '', "class='form-control chosen' required"));
- $status = empty($this->config->CRProduct) ? 'noclosed' : '';
- $products = $this->product->getProductPairsByProject($executionID, $status);
- if(empty($products))
- {
- return printf($this->lang->build->noProduct, $this->createLink('execution', 'manageproducts', "executionID=$executionID&from=buildCreate", '', 'true'), 'project');
- }
- else
- {
- return print(html::select('product', $products, empty($product) ? '' : $product->id, "onchange='loadBranches(this.value);' class='form-control chosen' required data-toggle='modal' data-type='iframe'"));
- }
- }
-
- /**
- * Ajax get product by id.
- *
- * @param int $productID
- * @access public
- * @return void
- */
- public function ajaxGetProductById($productID)
- {
- $product = $this->product->getById($productID);
-
- $product->branchSourceName = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]);
- $product->branchName = $this->lang->product->branchName[$product->type];
- echo json_encode($product);
- }
-
- /**
- * AJAX: get projects of a product in html select.
- *
- * @param int $productID
- * @param int $branch
- * @param int $projectID
- * @access public
- * @return void
- */
- public function ajaxGetProjects($productID, $branch = 0, $projectID = 0)
- {
- $projects = array('' => '');
- $projects += $this->product->getProjectPairsByProduct($productID, $branch);
- if($this->app->getViewType() == 'json') return print(json_encode($projects));
-
- return print(html::select('project', $projects, $projectID, "class='form-control' onchange='loadProductExecutions({$productID}, this.value)'"));
- }
-
- /**
- * AJAX: get projects of a product in html select.
- *
- * @param int $productID
- * @param int $branch
- * @param int $number
- * @access public
- * @return void
- */
- public function ajaxGetProjectsByBranch($productID, $branch = 0, $number = 0)
- {
- $projects = array('' => '');
- $projects += $this->product->getProjectPairsByProduct($productID, $branch);
-
- return print(html::select('projects' . "[$number]", array('' => '') + $projects, 0, "class='form-control' onchange='loadProductExecutionsByProject($productID, this.value, $number)'"));
- }
-
- /**
- * AJAX: get executions of a product in html select.
- *
- * @param int $productID
- * @param int $projectID
- * @param int $branch
- * @param string $number
- * @param int $executionID
- * @param string $from showImport
- * @param string mode
- * @access public
- * @return void
- */
- public function ajaxGetExecutions($productID, $projectID = 0, $branch = 0, $number = '', $executionID = 0, $from = '', $mode = '')
- {
- if($this->app->tab == 'execution' and $this->session->execution)
- {
- $execution = $this->loadModel('execution')->getByID($this->session->execution);
- if($execution->type == 'kanban') $projectID = $execution->project;
- }
-
- if($projectID) $project = $this->loadModel('project')->getById($projectID);
- $mode .= ($from == 'bugToTask' or empty($this->config->CRExecution)) ? 'noclosed' : '';
- $mode .= !$projectID ? ',multiple' : '';
- $executions = $from == 'showImport' ? $this->product->getAllExecutionPairsByProduct($productID, $branch, $projectID) : $this->product->getExecutionPairsByProduct($productID, $branch, 'id_desc', $projectID, $mode);
- if($this->app->getViewType() == 'json') return print(json_encode($executions));
-
- if($number === '')
- {
- $event = $from == 'bugToTask' ? '' : " onchange='loadExecutionRelated(this.value)'";
- $datamultiple = !empty($project) ? "data-multiple={$project->multiple}" : '';
- return print(html::select('execution', array('' => '') + $executions, $executionID, "class='form-control' $datamultiple $event"));
- }
- else
- {
- $executions = empty($executions) ? array('' => '') : $executions;
- $executionsName = $from == 'showImport' ? "execution[$number]" : "executions[$number]";
- $misc = $from == 'showImport' ? "class='form-control' onchange='loadImportExecutionRelated(this.value, $number)'" : "class='form-control' onchange='loadExecutionBuilds($productID, this.value, $number)'";
- return print(html::select($executionsName, $executions, '', $misc));
- }
- }
-
- /**
- * AJAX: get executions of a product in html select.
- *
- * @param int $productID
- * @param int $projectID
- * @param int $branch
- * @param int $number
- * @access public
- * @return void
- */
- public function ajaxGetExecutionsByProject($productID, $projectID = 0, $branch = 0, $number = 0)
- {
- $noMultipleExecutionID = $projectID ? $this->loadModel('execution')->getNoMultipleID($projectID) : '';
- $executions = $this->product->getExecutionPairsByProduct($productID, $branch, 'id_desc', $projectID, 'multiple,stagefilter');
-
- $disabled = $noMultipleExecutionID ? "disabled='disabled'" : '';
- $html = html::select("executions[{$number}]", array('' => '') + $executions, 0, "class='form-control' onchange='loadExecutionBuilds($productID, this.value, $number)' $disabled");
-
- if($noMultipleExecutionID) $html .= html::hidden("executions[{$number}]", $noMultipleExecutionID, "id=executions{$number}");
-
- return print($html);
- }
-
- /**
- * AJAX: get plans of a product in html select.
- *
- * @param int $productID
- * @param int $planID
- * @param bool $needCreate
- * @param string $expired
- * @param string $param
- * @access public
- * @return void
- */
- public function ajaxGetPlans($productID, $branch = 0, $planID = 0, $fieldID = '', $needCreate = false, $expired = '', $param = '')
- {
- $param = strtolower($param);
- if(strpos($param, 'forstory') === false)
- {
- $plans = $this->loadModel('productplan')->getPairs($productID, empty($branch) ? 'all' : $branch, $expired, strpos($param, 'skipparent') !== false);
- }
- else
- {
- $plans = $this->loadModel('productplan')->getPairsForStory($productID, $branch == '0' ? 'all' : $branch, $param);
- }
- $field = $fieldID !== '' ? "plans[$fieldID]" : 'plan';
- $multiple = strpos($param, 'multiple') === false ? '' : 'multiple';
- $output = html::select($field, $plans, $planID, "class='form-control chosen' $multiple");
-
- if($branch == 0 and strpos($param, 'edit') and (strpos($param, 'forstory') === false)) $output = html::select($field, $plans, $planID, "class='form-control chosen' multiple");
-
- if(count($plans) == 1 and $needCreate and $needCreate !== 'false')
- {
- $output .= "
";
- $output .= html::a($this->createLink('productplan', 'create', "productID=$productID&branch=$branch", '', true), "", '', "class='btn btn-icon' data-toggle='modal' data-type='iframe' data-width='95%' title='{$this->lang->productplan->create}'");
- $output .= '
';
- $output .= "";
- $output .= html::a("javascript:void(0)", "", '', "class='btn btn-icon refresh' data-toggle='tooltip' title='{$this->lang->refresh}' onclick='loadProductPlans($productID)'");
- $output .= '
';
- }
- echo $output;
- }
-
- /**
- * Ajax get product lines.
- *
- * @param int $programID
- * @param int $productID
- * @access public
- * @return void
- */
- public function ajaxGetLine($programID, $productID = 0)
- {
- $lines = array();
- if(empty($productID) or $programID) $lines = $this->product->getLinePairs($programID);
-
- if($productID) return print(html::select("lines[$productID]", array('' => '') + $lines, '', "class='form-control picker-select'"));
- if(!$productID) return print(html::select('line', array('' => '') + $lines, '', "class='form-control picker-select'"));
- }
-
- /**
- * Ajax get reviewers.
- *
- * @param int $productID
- * @param int $storyID
- * @access public
- * @return void
- */
- public function ajaxGetReviewers($productID, $storyID = 0)
- {
- /* Get product reviewers. */
- $product = $this->product->getByID($productID);
- $productReviewers = $product->reviewer;
- if(!$productReviewers and $product->acl != 'open') $productReviewers = $this->loadModel('user')->getProductViewListUsers($product, '', '', '', '');
-
- $storyReviewers = '';
- if($storyID)
- {
- $story = $this->loadModel('story')->getByID($storyID);
- $storyReviewers = $this->story->getReviewerPairs($story->id, $story->version);
- $storyReviewers = implode(',', array_keys($storyReviewers));
- }
-
- $reviewers = $this->loadModel('user')->getPairs('noclosed|nodeleted', $storyReviewers, 0, $productReviewers);
-
- echo html::select("reviewer[]", $reviewers, $storyReviewers, "class='form-control chosen' multiple");
- }
-
- /**
- * Drop menu page.
- *
- * @param int $productID
- * @param string $module
- * @param string $method
- * @param string $extra
- * @param string $from
- * @access public
- * @return void
- */
- public function ajaxGetDropMenu($productID, $module, $method, $extra = '', $from = '')
- {
- $shadow = 0;
- if($from == 'qa')
- {
- $shadow = 'all';
- $this->app->loadConfig('qa');
- foreach($this->config->qa->menuList as $menu) $this->lang->navGroup->$menu = 'qa';
- }
-
- $programProducts = array();
-
- if($this->app->tab == 'project')
- {
- $products = $this->product->getProducts($this->session->project);
- }
- elseif($this->app->tab == 'feedback')
- {
- $products = $this->loadModel('feedback')->getGrantProducts(false);
- }
- else
- {
- $products = $this->product->getList(0, 'all', 0, 0, $shadow);
- }
-
- $programProducts = array();
- foreach($products as $product) $programProducts[$product->program][] = $product;
-
- $this->view->link = $this->product->getProductLink($module, $method, $extra);
- $this->view->productID = $productID;
- $this->view->module = $module;
- $this->view->method = $method;
- $this->view->extra = $extra;
- $this->view->products = $programProducts;
- $this->view->projectID = $this->app->tab == 'project' ? $this->session->project : 0;
- $this->view->programs = $this->loadModel('program')->getPairs(true);
- $this->view->lines = $this->product->getLinePairs();
- $this->display();
- }
-
/**
* Update order.
*
@@ -1464,19 +1129,6 @@ class product extends control
$this->display();
}
- /**
- * Set product id to session in ajax
- *
- * @param int $productID
- * @access public
- * @return void
- */
- public function ajaxSetState($productID)
- {
- $this->session->set('product', (int)$productID, $this->app->tab);
- $this->send(array('result' => 'success', 'productID' => $this->session->product));
- }
-
/**
* Story track.
*
@@ -1543,4 +1195,293 @@ class product extends control
$data = fixer::input('post')->get();
$this->loadModel('setting')->updateItem("{$this->app->user->account}.product.showAllProjects", $data->showAllProjects);
}
+
+ /**
+ * Ajax get products.
+ *
+ * @param int $executionID
+ * @access public
+ * @return void
+ */
+ public function ajaxGetProducts($executionID)
+ {
+ $this->loadModel('build');
+ if(!$executionID) return print(html::select('product', array(), '', "class='form-control chosen' required"));
+ $status = empty($this->config->CRProduct) ? 'noclosed' : '';
+ $products = $this->product->getProductPairsByProject($executionID, $status);
+ if(empty($products))
+ {
+ return printf($this->lang->build->noProduct, $this->createLink('execution', 'manageproducts', "executionID=$executionID&from=buildCreate", '', 'true'), 'project');
+ }
+ else
+ {
+ return print(html::select('product', $products, empty($product) ? '' : $product->id, "onchange='loadBranches(this.value);' class='form-control chosen' required data-toggle='modal' data-type='iframe'"));
+ }
+ }
+
+ /**
+ * Ajax get product by id.
+ *
+ * @param int $productID
+ * @access public
+ * @return void
+ */
+ public function ajaxGetProductById($productID)
+ {
+ $product = $this->product->getById($productID);
+
+ $product->branchSourceName = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]);
+ $product->branchName = $this->lang->product->branchName[$product->type];
+ echo json_encode($product);
+ }
+
+ /**
+ * AJAX: get projects of a product in html select.
+ *
+ * @param int $productID
+ * @param int $branch
+ * @param int $projectID
+ * @access public
+ * @return void
+ */
+ public function ajaxGetProjects($productID, $branch = 0, $projectID = 0)
+ {
+ $projects = array('' => '');
+ $projects += $this->product->getProjectPairsByProduct($productID, $branch);
+ if($this->app->getViewType() == 'json') return print(json_encode($projects));
+
+ return print(html::select('project', $projects, $projectID, "class='form-control' onchange='loadProductExecutions({$productID}, this.value)'"));
+ }
+
+ /**
+ * AJAX: get projects of a product in html select.
+ *
+ * @param int $productID
+ * @param int $branch
+ * @param int $number
+ * @access public
+ * @return void
+ */
+ public function ajaxGetProjectsByBranch($productID, $branch = 0, $number = 0)
+ {
+ $projects = array('' => '');
+ $projects += $this->product->getProjectPairsByProduct($productID, $branch);
+
+ return print(html::select('projects' . "[$number]", array('' => '') + $projects, 0, "class='form-control' onchange='loadProductExecutionsByProject($productID, this.value, $number)'"));
+ }
+
+ /**
+ * AJAX: get executions of a product in html select.
+ *
+ * @param int $productID
+ * @param int $projectID
+ * @param int $branch
+ * @param string $number
+ * @param int $executionID
+ * @param string $from showImport
+ * @param string mode
+ * @access public
+ * @return void
+ */
+ public function ajaxGetExecutions($productID, $projectID = 0, $branch = 0, $number = '', $executionID = 0, $from = '', $mode = '')
+ {
+ if($this->app->tab == 'execution' and $this->session->execution)
+ {
+ $execution = $this->loadModel('execution')->getByID($this->session->execution);
+ if($execution->type == 'kanban') $projectID = $execution->project;
+ }
+
+ if($projectID) $project = $this->loadModel('project')->getById($projectID);
+ $mode .= ($from == 'bugToTask' or empty($this->config->CRExecution)) ? 'noclosed' : '';
+ $mode .= !$projectID ? ',multiple' : '';
+ $executions = $from == 'showImport' ? $this->product->getAllExecutionPairsByProduct($productID, $branch, $projectID) : $this->product->getExecutionPairsByProduct($productID, $branch, 'id_desc', $projectID, $mode);
+ if($this->app->getViewType() == 'json') return print(json_encode($executions));
+
+ if($number === '')
+ {
+ $event = $from == 'bugToTask' ? '' : " onchange='loadExecutionRelated(this.value)'";
+ $datamultiple = !empty($project) ? "data-multiple={$project->multiple}" : '';
+ return print(html::select('execution', array('' => '') + $executions, $executionID, "class='form-control' $datamultiple $event"));
+ }
+ else
+ {
+ $executions = empty($executions) ? array('' => '') : $executions;
+ $executionsName = $from == 'showImport' ? "execution[$number]" : "executions[$number]";
+ $misc = $from == 'showImport' ? "class='form-control' onchange='loadImportExecutionRelated(this.value, $number)'" : "class='form-control' onchange='loadExecutionBuilds($productID, this.value, $number)'";
+ return print(html::select($executionsName, $executions, '', $misc));
+ }
+ }
+
+ /**
+ * AJAX: get executions of a product in html select.
+ *
+ * @param int $productID
+ * @param int $projectID
+ * @param int $branch
+ * @param int $number
+ * @access public
+ * @return void
+ */
+ public function ajaxGetExecutionsByProject($productID, $projectID = 0, $branch = 0, $number = 0)
+ {
+ $noMultipleExecutionID = $projectID ? $this->loadModel('execution')->getNoMultipleID($projectID) : '';
+ $executions = $this->product->getExecutionPairsByProduct($productID, $branch, 'id_desc', $projectID, 'multiple,stagefilter');
+
+ $disabled = $noMultipleExecutionID ? "disabled='disabled'" : '';
+ $html = html::select("executions[{$number}]", array('' => '') + $executions, 0, "class='form-control' onchange='loadExecutionBuilds($productID, this.value, $number)' $disabled");
+
+ if($noMultipleExecutionID) $html .= html::hidden("executions[{$number}]", $noMultipleExecutionID, "id=executions{$number}");
+
+ return print($html);
+ }
+
+ /**
+ * AJAX: get plans of a product in html select.
+ *
+ * @param int $productID
+ * @param int $planID
+ * @param bool $needCreate
+ * @param string $expired
+ * @param string $param
+ * @access public
+ * @return void
+ */
+ public function ajaxGetPlans($productID, $branch = 0, $planID = 0, $fieldID = '', $needCreate = false, $expired = '', $param = '')
+ {
+ $param = strtolower($param);
+ if(strpos($param, 'forstory') === false)
+ {
+ $plans = $this->loadModel('productplan')->getPairs($productID, empty($branch) ? 'all' : $branch, $expired, strpos($param, 'skipparent') !== false);
+ }
+ else
+ {
+ $plans = $this->loadModel('productplan')->getPairsForStory($productID, $branch == '0' ? 'all' : $branch, $param);
+ }
+ $field = $fieldID !== '' ? "plans[$fieldID]" : 'plan';
+ $multiple = strpos($param, 'multiple') === false ? '' : 'multiple';
+ $output = html::select($field, $plans, $planID, "class='form-control chosen' $multiple");
+
+ if($branch == 0 and strpos($param, 'edit') and (strpos($param, 'forstory') === false)) $output = html::select($field, $plans, $planID, "class='form-control chosen' multiple");
+
+ if(count($plans) == 1 and $needCreate and $needCreate !== 'false')
+ {
+ $output .= "";
+ $output .= html::a($this->createLink('productplan', 'create', "productID=$productID&branch=$branch", '', true), "", '', "class='btn btn-icon' data-toggle='modal' data-type='iframe' data-width='95%' title='{$this->lang->productplan->create}'");
+ $output .= '
';
+ $output .= "";
+ $output .= html::a("javascript:void(0)", "", '', "class='btn btn-icon refresh' data-toggle='tooltip' title='{$this->lang->refresh}' onclick='loadProductPlans($productID)'");
+ $output .= '
';
+ }
+ echo $output;
+ }
+
+ /**
+ * Ajax get product lines.
+ *
+ * @param int $programID
+ * @param int $productID
+ * @access public
+ * @return void
+ */
+ public function ajaxGetLine($programID, $productID = 0)
+ {
+ $lines = array();
+ if(empty($productID) or $programID) $lines = $this->product->getLinePairs($programID);
+
+ if($productID) return print(html::select("lines[$productID]", array('' => '') + $lines, '', "class='form-control picker-select'"));
+ if(!$productID) return print(html::select('line', array('' => '') + $lines, '', "class='form-control picker-select'"));
+ }
+
+ /**
+ * Ajax get reviewers.
+ *
+ * @param int $productID
+ * @param int $storyID
+ * @access public
+ * @return void
+ */
+ public function ajaxGetReviewers($productID, $storyID = 0)
+ {
+ /* Get product reviewers. */
+ $product = $this->product->getByID($productID);
+ $productReviewers = $product->reviewer;
+ if(!$productReviewers and $product->acl != 'open') $productReviewers = $this->loadModel('user')->getProductViewListUsers($product, '', '', '', '');
+
+ $storyReviewers = '';
+ if($storyID)
+ {
+ $story = $this->loadModel('story')->getByID($storyID);
+ $storyReviewers = $this->story->getReviewerPairs($story->id, $story->version);
+ $storyReviewers = implode(',', array_keys($storyReviewers));
+ }
+
+ $reviewers = $this->loadModel('user')->getPairs('noclosed|nodeleted', $storyReviewers, 0, $productReviewers);
+
+ echo html::select("reviewer[]", $reviewers, $storyReviewers, "class='form-control chosen' multiple");
+ }
+
+ /**
+ * Drop menu page.
+ *
+ * @param int $productID
+ * @param string $module
+ * @param string $method
+ * @param string $extra
+ * @param string $from
+ * @access public
+ * @return void
+ */
+ public function ajaxGetDropMenu(string $productID, string $module, string $method, string $extra = '', string $from = '')
+ {
+ $productID = (int)$productID;
+ $shadow = 0;
+ if($from == 'qa')
+ {
+ $shadow = 'all';
+ $this->app->loadConfig('qa');
+ foreach($this->config->qa->menuList as $menu) $this->lang->navGroup->$menu = 'qa';
+ }
+
+ $programProducts = array();
+
+ if($this->app->tab == 'project')
+ {
+ $products = $this->product->getProducts($this->session->project);
+ }
+ elseif($this->app->tab == 'feedback')
+ {
+ $products = $this->loadModel('feedback')->getGrantProducts(false);
+ }
+ else
+ {
+ $products = $this->product->getList(0, 'all', 0, 0, $shadow);
+ }
+
+ $programProducts = array();
+ foreach($products as $product) $programProducts[$product->program][] = $product;
+
+ $this->view->link = $this->product->getProductLink($module, $method, $extra);
+ $this->view->productID = $productID;
+ $this->view->module = $module;
+ $this->view->method = $method;
+ $this->view->extra = $extra;
+ $this->view->products = $programProducts;
+ $this->view->projectID = $this->app->tab == 'project' ? $this->session->project : 0;
+ $this->view->programs = $this->loadModel('program')->getPairs(true);
+ $this->view->lines = $this->product->getLinePairs();
+ $this->display();
+ }
+
+ /**
+ * Set product id to session in ajax
+ *
+ * @param int $productID
+ * @access public
+ * @return void
+ */
+ public function ajaxSetState(string $productID)
+ {
+ $this->session->set('product', (int)$productID, $this->app->tab);
+ $this->send(array('result' => 'success', 'productID' => $this->session->product));
+ }
}
diff --git a/module/product/model.php b/module/product/model.php
index 49939c64aa..9f076efcb1 100755
--- a/module/product/model.php
+++ b/module/product/model.php
@@ -252,9 +252,9 @@ class productModel extends model
*
* @param int $productID
* @access public
- * @return object
+ * @return object|false
*/
- public function getById($productID)
+ public function getByID(int $productID): object|false
{
if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getProduct();
$product = $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch();
@@ -688,48 +688,37 @@ class productModel extends model
* Update a product.
*
* @param int $productID
+ * @param object $product
+ * @param string $uid
* @access public
- * @return array
+ * @return array|false
*/
- public function update($productID)
+ public function update(int $productID, object $product, string $uid = ''): array|false
{
- $productID = (int)$productID;
$oldProduct = $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch();
- $product = fixer::input('post')
- ->add('id', $productID)
- ->callFunc('name', 'trim')
- ->setDefault('line', 0)
- ->setDefault('whitelist', '')
- ->setDefault('reviewer', '')
- ->join('whitelist', ',')
- ->join('reviewer', ',')
- ->stripTags($this->config->product->editor->edit['id'], $this->config->allowedTags)
- ->remove('uid,changeProjects,contactListMenu')
- ->get();
-
$this->lang->error->unique = $this->lang->error->repeat;
- $product = $this->loadModel('file')->processImgURL($product, $this->config->product->editor->edit['id'], $this->post->uid);
- $programID = isset($product->program) ? $product->program : $oldProduct->program;
- $this->dao->update(TABLE_PRODUCT)->data($product)->autoCheck()
+ $this->dao->update(TABLE_PRODUCT)->data($product, 'uid,changeProjects,contactListMenu')->autoCheck()
->batchCheck($this->config->product->edit->requiredFields, 'notempty')
- ->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'")
+ ->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())
- {
- $this->file->updateObjectID($this->post->uid, $productID, 'product');
- $whitelist = explode(',', $product->whitelist);
- $this->loadModel('personnel')->updateWhitelist($whitelist, 'product', $productID);
- if($product->acl != 'open') $this->loadModel('user')->updateUserView($productID, 'product');
- if($product->type == 'normal' and $oldProduct->type != 'normal') $this->loadModel('branch')->unlinkBranch4Project($productID);
- if($product->type != 'normal' and $oldProduct->type == 'normal') $this->loadModel('branch')->linkBranch4Project($productID);
+ if(dao::isError()) return false;
- return common::createChanges($oldProduct, $product);
- }
+ /* Update objectID field of file recode, that upload by editor. */
+ $this->loadModel('file')->updateObjectID($uid, $productID, 'product');
+
+ $whitelist = explode(',', $product->whitelist);
+ $this->loadModel('personnel')->updateWhitelist($whitelist, 'product', $productID);
+ if($oldProduct->acl != $product->acl and $product->acl != 'open') $this->loadModel('user')->updateUserView($productID, 'product');
+
+ if($product->type == 'normal' and $oldProduct->type != 'normal') $this->loadModel('branch')->unlinkBranch4Project($productID);
+ if($product->type != 'normal' and $oldProduct->type == 'normal') $this->loadModel('branch')->linkBranch4Project($productID);
+
+ return common::createChanges($oldProduct, $product);
}
/**
diff --git a/module/product/tao.php b/module/product/tao.php
index a779efa96d..0b0a5a8faf 100644
--- a/module/product/tao.php
+++ b/module/product/tao.php
@@ -493,4 +493,17 @@ class productTao extends productModel
if(dao::isError())return false;
return (int)$this->dao->lastInsertID();
}
+
+ /**
+ * 从module表中查询所有产品线。
+ * Get all product lines from module table.
+ * TODO move to the MODULE module.
+ *
+ * @access protected
+ * @return array
+ */
+ protected function getProductLinesTODO(): array
+ {
+ return $this->dao->select('*')->from(TABLE_MODULE)->where('type')->eq('line')->andWhere('deleted')->eq(0)->orderBy('`order` asc')->fetchAll();
+ }
}
diff --git a/module/product/test/model/getbyid.php b/module/product/test/model/getbyid.php
index 232b55713d..b7da40c1e4 100755
--- a/module/product/test/model/getbyid.php
+++ b/module/product/test/model/getbyid.php
@@ -3,6 +3,8 @@
include dirname(__FILE__, 5) . "/test/lib/init.php";
include dirname(__FILE__, 2) . '/product.class.php';
+zdTable('product')->gen(10);
+
/**
title=productModel->getById();
@@ -18,13 +20,13 @@ pid=1
*/
-$productIDList = array('1', '2', '3', '4', '5', '1000001');
+$productIdList = array(1, 2, 3, 4, 5, 1000001);
$product = new productTest('admin');
-r($product->getByIdTest($productIDList[0])) && p('name,code,type,PO,QD,RD') && e('正常产品1,code1,normal,po1,test1,dev1'); // 测试获取产品1的信息
-r($product->getByIdTest($productIDList[1])) && p('name,code,type,PO,QD,RD') && e('正常产品2,code2,normal,po2,test2,dev2'); // 测试获取产品2的信息
-r($product->getByIdTest($productIDList[2])) && p('name,code,type,PO,QD,RD') && e('正常产品3,code3,normal,po3,test3,dev3'); // 测试获取产品3的信息
-r($product->getByIdTest($productIDList[3])) && p('name,code,type,PO,QD,RD') && e('正常产品4,code4,normal,po4,test4,dev4'); // 测试获取产品4的信息
-r($product->getByIdTest($productIDList[4])) && p('name,code,type,PO,QD,RD') && e('正常产品5,code5,normal,po5,test5,dev5'); // 测试获取产品5的信息
-r($product->getByIdTest($productIDList[5])) && p('name,code,type,PO,QD,RD') && e('0'); // 测试获取不存在产品的信息
\ No newline at end of file
+r($product->getByIdTest($productIdList[0])) && p('name,code,type,PO,QD,RD') && e('正常产品1,code1,normal,po1,test1,dev1'); // 测试获取产品1的信息
+r($product->getByIdTest($productIdList[1])) && p('name,code,type,PO,QD,RD') && e('正常产品2,code2,normal,po2,test2,dev2'); // 测试获取产品2的信息
+r($product->getByIdTest($productIdList[2])) && p('name,code,type,PO,QD,RD') && e('正常产品3,code3,normal,po3,test3,dev3'); // 测试获取产品3的信息
+r($product->getByIdTest($productIdList[3])) && p('name,code,type,PO,QD,RD') && e('正常产品4,code4,normal,po4,test4,dev4'); // 测试获取产品4的信息
+r($product->getByIdTest($productIdList[4])) && p('name,code,type,PO,QD,RD') && e('正常产品5,code5,normal,po5,test5,dev5'); // 测试获取产品5的信息
+r($product->getByIdTest($productIdList[5])) && p() && e('0'); // 测试获取不存在产品的信息
diff --git a/module/product/test/model/update.php b/module/product/test/model/update.php
index 2f47f24144..1fa29b8925 100755
--- a/module/product/test/model/update.php
+++ b/module/product/test/model/update.php
@@ -3,36 +3,36 @@
include dirname(__FILE__, 5) . "/test/lib/init.php"; su('admin');
include dirname(__FILE__, 2) . '/product.class.php';
+zdTable('product')->gen(50);
+
/**
title=测试productModel->update();
cid=1
pid=1
-测试更新产品名称 >> name,正常产品2,john
-测试更新产品代号 >> code,code2,newcode1
-测试更新产品名称和代号 >> name,john,jack;code,newcode1,newcode2
-测试不更改产品名称 >> 没有数据更新
-测试不更改产品代号 >> 没有数据更新
-测试同一项目集下产品名称不能重复 >> 『产品名称』已经有『jack』这条记录了。
-测试同一项目集下产品代号不能重复 >> 『产品代号』已经有『newcode2』这条记录了。
-
*/
$product = new productTest('admin');
-$t_upname = array('name' => 'john');
-$t_upid = array('code' => 'newcode1');
-$t_idname = array('name' => 'jack', 'code' => 'newcode2');
-$t_unname = array('name' => 'jack');
-$t_unid = array('code' => 'newcode2');
-$t_repeaproduct = array('name' => 'jack');
-$t_repeatid = array('code' => 'newcode2');
+$updateName = array('name' => 'john');
+$updateCode = array('code' => 'newcode1');
+$updateType = array('type' => 'branch');
+$revertType = array('type' => 'normal');
+$updateAcl = array('acl' => 'private');
+$updateWhitelist = array('whitelist' => ',test1,dev1,pm1');
+$uniqueName = array('name' => 'john');
+$uniqueCode = array('code' => 'newcode1');
+$repeatProduct = array('name' => 'john');
+$repeatCode = array('code' => 'newcode1');
-r($product->updateObject('product', 2, $t_upname)) && p('0:field,old,new') && e('name,正常产品2,john'); // 测试更新产品名称
-r($product->updateObject('product', 2, $t_upid)) && p('0:field,old,new') && e('code,code2,newcode1'); // 测试更新产品代号
-r($product->updateObject('product', 2, $t_idname)) && p('0:field,old,new;1:field,old,new') && e('name,john,jack;code,newcode1,newcode2'); // 测试更新产品名称和代号
-r($product->updateObject('product', 2, $t_unname)) && p() && e('没有数据更新'); // 测试不更改产品名称
-r($product->updateObject('product', 2, $t_unid)) && p() && e('没有数据更新'); // 测试不更改产品代号
-r($product->updateObject('product', 13, $t_repeaproduct)) && p('name:0') && e('『产品名称』已经有『jack』这条记录了。'); // 测试同一项目集下产品名称不能重复
-r($product->updateObject('product', 13, $t_repeatid)) && p('code:0') && e('『产品代号』已经有『newcode2』这条记录了。'); // 测试同一项目集下产品代号不能重复
+r($product->updateObject(2, $updateName)) && p('0:field,old,new') && e('name,正常产品2,john'); // 测试更新产品名称
+r($product->updateObject(2, $updateCode)) && p('0:field,old,new') && e('code,code2,newcode1'); // 测试更新产品代号
+r($product->updateObject(2, $updateType)) && p('0:field,old,new') && e('type,normal,branch'); // 测试更新产品类型
+r($product->updateObject(2, $revertType)) && p('0:field,old,new') && e('type,branch,normal'); // 测试还原产品类型
+r($product->updateObject(2, $updateAcl)) && p('0:field,old,new') && e('acl,open,private'); // 测试不更改产品名称
+r($product->updateObject(2, $updateWhitelist))&& p('0:field/new', '/') && e('whitelist/,test1,dev1,pm1'); // 测试不更改产品名称
+r($product->updateObject(2, $uniqueName)) && p() && e('0'); // 测试不更改产品名称
+r($product->updateObject(2, $uniqueCode)) && p() && e('0'); // 测试不更改产品代号
+r($product->updateObject(13, $repeatProduct)) && p('name:0') && e('『产品名称』已经有『john』这条记录了。'); // 测试同一项目集下产品名称不能重复
+r($product->updateObject(13, $repeatCode)) && p('code:0') && e('『产品代号』已经有『newcode1』这条记录了。'); // 测试同一项目集下产品代号不能重复
diff --git a/module/product/test/product.class.php b/module/product/test/product.class.php
index 00ff19955a..f00a2af44b 100644
--- a/module/product/test/product.class.php
+++ b/module/product/test/product.class.php
@@ -335,33 +335,21 @@ class productTest
/**
* Test update a product.
*
- * @param string $module
* @param int $objectID
- * @param array $param
+ * @param array $data
* @access public
- * @return array
+ * @return array|string
*/
- public function updateObject($module, $objectID, $param = array())
+ public function updateObject(int $objectID, array $data = array()): array|string
{
global $tester;
- $objectModel = $tester->loadModel($module);
+ $objectModel = $tester->loadModel('product');
- $object = $objectModel->getById($objectID);
- foreach($object as $field => $value)
- {
- if(in_array($field, array_keys($param)))
- {
- $_POST[$field] = $param[$field];
- }
- else
- {
- $_POST[$field] = $value;
- }
- }
+ $oldProduct = $objectModel->dao->select('*')->from(TABLE_PRODUCT)->where('id')->eq($objectID)->fetch();
- $change = $objectModel->update($objectID);
- if($change == array()) $change = '没有数据更新';
- unset($_POST);
+ $newProduct = clone $oldProduct;
+ foreach($data as $field => $value) $newProduct->$field = $value;
+ $change = $objectModel->update($objectID, $newProduct);
if(dao::isError())
{
@@ -399,9 +387,9 @@ class productTest
*
* @param int $productID
* @access public
- * @return object
+ * @return object|array
*/
- public function getByIdTest($productID)
+ public function getByIdTest(int $productID): object|array|false
{
$object = $this->objectModel->getById($productID);
diff --git a/module/product/ui/create.html.php b/module/product/ui/create.html.php
index 49f2232ac1..057df83c4e 100644
--- a/module/product/ui/create.html.php
+++ b/module/product/ui/create.html.php
@@ -1,13 +1,178 @@
buildForm($fields);
-$form->buildFormAction();
+/*
+ ======= Attention ======
-$content = block();
-$content->from = $form;
+ This file is generated by zin-tool, you should check the following to-do list.
-$page = page('create');
-$page->right->content = $content;
-$page->x();
+ + Familiar with the use of these widgets in zin: .
+ + Check the following variables which used in widgets: $programOptions, $lineOptions, $POOptions, $QDOptions, $RDOptions, $reviewerOptions, $typeOptions, $aclOptions, $whitelistOptions.
+ + Check the origin code in module/product/view/create.html.php, and ensure that all features have been implemented.
+ + Check the origin js code in module/product/js/common.js and module/product/js/create.js
+ + Check the origin css code in module/product/css/common.css and module/product/css/create.css
+ + Remove the comments which starts with "zin:"
+ + Test according to the new design draft and the original implementation
+ */
+
+namespace zin;
+
+/* ====== Preparing and processing page data ====== */
+
+/* zin: Set variables to define picker options for form */
+$programOptions = array();
+$lineOptions = array();
+$POOptions = array();
+$QDOptions = array();
+$RDOptions = array();
+$reviewerOptions = array();
+$typeOptions = array(array('value' => "normal", 'text' => "正常"), array('value' => "branch", 'text' => "多分支(适用于客户定制场景)"), array('value' => "platform", 'text' => "多平台(适用于跨平台应用开发,比如IOS、安卓、PC端等)"));
+$aclOptions = array(array('checked' => true, 'value' => "private", 'disabled' => false, 'text' => "私有(产品相关负责人、所属项目集的负责人及干系人、相关联项目的团队成员和干系人可访问)"), array('checked' => false, 'value' => "open", 'disabled' => false, 'text' => "公开(有产品视图权限,即可访问)"));
+$whitelistOptions = array();
+
+
+/* ====== Define the page structure with zin widgets ====== */
+
+/* zin: Define the form in main content */
+formPanel
+(
+ formGroup
+ (
+ set::width("1/3"),
+ set::name("program"),
+ set::label("项目集"),
+ set::control("picker"),
+ set::items($programOptions)
+ ),
+ formRow
+ (
+ set::hidden(true),
+ formGroup
+ (
+ set::width("1/3"),
+ set::name("line"),
+ set::label("产品线"),
+ set::control("picker"),
+ set::items($lineOptions)
+ )
+ ),
+ formGroup
+ (
+ set::width("1/3"),
+ set::name("name"),
+ set::label("产品名称"),
+ set::required(true),
+ set::control("text")
+ ),
+ formGroup
+ (
+ set::width("1/3"),
+ set::name("PO"),
+ set::label("产品负责人"),
+ set::control("picker"),
+ set::items($POOptions)
+ ),
+ formGroup
+ (
+ set::width("1/3"),
+ set::name("QD"),
+ set::label("测试负责人"),
+ set::control("picker"),
+ set::items($QDOptions)
+ ),
+ formGroup
+ (
+ set::width("1/3"),
+ set::name("RD"),
+ set::label("发布负责人"),
+ set::control("picker"),
+ set::items($RDOptions)
+ ),
+ formGroup
+ (
+ set::width("1/3"),
+ set::name("reviewer[]"),
+ set::label("评审人"),
+ set::control(["type" =>"picker","multiple"=>true]),
+ set::id("reviewer"),
+ set::items($reviewerOptions)
+ ),
+ formGroup
+ (
+ set::width("1/3"),
+ set::name("type"),
+ set::label("产品类型"),
+ set::value("normal"),
+ set::control("picker"),
+ set::items($typeOptions)
+ ),
+ formGroup
+ (
+ set::width("2/3"),
+ set::label("产品描述"),
+ inputGroup
+ (
+ control(set(array
+ (
+ 'id' => "title",
+ 'value' => "",
+ 'disabled' => false,
+ 'type' => "text"
+ ))),
+ "公共",
+ btn(set(array
+ (
+ 'type' => "btn",
+ 'text' => "保存",
+ 'class' => "input-group-btn"
+ )))
+ )
+ ),
+ formGroup
+ (
+ set::width("2/3"),
+ set::name("acl"),
+ set::label("访问控制"),
+ set::control("radioList"),
+ set::items($aclOptions)
+ ),
+ formGroup
+ (
+ set::width("1/3"),
+ set::label("白名单"),
+ inputGroup
+ (
+ control(set(array
+ (
+ 'name' => "whitelist[]",
+ 'id' => "whitelist",
+ 'value' => NULL,
+ 'disabled' => false,
+ 'type' => "picker",
+ 'items' => $whitelistOptions,
+ 'multiple' => true
+ ))),
+ btn(set(array
+ (
+ 'type' => "btn",
+ 'icon' => "cog",
+ 'text' => "",
+ 'class' => "input-group-btn"
+ ))),
+ btn(set(array
+ (
+ 'type' => "btn",
+ 'icon' => "refresh",
+ 'text' => "",
+ 'class' => "input-group-btn"
+ )))
+ )
+ )
+);
+
+
+/* ====== Render page ====== */
+
+render();
diff --git a/module/product/zen.php b/module/product/zen.php
index 83fc7bcd8c..aaaf765743 100644
--- a/module/product/zen.php
+++ b/module/product/zen.php
@@ -40,20 +40,31 @@ class productZen extends product
* @access protected
* @return void
*/
- protected function setCreateMenu(int $programID): void
+ protected function setCreateMenu(int $programID)
{
if($this->app->tab == 'program') $this->loadModel('program')->setMenu($programID);
if($this->app->tab == 'doc') unset($this->lang->doc->menu->product['subMenu']);
if($this->app->getViewType() != 'mhtml') return;
- if($this->app->rawModule == 'projectstory' and $this->app->rawMethod == 'story')
- {
- $this->loadModel('project')->setMenu();
- return;
- }
+ if($this->app->rawModule == 'projectstory' and $this->app->rawMethod == 'story') return $this->loadModel('project')->setMenu();
$this->product->setMenu();
}
+ /**
+ * 为编辑产品设置导航数据,主要是替换占位符。
+ * Set menu for edit product page.
+ *
+ * @param int $productID
+ * @param int $programID
+ * @access protected
+ * @return void
+ */
+ protected function setEditMenu(int $productID, int $programID)
+ {
+ if($programID) return $this->loadModel('program')->setMenu($programID);
+ $this->product->setMenu($productID);
+ }
+
/**
* 为showErrorNone方法,根据不同模块,设置不同的二级或三级导航配置。
* Set menu for showErrorNone page.
@@ -64,17 +75,13 @@ class productZen extends product
* @access protected
* @return void
*/
- protected function setShowErrorNoneMenu(string $moduleName, string $activeMenu, int $objectID): void
+ protected function setShowErrorNoneMenu(string $moduleName, string $activeMenu, int $objectID)
{
- if($this->app->getViewType() == 'mhtml')
- {
- $this->product->setMenu();
- return;
- }
+ if($this->app->getViewType() == 'mhtml') return $this->product->setMenu();
- if($moduleName == 'qa') $this->setShowErrorNoneMenu4QA($activeMenu);
- if($moduleName == 'project') $this->setShowErrorNoneMenu4Project($activeMenu, $objectID);
- if($moduleName == 'execution') $this->setShowErrorNoneMenu4Execution($activeMenu, $objectID);
+ if($moduleName == 'qa') return $this->setShowErrorNoneMenu4QA($activeMenu);
+ if($moduleName == 'project') return $this->setShowErrorNoneMenu4Project($activeMenu, $objectID);
+ if($moduleName == 'execution') return $this->setShowErrorNoneMenu4Execution($activeMenu, $objectID);
}
/**
@@ -85,7 +92,7 @@ class productZen extends product
* @access private
* @return void
*/
- private function setShowErrorNoneMenu4QA(string $activeMenu): void
+ private function setShowErrorNoneMenu4QA(string $activeMenu)
{
$this->loadModel('qa')->setMenu(array(), 0);
$this->view->moduleName = 'qa';
@@ -106,7 +113,7 @@ class productZen extends product
* @access private
* @return void
*/
- private function setShowErrorNoneMenu4Project(string $activeMenu, int $projectID): void
+ private function setShowErrorNoneMenu4Project(string $activeMenu, int $projectID)
{
$this->loadModel('project')->setMenu($projectID);
$this->app->rawModule = $activeMenu;
@@ -132,7 +139,7 @@ class productZen extends product
* @access private
* @return void
*/
- private function setShowErrorNoneMenu4Execution(string $activeMenu, int $executionID): void
+ private function setShowErrorNoneMenu4Execution(string $activeMenu, int $executionID)
{
$this->loadModel('execution')->setMenu($executionID);
$this->app->rawModule = $activeMenu;
@@ -167,13 +174,14 @@ class productZen extends product
* 获取创建产品页面的表单配置。
* Get form fields for create.
*
- * @param int $programID
+ * @param int $programID
+ * @param array $fields
* @access private
* @return array
*/
- private function getFormFields4Create(int $programID = 0): array
+ private function getFormFields4Create(int $programID = 0, array $fields = array()): array
{
- $fields = $this->config->product->form->create;
+ if(empty($fields)) $fields = $this->config->product->form->create;
$this->loadModel('user');
$poUsers = $this->user->getPairs('nodeleted|pofirst|noclosed');
@@ -185,7 +193,7 @@ class productZen extends product
{
if(isset($attr['options']) and $attr['options'] == 'users') $fields[$field]['options'] = $users;
$fields[$field]['name'] = $field;
- $fields[$field]['title'] = $this->lang->product->$field;
+ $fields[$field]['title'] = zget($this->lang->product, $field);
}
$fields['program']['options'] = array('') + $this->loadModel('program')->getTopPairs('', 'noclosed');
@@ -199,6 +207,37 @@ class productZen extends product
return $fields;
}
+ /**
+ * 获取编辑产品页面的表单配置。
+ * Get form fields for create.
+ *
+ * @param object $product
+ * @access private
+ * @return array
+ */
+ private function getFormFields4Edit(object $product): array
+ {
+ $programID = (int)$product->program;
+ $fields = $this->getFormFields4Create($programID, $this->config->product->form->edit);
+
+ /* 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)
+ {
+ $program = $this->program->getByID($programID);
+ $fields['program']['options'] += array($programID => $program->name);
+ }
+
+ /* Set default value by product. */
+ foreach($fields as $field => $attr)
+ {
+ if(isset($product->{$field})) $fields[$field]['default'] = $product->{$field};
+ }
+
+ return $fields;
+ }
+
/**
* Get product lines and product lines of program.
*
@@ -208,8 +247,7 @@ class productZen extends product
protected function getProductLines(): array
{
/* Get all product lines. */
- /* TODO use model of module. */
- $productLines = $this->dao->select('*')->from(TABLE_MODULE)->where('type')->eq('line')->andWhere('deleted')->eq(0)->orderBy('`order` asc')->fetchAll();
+ $productLines = $this->product->getProductLinesTODO();
/* Collect product lines of program lines. */
$programLines = array();
@@ -231,19 +269,37 @@ class productZen extends product
* @access protected
* @return void
*/
- protected function buildCreateForm(int $programID = 0, string $extra = ''): void
+ protected function buildCreateForm(int $programID = 0, string $extra = '')
{
$this->view->title = $this->lang->product->create;
$this->view->gobackLink = $this->getBackLink4Create($extra);
$this->view->programID = $programID;
$this->view->fields = $this->getFormFields4Create($programID);
- unset($this->lang->product->typeList['']);
+ unset($this->lang->product->typeList['']);
$this->display();
}
/**
- * 追加创建信息,处理白名单、评审者、项目集字段,还有富文本内容处理。
+ * 构建编辑产品页面数据。
+ * Build form fields for edit.
+ *
+ * @param object $product
+ * @access protected
+ * @return void
+ */
+ protected function buildEditForm(object $product)
+ {
+ $this->view->title = $this->lang->product->edit . $this->lang->colon . $product->name;
+ $this->view->product = $product;
+ $this->view->fields = $this->getFormFields4Edit($product);
+
+ unset($this->lang->product->typeList['']);
+ $this->display();
+ }
+
+ /**
+ * 追加创建信息,处理白名单、项目集字段,还有富文本内容处理。
* Prepare data for create.
*
* @param object $data
@@ -262,11 +318,28 @@ class productZen extends product
->stripTags($this->config->product->editor->create['id'], $this->config->allowedTags)
->remove('uid,newLine,lineName,contactListMenu')
->get();
- if(empty($product)) return false;
- $product = $this->loadModel('file')->processImgURL($product, $this->config->product->editor->create['id'], $uid);
+ return $this->loadModel('file')->processImgURL($product, $this->config->product->editor->create['id'], $uid);
+ }
- return $product;
+ /**
+ * 处理白名单和富文本内容。
+ * Prepare data for edit.
+ *
+ * @param object $data
+ * @param string $acl
+ * @param string $uid
+ * @access protected
+ * @return object
+ */
+ protected function prepareEditExtras(object $data, string $acl, string $uid): object
+ {
+ $product = fixer::input('post')->setIF($acl == 'open', 'whitelist', '')
+ ->stripTags($this->config->product->editor->edit['id'], $this->config->allowedTags)
+ ->remove('uid,changeProjects,contactListMenu')
+ ->get();
+
+ return $this->loadModel('file')->processImgURL($product, $this->config->product->editor->edit['id'], $uid);
}
/**
@@ -280,8 +353,9 @@ class productZen extends product
* @access protected
* @return void
*/
- protected function responseAfterCreate(int $productID, object $product, string $uid, string $lineName = ''): void
+ protected function responseAfterCreate(int $productID, object $product, string $uid, string $lineName = '')
{
+ /* Fix order and line fields for product. */
$fixData = new stdclass();
$fixData->order = $productID * 5;
if(!empty($lineName))
@@ -289,27 +363,45 @@ class productZen extends product
$lineID = $this->product->createLine((int)$product->program, $lineName);
if($lineID) $fixData->line = $lineID;
}
-
$this->dao->update(TABLE_PRODUCT)->data($fixData)->where('id')->eq($productID)->exec();
- $this->file->updateObjectID($uid, $productID, 'product');
+ /* Update and create linked data. */
+ $this->loadModel('file')->updateObjectID($uid, $productID, 'product');
+ $this->product->createMainLib($productID);
if($product->whitelist) $this->loadModel('personnel')->updateWhitelist(explode(',', $product->whitelist), 'product', $productID);
if($product->acl != 'open') $this->loadModel('user')->updateUserView($productID, 'product');
- $this->product->createMainLib($productID);
-
$this->loadModel('action')->create('product', $productID, 'opened');
$message = $this->executeHooks($productID);
if($message) $this->lang->saveSuccess = $message;
- if($this->viewType == 'json')
+ if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $productID));
+ $this->sendCreateLocate($productID, (int)$product->program);
+ }
+
+ /**
+ * 成功更新产品数据后,其他的额外操作。
+ * Process after edit product.
+ *
+ * @param int $productID
+ * @param int $programID
+ * @param array $changes
+ * @access protected
+ * @return void
+ */
+ protected function responseAfterEdit(int $productID, int $programID, array $changes)
+ {
+ if($changes)
{
- $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $productID));
- return;
+ $actionID = $this->loadModel('action')->create('product', $productID, 'edited');
+ $this->action->logHistory($actionID, $changes);
}
- $this->sendCreateLocate($productID, (int)$product->program);
+ $message = $this->executeHooks($productID);
+ if($message) $this->lang->saveSuccess = $message;
+
+ return $this->sendCreateLocate($productID, $programID);
}
/**
@@ -321,7 +413,7 @@ class productZen extends product
* @access private
* @return void
*/
- private function sendCreateLocate(int $productID, int $programID): void
+ private function sendCreateLocate(int $productID, int $programID)
{
$tab = $this->app->tab;
$moduleName = $tab == 'program' ? 'program' : $this->moduleName;
@@ -334,13 +426,33 @@ class productZen extends product
}
/**
- * 输出创建产品产生的错误。
- * Send error for create.
+ * 编辑完成后,做页面跳转。
+ * Locate after edit product.
+ *
+ * @param int $productID
+ * @param int $programID
+ * @access private
+ * @return void
+ */
+ private function sendEditLocate(int $productID, int $programID)
+ {
+ $moduleName = $programID ? 'program' : 'product';
+ $methodName = $programID ? 'product' : 'view';
+ $param = $programID ? "programID=$programID" : "product=$productID";
+ $locate = $this->createLink($moduleName, $methodName, $param);
+
+ if(!$programID) $this->session->set('productList', $this->createLink('product', 'browse', $param), 'product');
+ return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $locate));
+ }
+
+ /**
+ * 输出数据库操作产生的错误。
+ * Send error for dao.
*
* @access protected
* @return void
*/
- protected function sendError4Create(): void
+ protected function sendDaoError()
{
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
}
diff --git a/module/productplan/model.php b/module/productplan/model.php
index 16d40746e6..3e6faad7ec 100644
--- a/module/productplan/model.php
+++ b/module/productplan/model.php
@@ -1058,7 +1058,7 @@ class productplanModel extends model
$this->loadModel('story');
$this->loadModel('action');
- $bugs = $this->loadModel('bug')->getByList($this->post->bugs);
+ $bugs = $this->loadModel('bug')->getByIdList($this->post->bugs);
foreach($this->post->bugs as $bugID)
{
if(!isset($bugs[$bugID])) continue;
diff --git a/module/project/config/form.php b/module/project/config/form.php
index 2f2bd837dd..e3eb4978a9 100644
--- a/module/project/config/form.php
+++ b/module/project/config/form.php
@@ -37,6 +37,9 @@ $config->project->form->edit['acl'] = array('type' => 'string', 'required
$config->project->form->edit['whitelist'] = array('type' => 'array', 'required' => false, 'default' => '', 'filter' => 'join');
$config->project->form->edit['auth'] = array('type' => 'array', 'required' => false, 'default' => '');
$config->project->form->edit['model'] = array('type' => 'string', 'required' => false, 'default' => '');
+$config->project->form->edit['plans'] = array('type' => 'array', 'required' => false, 'default' => '');
+$config->project->form->edit['products'] = array('type' => 'array', 'required' => false, 'default' => '');
+$config->project->form->edit['product'] = array('type' => 'array', 'required' => false, 'default' => '');
$config->project->form->start['realBegan'] = array('type' => 'date', 'required' => true, 'filter' => 'trim');
diff --git a/module/project/control.php b/module/project/control.php
index 1fdd60f7f6..754eff9d79 100755
--- a/module/project/control.php
+++ b/module/project/control.php
@@ -73,8 +73,7 @@ class project extends control
if(isset($fields['hasProduct'])) $fields['hasProduct'] = $projectLang->type;
- $involved = $this->cookie->involved ? $this->cookie->involved : 0;
- $projects = $this->project->getInfoList($status, $orderBy, '', $involved);
+ $projects = $this->project->getList($status, $orderBy);
$users = $this->loadModel('user')->getPairs('noletter');
$this->loadModel('product');
@@ -316,7 +315,7 @@ class project extends control
if($project->model == 'kanban' and $this->config->vision != 'lite')
{
/* Load pager and get kanban list. */
- $this->app->loadClass('pager', $static = true);
+ $this->app->loadClass('pager', true);
$pager = new pager($recTotal, $recPerPage, $pageID);
$kanbanList = $this->loadModel('execution')->getList($projectID, 'all', $browseType, 0, 0, 0, $pager);
@@ -370,7 +369,7 @@ class project extends control
$browseType = strtolower($browseType);
/* Load pager. */
- $this->app->loadClass('pager', $static = true);
+ $this->app->loadClass('pager', true);
$pager = new pager($recTotal, $recPerPage, $pageID);
$queryID = ($browseType == 'bysearch') ? (int)$param : 0;
@@ -509,9 +508,8 @@ class project extends control
* @param int $projectID
* @param string $from
* @access public
- * @return void
*/
- public function edit(string $projectID, string $from = ''): void
+ public function edit(string $projectID, string $from = '')
{
$this->loadModel('action');
$this->loadModel('custom');
@@ -520,10 +518,8 @@ class project extends control
$this->loadModel('program');
$this->loadModel('execution');
-
- $projectID = (int)$projectID;
- $project = $this->project->getByID($projectID);
- $programID = $project->parent;
+ $projectID = (int)$projectID;
+ $project = $this->project->getByID($projectID);
$this->project->setMenu($projectID);
if($project->model == 'kanban')
@@ -547,7 +543,7 @@ class project extends control
if($_POST)
{
- $postData = form::data($this->config->project->form->eidt);
+ $postData = form::data($this->config->project->form->edit);
$project = $this->projectZen->prepareEditExtras($postData);
$project->id = $projectID;
@@ -738,7 +734,7 @@ class project extends control
}
/* Load pager. */
- $this->app->loadClass('pager', $static = true);
+ $this->app->loadClass('pager', true);
$pager = new pager(0, 30, 1);
/* Check exist extend fields. */
@@ -867,8 +863,8 @@ class project extends control
$orderBy = $direction == 'next' ? 'date_desc' : 'date_asc';
/* Set the pager. */
- $this->app->loadClass('pager', $static = true);
- $pager = new pager($recTotal, $recPerPage = 50, $pageID = 1);
+ $this->app->loadClass('pager', true);
+ $pager = new pager($recTotal, 50, 1);
/* Set the user and type. */
$account = 'all';
@@ -936,7 +932,7 @@ class project extends control
if(!empty($project->model) and $project->model == 'kanban' and !(defined('RUN_MODE') and RUN_MODE == 'api')) return print(js::locate($this->createLink('project', 'index', "projectID=$projectID")));
/* Load pager and get tasks. */
- $this->app->loadClass('pager', $static = true);
+ $this->app->loadClass('pager', true);
$pager = new pager($recTotal, $recPerPage, $pageID);
$allExecution = $this->execution->getStatData($projectID, 'all');
@@ -1679,7 +1675,7 @@ class project extends control
* @access public
* @return void
*/
- public function editGroup($groupID): void
+ public function editGroup($groupID): mixed
{
$groupID = (int)$groupID;
$this->loadModel('group');
@@ -1934,8 +1930,8 @@ class project extends control
}
/**
- * 管理项目下的关联产品
- * Manage products.
+ * 管理项目的关联产品
+ * Manage products under project.
*
* @param string $projectID
* @param string $from project|program|programproject
@@ -1943,8 +1939,9 @@ class project extends control
* @access public
* @return void
*/
- public function manageProducts(string $projectID, $from = 'project'): void
+ public function manageProducts(string $projectID, $from = 'project'): mixed
{
+ /* Access the nonProduct project alter tips. */
$projectID = (int)$projectID;
$project = $this->project->getById($projectID);
if(!$project->hasProduct) return print(js::error($this->lang->project->cannotManageProducts) . js::locate('back'));
@@ -1961,6 +1958,7 @@ class project extends control
return $this->send(array('result' => 'fail', 'message' => dao::getError()));
}
+ /* Update linked products. */
$this->projectZen->mergeProducts($projectID, $project, $executionIDs, $postData);
$locateLink = inLink('manageProducts', "projectID=$projectID");
@@ -1968,9 +1966,10 @@ class project extends control
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $locateLink));
}
+ /* Set menu. */
if($this->app->tab == 'program')
{
- $this->program->setMenu($project->parent);
+ $this->loadModel('program')->setMenu($project->parent);
}
else if($this->app->tab == 'project')
{
@@ -1978,7 +1977,12 @@ class project extends control
}
$this->projectZen->dealLinkProduct($projectID, $project);
- $this->projectZen->buildMangedProductForm($projectID, $project, $executions);
+
+ $this->view->title = $this->lang->project->manageProducts . $this->lang->colon . $project->name;
+ $this->view->project = $project;
+ $this->view->executions = $executions;
+ $this->view->branches = $this->project->getBranchesByProject($projectID);
+ $this->display();
}
/**
@@ -1993,7 +1997,7 @@ class project extends control
* @access public
* @return void
*/
- public function ajaxGetExecutions(string $projectID, int $executionID = 0, string $mode = '', string $type = 'all'): void
+ public function ajaxGetExecutions(string $projectID, int $executionID = 0, string $mode = '', string $type = 'all'): mixed
{
$project = $this->project->getByID($projectID);
$disabled = $project->multiple ? '' : 'disabled';
diff --git a/module/project/model.php b/module/project/model.php
index 7284828fda..82aec9ecf3 100755
--- a/module/project/model.php
+++ b/module/project/model.php
@@ -47,10 +47,8 @@ class projectModel extends model
{
if(defined('TUTORIAL')) return true;
- echo(js::alert($this->lang->project->accessDenied));
$this->session->set('project', '');
-
- return print(js::locate(helper::createLink('project', 'index')));
+ return print(js::alert($this->lang->project->accessDenied) . js::locate(helper::createLink('project', 'index')));
}
/**
@@ -148,8 +146,8 @@ class projectModel extends model
*/
public function getMultiLinkedProducts($projectID)
{
- $linkedProducts = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->fetchPairs();
- $multiLinkedProducts = $this->dao->select('t3.id,t3.name')->from(TABLE_PROJECTPRODUCT)->alias('t1')
+ $linkedProducts = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->fetchPairs();
+ return $this->dao->select('t3.id,t3.name')->from(TABLE_PROJECTPRODUCT)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product = t3.id')
->where('t1.product')->in($linkedProducts)
@@ -158,8 +156,6 @@ class projectModel extends model
->andWhere('t2.deleted')->eq('0')
->andWhere('t3.deleted')->eq('0')
->fetchPairs('id', 'name');
-
- return $multiLinkedProducts;
}
/*
@@ -235,39 +231,27 @@ class projectModel extends model
}
/**
- * Get project info.
+ * 根据状态和和我参与的查询项目列表。
+ * Get project list by status and with my participation.
*
* @param string $status
* @param string $orderBy
+ * @param bool $involved
* @param int $pager
- * @param int $involved
* @access public
* @return array
*/
- public function getInfoList($status = 'undone', $orderBy = 'order_desc', $pager = null, $involved = 0)
+ public function getList(string $status = 'undone', string $orderBy = 'order_desc', bool $involved = false, object|null $pager = null): array
{
/* Init vars. */
- $projects = $this->loadModel('program')->getProjectList(0, $status, 0, $orderBy, $pager, 0, $involved);
+ $projects = $this->projectTao->fetchProjectList($status, $orderBy, $involved, $pager);
if(empty($projects)) return array();
$projectIdList = array_keys($projects);
- $teams = $this->dao->select('t1.root, count(t1.id) as count')->from(TABLE_TEAM)->alias('t1')
- ->leftJoin(TABLE_USER)->alias('t2')->on('t1.account=t2.account')
- ->where('t1.root')->in($projectIdList)
- ->andWhere('t2.deleted')->eq(0)
- ->groupBy('t1.root')
- ->fetchAll('root');
+ $teams = $this->projectTao->fetchMemberCountByIdList($projectIdList);
+ $estimates = $this->projectTao->fetchTaskEstimateByIdList($projectIdList);
- $estimates = $this->dao->select("t2.project as project, sum(estimate) as estimate")->from(TABLE_TASK)->alias('t1')
- ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.execution = t2.id')
- ->where('t1.parent')->lt(1)
- ->andWhere('t2.project')->in($projectIdList)
- ->andWhere('t1.deleted')->eq(0)
- ->andWhere('t2.deleted')->eq(0)
- ->groupBy('t2.project')
- ->fetchAll('project');
-
- $this->app->loadClass('pager', $static = true);
+ $this->app->loadClass('pager', true);
foreach($projects as $projectID => $project)
{
$orderBy = $project->model == 'waterfall' ? 'id_asc' : 'id_desc';
@@ -868,12 +852,11 @@ class projectModel extends model
->orderBy('grade desc')
->fetch();
- $projects = $this->dao->select('id')->from(TABLE_PROJECT)
+ return $this->dao->select('id')->from(TABLE_PROJECT)
->where('type')->eq('project')
->andWhere('deleted')->eq(0)
->andWhere('path')->like("{$parentProgram->path}%")
->fetchPairs('id');
- return $projects;
}
/**
@@ -1310,6 +1293,47 @@ class projectModel extends model
return $projectID;
}
+ /**
+ * Check branch and product valid by project.
+ *
+ * @param int $projectID
+ * @param object $project
+ * @access public
+ * @return bool
+ */
+ public function checkBranchAndProductValid(int $projectID, object $project): bool
+ {
+ $topProgramID = $this->loadModel('program')->getTopByID($project->parent);
+ $multipleProducts = $this->loadModel('product')->getMultiBranchPairs($topProgramID);
+ foreach($project->products as $index => $productID)
+ {
+ if(isset($multipleProducts[$productID]) and empty($project->branch[$index]))
+ {
+ dao::$errors[] = $this->lang->project->emptyBranch;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Check dates valid by project.
+ *
+ * @param int $projectID
+ * @param object $project
+ * @access public
+ * @return bool
+ */
+ public function checkDatesValidByProject($projectID, $project): bool
+ {
+ $minExecutionBegin = $this->dao->select('`begin` as minBegin')->from(TABLE_PROJECT)->where('project')->eq($projectID)->andWhere('deleted')->eq('0')->orderBy('begin_asc')->fetch();
+ $maxExecutionEnd = $this->dao->select('`end` as maxEnd')->from(TABLE_PROJECT)->where('project')->eq($projectID)->andWhere('deleted')->eq('0')->orderBy('end_desc')->fetch();
+ if($minExecutionBegin and $project->begin > $minExecutionBegin->minBegin) dao::$errors['begin'] = sprintf($this->lang->project->begigLetterExecution, $minExecutionBegin->minBegin);
+ if($maxExecutionEnd and $project->end < $maxExecutionEnd->maxEnd) dao::$errors['end'] = sprintf($this->lang->project->endGreateExecution, $maxExecutionEnd->maxEnd);
+ if(dao::isError()) return false;
+ return true;
+ }
+
/**
* Update project.
*
@@ -1326,28 +1350,7 @@ class projectModel extends model
$executionsCount = $this->dao->select('COUNT(*) as count')->from(TABLE_PROJECT)->where('project')->eq($project->id)->andWhere('deleted')->eq('0')->fetch('count');
- if(!empty($executionsCount) and $oldProject->multiple)
- {
- $minExecutionBegin = $this->dao->select('`begin` as minBegin')->from(TABLE_PROJECT)->where('project')->eq($project->id)->andWhere('deleted')->eq('0')->orderBy('begin_asc')->fetch();
- $maxExecutionEnd = $this->dao->select('`end` as maxEnd')->from(TABLE_PROJECT)->where('project')->eq($project->id)->andWhere('deleted')->eq('0')->orderBy('end_desc')->fetch();
- if($minExecutionBegin and $project->begin > $minExecutionBegin->minBegin) dao::$errors['begin'] = sprintf($this->lang->project->begigLetterExecution, $minExecutionBegin->minBegin);
- if($maxExecutionEnd and $project->end < $maxExecutionEnd->maxEnd) dao::$errors['end'] = sprintf($this->lang->project->endGreateExecution, $maxExecutionEnd->maxEnd);
- if(dao::isError()) return false;
- }
-
- if($_POST['products'])
- {
- $topProgramID = $this->loadModel('program')->getTopByID($project->parent);
- $multipleProducts = $this->loadModel('product')->getMultiBranchPairs($topProgramID);
- foreach($_POST['products'] as $index => $productID)
- {
- if(isset($multipleProducts[$productID]) and empty($_POST['branch'][$index]))
- {
- dao::$errors[] = $this->lang->project->emptyBranch;
- return false;
- }
- }
- }
+ if($project->product && !$this->checkBranchAndProductValid($projectID, $project)) return false;
/* Judge products not empty. */
$linkedProductsCount = 0;
@@ -1376,17 +1379,9 @@ class projectModel extends model
if($this->post->delta == 999) $requiredFields = trim(str_replace(',end,', ',', ",{$requiredFields},"), ',');
$this->lang->error->unique = $this->lang->error->repeat;
- $this->dao->update(TABLE_PROJECT)->data($project)
- ->autoCheck($skipFields = 'begin,end')
- ->batchcheck($requiredFields, 'notempty')
- ->checkIF($project->begin != '', 'begin', 'date')
- ->checkIF($project->end != '', 'end', 'date')
- ->checkIF($project->end != '', 'end', 'gt', $project->begin)
- ->checkIF(!empty($project->name), 'name', 'unique', "id != $projectID and `type` = 'project' and `parent` = '$oldProject->parent' and `model` = '{$project->model}' and `deleted` = '0'")
- ->checkIF(!empty($project->code), 'code', 'unique', "id != $projectID and `type` = 'project' and `model` = '{$project->model}' and `deleted` = '0'")
- ->checkFlow()
- ->where('id')->eq($projectID)
- ->exec();
+
+ if(!empty($executionsCount) and $oldProject->multiple) $this->checkDatesValidByProject($projectID ,$project);
+ $this->projectTao->doUpdate($projectID, $project, $oldProject);
if(dao::isError()) return false;
if(!$oldProject->hasProduct and ($oldProject->name != $project->name or $oldProject->parent != $project->parent or $oldProject->acl != $project->acl)) $this->updateShadowProduct($project);
@@ -1536,7 +1531,7 @@ class projectModel extends model
$parentID = !isset($project->parent) ? $oldProject->parent : $project->parent;
$this->dao->update(TABLE_PROJECT)->data($project)
- ->autoCheck($skipFields = 'begin,end')
+ ->autoCheck('begin,end')
->batchCheck($this->config->project->edit->requiredFields, 'notempty')
->checkIF($project->begin != '', 'begin', 'date')
->checkIF($project->end != '', 'end', 'date')
@@ -3047,16 +3042,13 @@ class projectModel extends model
*/
public function updatePlanIdListByProject(int $projectID, array $plans): void
{
- /* Link the plan stories. */
+ /* Link the plan stories and transform $plans to $newPlans. */
$newPlans = array();
if(isset($plans))
{
foreach($plans as $planList)
{
- foreach($planList as $planIDList)
- {
- foreach($planIDList as $planID) $newPlans[$planID] = $planID;
- }
+ foreach($planList as $planID) $newPlans[$planID] = $planID;
}
}
if(empty($newPlans)) return;
diff --git a/module/project/tao.php b/module/project/tao.php
index 90aff1b15d..07ee19fb5f 100755
--- a/module/project/tao.php
+++ b/module/project/tao.php
@@ -77,7 +77,7 @@ class projectTao extends projectModel
}
/**
- * Update project.
+ * Update project table when activate a project.
*
* @param int $projectID
* @param object $project
@@ -95,6 +95,33 @@ class projectTao extends projectModel
return !dao::isError();
}
+
+ /**
+ * Update project table when edit a project.
+ *
+ * @param int $projectID
+ * @param object $project
+ * @param object $oldProject
+ * @access protected
+ * @return bool
+ */
+ protected function doUpdate(int $projectID ,object $project, object $oldProject): bool
+ {
+ $this->dao->update(TABLE_PROJECT)->data($project)
+ ->autoCheck('begin,end')
+ ->batchcheck($requiredFields, 'notempty')
+ ->checkIF($project->begin != '', 'begin', 'date')
+ ->checkIF($project->end != '', 'end', 'date')
+ ->checkIF($project->end != '', 'end', 'gt', $project->begin)
+ ->checkIF(!empty($project->name), 'name', 'unique', "id != $projectID and `type` = 'project' and `parent` = '$oldProject->parent' and `model` = '{$project->model}' and `deleted` = '0'")
+ ->checkIF(!empty($project->code), 'code', 'unique', "id != $projectID and `type` = 'project' and `model` = '{$project->model}' and `deleted` = '0'")
+ ->checkFlow()
+ ->where('id')->eq($projectID)
+ ->exec();
+
+ return !dao::isError();
+ }
+
/**
* Fetch undone tasks.
*
@@ -490,17 +517,96 @@ class projectTao extends projectModel
}
/**
- * 将旧的产品替换成新的
- * replace oldProduct
+ * 查找项目执行下关联的产品
+ * Get linked products with execution under the project.
*
* @param array $executionIDs
*
* @access protected
- * @return bool
+ * @return array
*/
- protected function replaceOldProduct(array $executionIDs): bool
+ protected function getExecutionProductGroup(array $executionIDs): array
{
$oldExecutionProducts = $this->dao->select('project,product')->from(TABLE_PROJECTPRODUCT)->where('project')->in($executionIDs)->fetchGroup('project', 'product');
- return !dao::isError();
+ return $oldExecutionProducts;
+ }
+
+ /**
+ * 根据状态和和我参与的查询项目列表。
+ * Get project list by status and with my participation.
+ *
+ * @param string $status
+ * @param string $orderBy
+ * @param bool $involved
+ * @param object $pager
+ * @access protected
+ * @return array
+ */
+ protected function fetchProjectList(string $status, string $orderBy, bool $involved, object|null $pager): array
+ {
+ return $this->dao->select('DISTINCT t1.*')->from(TABLE_PROJECT)->alias('t1')
+ ->leftJoin(TABLE_TEAM)->alias('t2')->on('t1.id=t2.root')
+ ->leftJoin(TABLE_STAKEHOLDER)->alias('t3')->on('t1.id=t3.objectID')
+ ->where('t1.deleted')->eq('0')
+ ->andWhere('t1.vision')->eq($this->config->vision)
+ ->andWhere('t1.type')->eq('project')
+ ->beginIF(!in_array($status, array('all', 'undone', 'review', 'unclosed'), true))->andWhere('t1.status')->eq($status)->fi()
+ ->beginIF($status == 'undone' or $status == 'unclosed')->andWhere('t1.status')->in('wait,doing')->fi()
+ ->beginIF($status == 'review')
+ ->andWhere("FIND_IN_SET('{$this->app->user->account}', t1.reviewers)")
+ ->andWhere('t1.reviewStatus')->eq('doing')
+ ->fi()
+ ->beginIF($this->cookie->involved or $involved)
+ ->andWhere('t2.type')->eq('project')
+ ->andWhere('t1.openedBy', true)->eq($this->app->user->account)
+ ->orWhere('t1.PM')->eq($this->app->user->account)
+ ->orWhere('t2.account')->eq($this->app->user->account)
+ ->orWhere('(t3.user')->eq($this->app->user->account)
+ ->andWhere('t3.deleted')->eq(0)
+ ->markRight(1)
+ ->orWhere("CONCAT(',', t1.whitelist, ',')")->like("%,{$this->app->user->account},%")
+ ->markRight(1)
+ ->fi()
+ ->orderBy($orderBy)
+ ->page($pager, 't1.id')
+ ->fetchAll('id');
+ }
+
+ /**
+ * 根据项目ID列表查询团队成员数量。
+ * Get project team member count by project id list.
+ *
+ * @param array $projectIdList
+ * @access protected
+ * @return array
+ */
+ protected function fetchMemberCountByIdList(array $projectIdList): array
+ {
+ return $this->dao->select('t1.root, count(t1.id) as count')->from(TABLE_TEAM)->alias('t1')
+ ->leftJoin(TABLE_USER)->alias('t2')->on('t1.account=t2.account')
+ ->where('t1.root')->in($projectIdList)
+ ->andWhere('t2.deleted')->eq(0)
+ ->groupBy('t1.root')
+ ->fetchAll('root');
+ }
+
+ /**
+ * 根据项目ID列表查询任务的总预计工时。
+ * Get task all estimate by project id list.
+ *
+ * @param array $projectIdList
+ * @access protected
+ * @return array
+ */
+ protected function fetchTaskEstimateByIdList(array $projectIdList): array
+ {
+ return $this->dao->select("t2.project as project, sum(estimate) as estimate")->from(TABLE_TASK)->alias('t1')
+ ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.execution = t2.id')
+ ->where('t1.parent')->lt(1)
+ ->andWhere('t2.project')->in($projectIdList)
+ ->andWhere('t1.deleted')->eq(0)
+ ->andWhere('t2.deleted')->eq(0)
+ ->groupBy('t2.project')
+ ->fetchAll('project');
}
}
diff --git a/module/project/test/model/getinfolist.php b/module/project/test/model/getinfolist.php
deleted file mode 100755
index 179a55ed9d..0000000000
--- a/module/project/test/model/getinfolist.php
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env php
-> 44
-查询wait状态的Id为11的项目名称 >> 项目1
-查询暂停状态的项目数量 >> 11
-查询关闭状态的项目数量 >> 11
-查询所有状态的项目数量 >> 110
-
-*/
-
-global $tester;
-$tester->loadModel('project');
-
-$doingProjects = $tester->project->getInfoList('doing');
-$waitProjects = $tester->project->getInfoList('wait');
-$suspendedProjects = $tester->project->getInfoList('suspended');
-$closedProjects = $tester->project->getInfoList('closed');
-$allProjects = $tester->project->getInfoList('all');
-
-r(count($doingProjects)) && p() && e('44'); //查询正在进行的项目数量
-r($waitProjects) && p('11:name') && e('项目1'); //查询wait状态的Id为11的项目名称
-r(count($suspendedProjects)) && p() && e('11'); //查询暂停状态的项目数量
-r(count($closedProjects)) && p() && e('11'); //查询关闭状态的项目数量
-r(count($allProjects)) && p() && e('110'); //查询所有状态的项目数量
diff --git a/module/project/test/model/getlist.php b/module/project/test/model/getlist.php
new file mode 100755
index 0000000000..ba074c19aa
--- /dev/null
+++ b/module/project/test/model/getlist.php
@@ -0,0 +1,59 @@
+#!/usr/bin/env php
+id->range('11-19');
+ $project->project->range('11-19');
+ $project->name->prefix("项目")->range('11-19');
+ $project->code->prefix("project")->range('11-19');
+ $project->model->range("scrum");
+ $project->auth->range("[]");
+ $project->path->range("[]");
+ $project->type->range("project");
+ $project->grade->range("1");
+ $project->days->range("1");
+ $project->status->range("wait,doing,suspended,closed");
+ $project->desc->range("[]");
+ $project->budget->range("100000,200000");
+ $project->budgetUnit->range("CNY");
+ $project->percent->range("0-0");
+ $project->openedDate->range("`2023-05-01 10:00:10`");
+ $project->gen(9);
+
+ zdTable('team')->gen(10);
+
+ $stakeholder = zdTable('stakeholder');
+ $stakeholder->id->range('1-9');
+ $stakeholder->objectID->range('11-19');
+ $stakeholder->objectType->range('program,project');
+ $stakeholder->user->range("admin");
+ $stakeholder->type->range("inside");
+ $stakeholder->from->range("[]");
+ $stakeholder->createdBy->range("admin");
+ $stakeholder->createdDate->range("`2023-05-01 10:00:10`");
+ $stakeholder->gen(9);
+}
+
+/**
+
+title=测试 projectModel::fetchProjectList();
+timeout=0
+cid=1
+
+
+*/
+
+initData();
+$statusList = array('', 'all', 'undone', 'unclosed', 'error');
+
+$projectTester = new Project();
+r($projectTester->testGetList($statusList[0])) && p() && e('0'); // 查询状态为空的项目
+r(count($projectTester->testGetList($statusList[1]))) && p() && e('9'); // 获取所有项目数量
+r($projectTester->testGetList($statusList[2])) && p('11:code') && e('project11'); // 查询未完成的第一个项目的code
+r($projectTester->testGetList($statusList[3], true)) && p('12:name') && e('项目12'); // 获取我参与的一个项目的项目名
+r($projectTester->testGetList($statusList[4])) && p() && e('0'); // 获取错误类型的项目
diff --git a/module/project/test/model/getlistbycurrentuser.php b/module/project/test/model/getlistbycurrentuser.php
index 1ed4729f55..2b2b07ceed 100644
--- a/module/project/test/model/getlistbycurrentuser.php
+++ b/module/project/test/model/getlistbycurrentuser.php
@@ -3,8 +3,8 @@
include dirname(__FILE__, 5) . "/test/lib/init.php";
su('admin');
-$project = zdTable('project');
-$project->gen(5);
+$project = zdTable('project')->config('project');
+$project->gen(4);
/**
@@ -12,7 +12,7 @@ title=测试 projectModel->getListByCurrentUser();
timeout=0
cid=1
-- 执行projectModel模块的getListByCurrentUser方法 @1
+- 执行projectModel模块的getListByCurrentUser方法 @0
- 执行projectModel模块的getListByCurrentUser方法 @1
@@ -27,6 +27,9 @@ cid=1
global $tester;
$projectModel = $tester->loadModel('project');
-r(count($projectModel->getListByCurrentUser())) && p() && e('1');
+$tester->app->user->admin = true;
+$tester->app->config->vision = 'lite';
+r(count($projectModel->getListByCurrentUser())) && p() && e('0');
+$tester->app->config->vision = 'rnd';
r(count($projectModel->getListByCurrentUser())) && p() && e('1');
r($projectModel->getListByCurrentUser()) && p('11:id,name') && e('11,项目1');
\ No newline at end of file
diff --git a/module/project/test/model/yaml/getlistbycurrentuser/project.yaml b/module/project/test/model/yaml/getlistbycurrentuser/project.yaml
new file mode 100644
index 0000000000..ab7a7a5ae0
--- /dev/null
+++ b/module/project/test/model/yaml/getlistbycurrentuser/project.yaml
@@ -0,0 +1,16 @@
+title: zt_project
+author: liuhong
+version: "1.0"
+fields:
+ - field: type
+ range: 'project,sprint,project,stage'
+ - field: status
+ range: 'wait,doing,closed,suspended'
+ - field: deleted
+ range: 0,1,1,0
+ - field: vision
+ range: rnd,rnd,rnd,lite
+ - field: openedDate
+ range: "20220101 000000:1W" # 生成从2021年1月1日0时0分0秒到当前时间的数据,步长为1周
+ type: timestamp
+ format: "YY/MM/DD hh:mm:ss"
diff --git a/module/project/test/project.class.php b/module/project/test/project.class.php
index b272a5721e..fe65375fb2 100644
--- a/module/project/test/project.class.php
+++ b/module/project/test/project.class.php
@@ -162,10 +162,10 @@ class Project
/**
* Activate a project.
*
- * @param int $projectID
- * @param object $project
+ * @param int $projectID
+ * @param object $project
* @access public
- * @return array $changes
+ * @return array
*/
public function activate($projectID, $project)
{
@@ -175,8 +175,8 @@ class Project
/**
* Do activate a project.
*
- * @param int $projectID
- * @param object $project
+ * @param int $projectID
+ * @param object $project
* @access public
* @return bool
*/
@@ -190,7 +190,7 @@ class Project
*
* @param int $budget
* @access public
- * @return int|string $projectBudget
+ * @return int|string
*/
public function getBudgetWithUnit($budget)
{
@@ -202,13 +202,40 @@ class Project
*
* @param int $budget
* @access public
- * @return int|string $projectBudget
+ * @return int|string
*/
public function addProjectAdminTest($projectID)
{
- global $tester;
- $tester->loadModel('project')->addProjectAdmin($projectID);
+ $this->project->addProjectAdmin($projectID);
return $tester->dao->select('*')->from(TABLE_PROJECTADMIN)->fetch();
}
+
+ /**
+ * Test fetchProjectList function.
+ *
+ * @param int $status
+ * @param bool $involved
+ * @access public
+ * @return array
+ */
+ public function testFetchProjectList($status, $involved = false)
+ {
+ $projects = $this->project->fetchProjectList($status, 'id_desc', $involved, null);
+ return $projects;
+ }
+
+ /**
+ * Test getList function.
+ *
+ * @param int $status
+ * @param bool $involved
+ * @access public
+ * @return array
+ */
+ public function testGetList($status, $involved = false)
+ {
+ $projects = $this->project->fetchProjectList($status, 'id_desc', $involved, null);
+ return $projects;
+ }
}
diff --git a/module/project/test/tao/fetchmembercountbyidlist.php b/module/project/test/tao/fetchmembercountbyidlist.php
new file mode 100644
index 0000000000..20c8dbed9b
--- /dev/null
+++ b/module/project/test/tao/fetchmembercountbyidlist.php
@@ -0,0 +1,50 @@
+#!/usr/bin/env php
+id->range('11-19');
+ $project->project->range('11-19');
+ $project->name->prefix("项目")->range('11-19');
+ $project->code->prefix("project")->range('11-19');
+ $project->model->range("scrum");
+ $project->auth->range("[]");
+ $project->path->range("[]");
+ $project->type->range("project");
+ $project->grade->range("1");
+ $project->days->range("1");
+ $project->status->range("wait,doing,suspended,closed");
+ $project->desc->range("[]");
+ $project->budget->range("100000,200000");
+ $project->budgetUnit->range("CNY");
+ $project->percent->range("0-0");
+ $project->openedDate->range("`2023-05-01 10:00:10`");
+ $project->gen(9);
+
+ zdTable('team')->gen(10);
+ zdTable('user')->gen(10);
+}
+
+/**
+
+title=测试 projectModel::fetchProjectList();
+timeout=0
+cid=1
+
+
+*/
+
+initData();
+$noneIDList = array();
+$wrongIDList = array('1', '2');
+$realIDList = array('11', '12');
+
+global $tester;
+$projectTester = $tester->loadModel('project');
+r($projectTester->fetchMemberCountByIdList($noneIDList)) && p() && e('0'); // 查询没有项目ID的情况
+r($projectTester->fetchMemberCountByIdList($wrongIDList)) && p() && e('0'); // 查询错误ID的情况
+r($projectTester->fetchMemberCountByIdList($realIDList)) && p('11:count') && e('1'); // 查询正常ID的情况
diff --git a/module/project/test/tao/fetchprojectlist.php b/module/project/test/tao/fetchprojectlist.php
new file mode 100755
index 0000000000..1c2dc6bed4
--- /dev/null
+++ b/module/project/test/tao/fetchprojectlist.php
@@ -0,0 +1,59 @@
+#!/usr/bin/env php
+id->range('11-19');
+ $project->project->range('11-19');
+ $project->name->prefix("项目")->range('11-19');
+ $project->code->prefix("project")->range('11-19');
+ $project->model->range("scrum");
+ $project->auth->range("[]");
+ $project->path->range("[]");
+ $project->type->range("project");
+ $project->grade->range("1");
+ $project->days->range("1");
+ $project->status->range("wait,doing,suspended,closed");
+ $project->desc->range("[]");
+ $project->budget->range("100000,200000");
+ $project->budgetUnit->range("CNY");
+ $project->percent->range("0-0");
+ $project->openedDate->range("`2023-05-01 10:00:10`");
+ $project->gen(9);
+
+ zdTable('team')->gen(10);
+
+ $stakeholder = zdTable('stakeholder');
+ $stakeholder->id->range('1-9');
+ $stakeholder->objectID->range('11-19');
+ $stakeholder->objectType->range('program,project');
+ $stakeholder->user->range("admin");
+ $stakeholder->type->range("inside");
+ $stakeholder->from->range("[]");
+ $stakeholder->createdBy->range("admin");
+ $stakeholder->createdDate->range("`2023-05-01 10:00:10`");
+ $stakeholder->gen(9);
+}
+
+/**
+
+title=测试 projectModel::fetchProjectList();
+timeout=0
+cid=1
+
+
+*/
+
+initData();
+$statusList = array('', 'all', 'undone', 'unclosed', 'error');
+
+$projectTester = new Project();
+r($projectTester->testFetchProjectList($statusList[0])) && p() && e('0'); // 查询状态为空的项目
+r(count($projectTester->testFetchProjectList($statusList[1]))) && p() && e('9'); // 获取所有项目数量
+r($projectTester->testFetchProjectList($statusList[2])) && p('11:code') && e('project11'); // 查询未完成的第一个项目的code
+r($projectTester->testFetchProjectList($statusList[3], true)) && p('12:name') && e('项目12'); // 获取我参与的一个项目的项目名
+r($projectTester->testFetchProjectList($statusList[4])) && p() && e('0'); // 获取错误类型的项目
diff --git a/module/project/test/tao/fetchtaskestimatebyidlist.php b/module/project/test/tao/fetchtaskestimatebyidlist.php
new file mode 100755
index 0000000000..c3aea6773c
--- /dev/null
+++ b/module/project/test/tao/fetchtaskestimatebyidlist.php
@@ -0,0 +1,55 @@
+#!/usr/bin/env php
+id->range('11-19,101-109');
+ $project->project->range('11-19');
+ $project->name->setFields(array(
+ array('field' => 'name1', 'range' => '项目{9},迭代{9}'),
+ array('field' => 'name2', 'range' => '11-19,101-109')
+ ));
+ $project->code->setFields(array(
+ array('field' => 'name1', 'range' => 'project{9},execution{9}'),
+ array('field' => 'name2', 'range' => '11-19,101-109')
+ ));
+ $project->model->range("scrum{9},[]{9}");
+ $project->auth->range("[]");
+ $project->path->range("[]");
+ $project->type->range("project{9},sprint{9}");
+ $project->grade->range("1");
+ $project->days->range("1");
+ $project->status->range("wait,doing,suspended,closed");
+ $project->desc->range("[]");
+ $project->budget->range("100000,200000");
+ $project->budgetUnit->range("CNY");
+ $project->percent->range("0-0");
+ $project->openedDate->range("`2023-05-01 10:00:10`");
+ $project->gen(18);
+
+ zdTable('task')->gen(10);
+}
+
+/**
+
+title=测试 projectModel::fetchProjectList();
+timeout=0
+cid=1
+
+
+*/
+
+initData();
+$noneIDList = array();
+$wrongIDList = array('1', '2');
+$realIDList = array('13', '14');
+
+global $tester;
+$projectTester = $tester->loadModel('project');
+r($projectTester->fetchTaskEstimateByIdList($noneIDList)) && p() && e('0'); // 查询没有项目ID的情况
+r($projectTester->fetchTaskEstimateByIdList($wrongIDList)) && p() && e('0'); // 查询错误ID的情况
+r($projectTester->fetchTaskEstimateByIdList($realIDList)) && p('14:estimate') && e('3'); // 查询正常ID的情况
diff --git a/module/project/zen.php b/module/project/zen.php
index e9907f1088..b841f57fe2 100644
--- a/module/project/zen.php
+++ b/module/project/zen.php
@@ -652,8 +652,8 @@ class projectZen extends project
}
/**
- * 处理并合并项目下的新旧产品
- * mergeProducts
+ * 关联产品时,合并项目下的新旧产品
+ * Merge old and new products under the project When link products.
*
* @param int $projectID
* @param object $project
@@ -663,7 +663,7 @@ class projectZen extends project
* @access protected
* @return void
*/
- protected function mergeProducts(int $projectID, object $project, int|array $executionIDs, array $postData): void
+ protected function mergeProducts(int $projectID, object $project, int|array $executionIDs, array $postData): mixed
{
$this->loadModel('product');
$this->loadModel('execution');
@@ -672,21 +672,20 @@ class projectZen extends project
$this->project->updateProducts($projectID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- //判断是否为项目型项目并更新关联产品
- if(empty($project->multiple))
- {
- $executionID = $this->execution->getNoMultipleID($projectID);
- if($executionID) $this->execution->updateProducts($executionID);
- }
-
- //将项目下关联的新旧产品合并
+ /* Merge old and new linked products under the project. */
$newProducts = $this->product->getProducts($projectID);
$oldProductIDs = array_keys($oldProducts);
$newProductIDs = array_keys($newProducts);
$diffProducts = array_merge(array_diff($oldProductIDs, $newProductIDs), array_diff($newProductIDs, $oldProductIDs));
if($diffProducts) $this->loadModel('action')->create('project', $projectID, 'Managed', '', !empty($postData->rawdata->products) ? implode(',', $postData->rawdata->products) : '');
- //判断是否为产品型项目并更新关联产品
+ /* Multiple and Division project update linked products. */
+ if(empty($project->multiple))
+ {
+ $executionID = $this->execution->getNoMultipleID($projectID);
+ if($executionID) $this->execution->updateProducts($executionID);
+ }
+
if(empty($project->division))
{
foreach($executionIDs as $executionID)
@@ -696,48 +695,47 @@ class projectZen extends project
}
}
- //处理非瀑布及产品型项目
- $this->dealExecutionProduct($project, $oldProducts, $newProductIDs, $executionIDs);
+ /* Record multiple and waterfall project unlinked products. */
+ if($project->multiple and $project->model != 'waterfall' and $project->model != 'waterfallplus')
+ {
+ $this->dealUnlinkedProduct($project, $oldProducts, $newProductIDs, $executionIDs);
+ }
}
/**
- * 处理项目执行下关联产品
- * deal execution product
+ * 记录多迭代及瀑布类项目移除的产品
+ * Record multiple and waterfall project unlinked products
*
* @param object $project
- * @param object $oldProducts
+ * @param array $oldProducts
* @param array $newProductIDs
* @param int|array $executionIDs
*
* @access protected
* @return void
*/
- protected function dealExecutionProduct(object $project, object $oldProducts, array $newProductIDs, array $executionIDs): void
+ protected function dealUnlinkedProduct(object $project, array $oldProducts, array $newProductIDs, array $executionIDs): void
{
- //处理非瀑布及产品型项目
- if($project->multiple and $project->model != 'waterfall' and $project->model != 'waterfallplus')
+ $oldExecutionProducts = $this->projectTao->getExecutionProductGroup($executionIDs);
+ $unlinkedProducts = array_diff(array_keys($oldProducts), $newProductIDs);
+ if(!empty($unlinkedProducts))
{
- $oldExecutionProducts = $this->projectTao->replaceOldProduct($executionIDs);
- $unlinkedProducts = array_diff(array_keys($oldProducts), $newProductIDs);
- if(!empty($unlinkedProducts))
+ $unlinkedProductPairs = array();
+ foreach($unlinkedProducts as $unlinkedProduct) $unlinkedProductPairs[$unlinkedProduct] = $oldProducts[$unlinkedProduct]->name;
+
+ $unlinkExecutions = array();
+ foreach($oldExecutionProducts as $executionID => $executionProducts)
{
- $unlinkedProductPairs = array();
- foreach($unlinkedProducts as $unlinkedProduct) $unlinkedProductPairs[$unlinkedProduct] = $oldProducts[$unlinkedProduct]->name;
-
- $unlinkExecutions = array();
- foreach($oldExecutionProducts as $executionID => $executionProducts)
- {
- $unlinkExecutionProducts = array_intersect_key($unlinkedProductPairs, $executionProducts);
- if($unlinkExecutionProducts) $unlinkExecutions[$executionID] = $unlinkExecutionProducts;
- }
-
- foreach($unlinkExecutions as $executionID => $unlinkExecutionProducts) $this->loadModel('action')->create('execution', $executionID, 'unlinkproduct', '', implode(',', $unlinkExecutionProducts));
+ $unlinkExecutionProducts = array_intersect_key($unlinkedProductPairs, $executionProducts);
+ if($unlinkExecutionProducts) $unlinkExecutions[$executionID] = $unlinkExecutionProducts;
}
+
+ foreach($unlinkExecutions as $executionID => $unlinkExecutionProducts) $this->loadModel('action')->create('execution', $executionID, 'unlinkproduct', '', implode(',', $unlinkExecutionProducts));
}
}
/**
- * 处理项目关联需求的产品
+ * 项目关联用户故事则无法移除产品
* dealLinkProduct
*
* @param int $projectID
@@ -759,7 +757,6 @@ class projectZen extends project
$linkedProducts = $this->product->getProducts($projectID, 'all', '', true, $linkedProductIdList);
$projectStories = $this->project->getStoriesByProject($projectID);
$projectBranches = $this->project->getBranchGroupByProject($projectID, array_keys($linkedProducts));
- $branchGroups = $this->loadModel('branch')->getByProducts(array_keys($allProducts), 'ignoreNormal|noclosed', $linkedBranchIdList);
/* If the story of the product which linked the project,don't allow to remove the product. */
$unmodifiableProducts = array();
@@ -782,86 +779,87 @@ class projectZen extends project
}
}
- $this->dealOtherLinkProduct($project, $branchGroups, $linkedBranches);
+ /* Initializes the product from other linked products. */
+ if($this->config->systemMode == 'ALM') $this->InitOtherLinkProduct($project, $allProducts, $linkedBranchIdList, $linkedBranches, $linkedProducts);
- $this->view->allBranches = $this->loadModel('branch')->getByProducts(array_keys($allProducts), 'ignoreNormal');
- $this->view->allProducts = $allProducts;
$this->view->unmodifiableProducts = $unmodifiableProducts;
$this->view->unmodifiableBranches = $unmodifiableBranches;
$this->view->unmodifiableMainBranches = $unmodifiableMainBranches;
- $this->view->linkedBranches = $linkedBranches;
- $this->view->branchGroups = $branchGroups;
}
/**
- * dealOtherLinkProduct
+ * 初始化项目集下其他关联产品中当前产品
+ * Initializes the current product under the projectprogram.
*
* @param object $project
- * @param object $branchGroups
+ * @param array $allProducts
+ * @param array $linkedBranchIdList
* @param array $linkedBranches
+ * @param array $linkedProducts
*
* @access protected
* @return void
*/
- protected function dealOtherLinkProduct(object $project, object $branchGroups, array $linkedBranches): void
+ protected function InitOtherLinkProduct(object $project, array $allProducts, array $linkedBranchIdList, array $linkedBranches, array $linkedProducts): void
{
- $linkedProducts = $this->product->getProducts($projectID, 'all', '', true, $linkedProductIdList);
+ $branchGroups = $this->loadModel('branch')->getByProducts(array_keys($allProducts), 'ignoreNormal|noclosed', $linkedBranchIdList);
+ $topProgramID = $project->parent ? $this->program->getTopByPath($project->path) : 0;
+ $productsGroupByProgram = $this->loadModel('product')->getProductsGroupByProgram();
- if($this->config->systemMode == 'ALM')
+ $currentProducts = array();
+ foreach($productsGroupByProgram as $programID => $programProducts)
{
- $topProgramID = $project->parent ? $this->program->getTopByPath($project->path) : 0;
- $productsGroupByProgram = $this->product->getProductsGroupByProgram();
-
- $currentProducts = array();
- $otherProducts = array();
- foreach($productsGroupByProgram as $programID => $programProducts)
+ if($programID != $topProgramID)
{
- if($programID != $topProgramID)
- {
- foreach($programProducts as $productID => $productName)
- {
- if(!empty($branchGroups[$productID]))
- {
- foreach($branchGroups[$productID] as $branchID => $branchName)
- {
- if(isset($linkedProducts[$productID]) and isset($linkedBranches[$productID][$branchID])) continue;
+ $otherProducts = $this->InitBranchProduct($programProducts, $branchGroups, $linkedBranches, $linkedProducts);
+ }
+ else
+ {
+ $currentProducts += $programProducts;
+ }
+ }
+ $this->view->currentProducts = $currentProducts;
+ $this->view->otherProducts = $otherProducts;
- $otherProducts["{$productID}_{$branchID}"] = $productName . '_' . $branchName;
- }
- }
- else
- {
- if(isset($linkedProducts[$productID])) continue;
- $otherProducts[$productID] = $productName;
- }
- }
- }
- else
+ $this->view->branchGroups = $branchGroups;
+ $this->view->linkedBranches = $linkedBranches;
+ $this->view->linkedProducts = $linkedProducts;
+ $this->view->allProducts = $allProducts;
+ $this->view->allBranches = $this->loadModel('branch')->getByProducts(array_keys($allProducts), 'ignoreNormal');
+ }
+
+ /**
+ * 初始化项目集下其他关联产品中多分支产品
+ * Initializes the multi-branch product under the projectprogram.
+ *
+ * @param object $programProducts
+ * @param array $branchGroups
+ * @param array $linkedBranches
+ * @param array $linkedProducts
+ *
+ * @access protected
+ * @return array
+ */
+ protected function InitBranchProduct(object $programProducts, array $branchGroups, array $linkedBranches, array $linkedProducts): array
+ {
+ $otherProducts = array();
+ foreach($programProducts as $productID => $productName)
+ {
+ if(!empty($branchGroups[$productID]))
+ {
+ foreach($branchGroups[$productID] as $branchID => $branchName)
{
- $currentProducts += $programProducts;
+ if(isset($linkedProducts[$productID]) and isset($linkedBranches[$productID][$branchID])) continue;
+ $otherProducts["{$productID}_{$branchID}"] = $productName . '_' . $branchName;
}
}
- $this->view->currentProducts = $currentProducts;
- $this->view->otherProducts = $otherProducts;
+ else
+ {
+ if(isset($linkedProducts[$productID])) continue;
+ $otherProducts[$productID] = $productName;
+ }
}
- $this->view->linkedProducts = $linkedProducts;
- }
- /**
- * buildMangedProductForm
- *
- * @param int $projectID
- * @param object $project
- *
- * @access protected
- * @return void
- */
- protected function buildMangedProductForm(int $projectID, $project, $executions): void
- {
- $this->view->title = $this->lang->project->manageProducts . $this->lang->colon . $project->name;
- $this->view->project = $project;
- $this->view->executions = $executions;
- $this->view->branches = $this->project->getBranchesByProject($projectID);
- $this->display();
+ return $otherProducts;
}
}
diff --git a/module/projectrelease/control.php b/module/projectrelease/control.php
index 2462a83b3b..ce3b0032f7 100644
--- a/module/projectrelease/control.php
+++ b/module/projectrelease/control.php
@@ -757,7 +757,7 @@ class projectrelease extends control
}
$this->view->allBugs = $allBugs;
- $this->view->releaseBugs = empty($releaseBugs) ? array() : $this->bug->getByList($releaseBugs);
+ $this->view->releaseBugs = empty($releaseBugs) ? array() : $this->bug->getByIdList($releaseBugs);
$this->view->release = $release;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->browseType = $browseType;
diff --git a/module/release/control.php b/module/release/control.php
index edc2bbe131..06001be094 100644
--- a/module/release/control.php
+++ b/module/release/control.php
@@ -674,7 +674,7 @@ class release extends control
}
$this->view->allBugs = $allBugs;
- $this->view->releaseBugs = empty($releaseBugs) ? array() : $this->bug->getByList($releaseBugs);
+ $this->view->releaseBugs = empty($releaseBugs) ? array() : $this->bug->getByIdList($releaseBugs);
$this->view->release = $release;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->browseType = $browseType;
diff --git a/module/repo/model.php b/module/repo/model.php
index 7d996f2a0a..71bca9ab07 100644
--- a/module/repo/model.php
+++ b/module/repo/model.php
@@ -2806,7 +2806,7 @@ class repoModel extends model
}
}
$stories = empty($storyIDs) ? array() : $this->loadModel('story')->getByList($storyIDs);
- $bugs = empty($bugIDs) ? array() : $this->loadModel('bug')->getByList($bugIDs);
+ $bugs = empty($bugIDs) ? array() : $this->loadModel('bug')->getByIdList($bugIDs);
$tasks = empty($taskIDs) ? array() : $this->loadModel('task')->getByList($taskIDs);
$titleList = array();
diff --git a/module/story/control.php b/module/story/control.php
index 97da97dcee..54a652d8e3 100755
--- a/module/story/control.php
+++ b/module/story/control.php
@@ -2399,7 +2399,7 @@ class story extends control
public function tasks($storyID, $executionID = 0)
{
$this->loadModel('task');
- $tasks = $this->task->getStoryTasks($storyID, $executionID);
+ $tasks = $this->task->getListByStory($storyID, $executionID);
$this->view->tasks = $tasks;
$this->view->users = $this->user->getPairs('noletter');
$this->view->summary = $this->execution->summary($tasks);
diff --git a/module/story/model.php b/module/story/model.php
index 99b3c06079..11cbd0d805 100644
--- a/module/story/model.php
+++ b/module/story/model.php
@@ -5463,7 +5463,7 @@ class storyModel extends model
$stories[$id]->title = $story->title;
$stories[$id]->cases = $this->loadModel('testcase')->getStoryCases($id);
$stories[$id]->bugs = $this->loadModel('bug')->getStoryBugs($id);
- $stories[$id]->tasks = $this->loadModel('task')->getStoryTasks($id);
+ $stories[$id]->tasks = $this->loadModel('task')->getListByStory($id);
if($this->config->edition == 'max')
{
$stories[$id]->designs = $this->dao->select('id, name')->from(TABLE_DESIGN)
@@ -5537,7 +5537,7 @@ class storyModel extends model
$stories[$id]->title = $story->title;
$stories[$id]->cases = $this->loadModel('testcase')->getStoryCases($id);
$stories[$id]->bugs = $this->loadModel('bug')->getStoryBugs($id);
- $stories[$id]->tasks = $this->loadModel('task')->getStoryTasks($id, 0, $projectID);
+ $stories[$id]->tasks = $this->loadModel('task')->getListByStory($id, 0, $projectID);
if($this->config->edition == 'max')
{
$stories[$id]->designs = $this->dao->select('id, name')->from(TABLE_DESIGN)
@@ -5581,7 +5581,7 @@ class storyModel extends model
$track[$id]->case = $this->loadModel('testcase')->getStoryCases($id);
$track[$id]->bug = $this->loadModel('bug')->getStoryBugs($id);
$track[$id]->story = $this->getByID($id);
- $track[$id]->task = $this->loadModel('task')->getStoryTasks($id);
+ $track[$id]->task = $this->loadModel('task')->getListByStory($id);
if($this->config->edition == 'max')
{
$track[$id]->design = $this->dao->select('id, name')->from(TABLE_DESIGN)
diff --git a/module/task/control.php b/module/task/control.php
index f59e4a0ce8..a64ba89fb1 100755
--- a/module/task/control.php
+++ b/module/task/control.php
@@ -2148,7 +2148,7 @@ class task extends control
}
}
- $bugs = $this->loadModel('bug')->getByList($relatedBugIdList);
+ $bugs = $this->loadModel('bug')->getByIdList($relatedBugIdList);
foreach($tasks as $task)
{
if($this->post->fileType == 'csv')
diff --git a/module/task/test/tao/buildtasktree.php b/module/task/test/tao/buildtasktree.php
index bcc72bdf14..e28d97cdf0 100755
--- a/module/task/test/tao/buildtasktree.php
+++ b/module/task/test/tao/buildtasktree.php
@@ -27,16 +27,26 @@ cid=1
$taskTester = new taskTest();
$allTaskIdList = range(1, 9);
$notParentTaskIdList = range(4, 9);
+$hasParentTaskIdList = array(1, 3, 4);
+$parentTaskIdList = range(1, 3);
$emptyData = $taskTester->buildTaskTreeTest(array());
$allTasks = $taskTester->buildTaskTreeTest($allTaskIdList);
$notParentTasks = $taskTester->buildTaskTreeTest($notParentTaskIdList);
+$hasParentTasks = $taskTester->buildTaskTreeTest($hasParentTaskIdList);
+$parentTasks = $taskTester->buildTaskTreeTest($parentTaskIdList);
$parentTask = current($allTasks);
$allTasksCount = count($allTasks);
$notParentTasksCount = count($notParentTasks);
+$hasParentTasksCount = count($hasParentTasks);
+$parentTasksCount = count($parentTasks);
r($emptyData) && p() && e('0'); // 测试空数据的情况
r($allTasksCount) && p() && e('6'); // 测试数据中有父任务时,重构结构后的任务数量
r($parentTask->children) && p('4:name') && e('子任务4'); // 测试数据中有父任务时,重构结构后子任务的数据
r($notParentTasksCount) && p() && e('6'); // 测试数据中没有父任务时,重构结构后的任务数量
r($notParentTasks) && p('4:parentName') && e('父任务1'); // 测试数据中没有父任务时,重构结构后的子任务中父任务的名称
+r($hasParentTasks) && p('1:name') && e('父任务1'); // 测试数据中有父子任务时,重构结构后的子任务中父任务的名称
+r($hasParentTasksCount) && p() && e('2'); // 测试数据中有父子任务时,重构结构后的任务数量
+r($parentTasks) && p('1:name') && e('父任务1'); // 测试数据中只有父任务时,重构结构后的父任务的名称
+r($parentTasksCount) && p() && e('3'); // 测试数据中只有父任务时,重构结构后的任务数量
diff --git a/module/task/test/tao/updatetaskesdatebygantt.php b/module/task/test/tao/updatetaskesdatebygantt.php
new file mode 100755
index 0000000000..d318e739d3
--- /dev/null
+++ b/module/task/test/tao/updatetaskesdatebygantt.php
@@ -0,0 +1,58 @@
+#!/usr/bin/env php
+id->range('1-5');
+ $task->name->prefix('任务')->range('1-5');
+ $task->parent->range('`-1`,1,1,0,0');
+ $task->execution->range('6,7,8,9,10');
+ $task->project->range('1,2,3,4,5');
+
+ $task->gen(5);
+
+ $project = zdTable('project');
+ $project->id->range('1-10');
+ $project->name->prefix('project')->range('1-10');
+ $project->project->range('0,0,0,0,0,1,2,3,4,5');
+
+ $project->gen(10);
+}
+
+function insertDate($taskID, $estStarted, $deadline)
+{
+}
+
+function getByID($taskID)
+{
+ global $tester;
+ return $tester->dao->select('estStarted,deadline,lastEditedBy')->from(TABLE_TASK)->where('id')->eq($taskID)->fetch();
+}
+
+/**
+
+title=测试updatetaskesdatebygantt
+cid=1
+
+*/
+initData();
+
+$postData = new stdClass();
+$postData->id = 1;
+$postData->startDate = '2023-04-20';
+$postData->endDate = '2023-04-24';
+$postData->type = 'task';
+
+$tester->loadModel('task');
+
+$taskIDList = range(1,5);
+$taskList = $tester->task->getByList($taskIDList);
+
+$tester->task->updateTaskEsDateByGantt($taskIDList[1], $postData);
+$tester->task->updateTaskEsDateByGantt($taskIDList[2], $postData);
+$tester->task->updateTaskEsDateByGantt($taskIDList[3], $postData);
+$tester->task->updateTaskEsDateByGantt($taskIDList[4], $postData);
+$tester->task->updateTaskEsDateByGantt($taskIDList[5], $postData);
diff --git a/module/task/test/task.class.php b/module/task/test/task.class.php
index f22a628ff5..3e5585435f 100644
--- a/module/task/test/task.class.php
+++ b/module/task/test/task.class.php
@@ -1523,7 +1523,7 @@ class taskTest
* @access public
* @return array
*/
- public function fetchExecutionTasksTest(int $executionID, int $productID = 0, string|array $type = 'all', array $modules = array(), string $orderBy = 'status_asc, id_desc', string $count = '0'): array|int
+ public function fetchExecutionTasksTest($executionID, $productID = 0, $type = 'all', $modules = array(), $orderBy = 'status_asc, id_desc', $count = '0'): array|int
{
$tasks = $this->objectModel->fetchExecutionTasks($executionID, $productID, $type, $modules, $orderBy);
if(dao::isError())
@@ -1548,7 +1548,7 @@ class taskTest
* @access public
* @return object[]
*/
- public function buildTaskTreeTest(array $taskIdList): array
+ public function buildTaskTreeTest($taskIdList): array
{
$tasks = array();
if(!empty($taskIdList)) $tasks = $this->objectModel->getByList($taskIdList);
@@ -1572,7 +1572,7 @@ class taskTest
* @access public
* @return string
*/
- public function getAssignedTo4MultiTest(int $taskID, string $type = 'current'): string
+ public function getAssignedTo4MultiTest($taskID, $type = 'current'): string
{
$task = $this->objectModel->getByID($taskID);
$members = empty($task->team) ? array() : $task->team;
@@ -1592,7 +1592,7 @@ class taskTest
* @access public
* @return object
*/
- public function computeCurrentTaskStatusTest(object $currentTask, object $oldTask, object $task, bool $autoStatus, bool $hasEfforts, array $members): object
+ public function computeCurrentTaskStatusTest($currentTask, $oldTask, $task, $autoStatus, $hasEfforts, $members): object
{
$task = $this->objectModel->computeCurrentTaskStatus($currentTask, $oldTask, $task, $autoStatus, $hasEfforts, $members);
if(dao::isError())
diff --git a/module/testreport/control.php b/module/testreport/control.php
index 29e9d061e9..a6fc8af407 100644
--- a/module/testreport/control.php
+++ b/module/testreport/control.php
@@ -549,7 +549,7 @@ class testreport extends control
$this->view->report = $report;
$this->view->execution = $execution;
$this->view->stories = $stories;
- $this->view->bugs = $report->bugs ? $this->bug->getByList($report->bugs) : array();
+ $this->view->bugs = $report->bugs ? $this->bug->getByIdList($report->bugs) : array();
$this->view->builds = $builds;
$this->view->cases = $this->testreport->getTaskCases($tasks, $report->begin, $report->end, $report->cases, $pager);
$this->view->users = $this->user->getPairs('noletter|noclosed|nodeleted');
diff --git a/module/todo/config.php b/module/todo/config.php
index 3bf3e70fdd..e9b915f6eb 100644
--- a/module/todo/config.php
+++ b/module/todo/config.php
@@ -1,6 +1,7 @@
todo = new stdclass();
$config->todo->batchCreate = 8;
@@ -59,3 +60,17 @@ $config->todo->project['opportunity'] = TABLE_OPPORTUNITY;
$config->todo->project['review'] = TABLE_REVIEW;
$config->todo->project['testtask'] = TABLE_TESTTASK;
+$config->todo->dateRange = array();
+$config->todo->dateRange['all'] = array('begin' => '1970-01-01', 'end' => '2109-01-01');
+$config->todo->dateRange['assignedtoother'] = array('begin' => '1970-01-01', 'end' => '2109-01-01');
+$config->todo->dateRange['today'] = array('begin' => date::today(), 'end' => date::today());
+$config->todo->dateRange['future'] = array('begin' => '2030-01-01', 'end' => '2030-01-01');
+$config->todo->dateRange['before'] = array('begin' => '1970-01-01', 'end' => date::today());
+$config->todo->dateRange['cycle'] = array('begin' => '', 'end' => '');
+$config->todo->dateRange['yesterday'] = array('begin' => date::yesterday(), 'end' => date::yesterday());
+$config->todo->dateRange['thisweek'] = array('begin' => date::getThisWeek()['begin'], 'end' => date::getThisWeek()['end']);
+$config->todo->dateRange['lastweek'] = array('begin' => date::getLastWeek()['begin'], 'end' => date::getLastWeek()['end']);
+$config->todo->dateRange['thismonth'] = array('begin' => date::getThisMonth()['begin'], 'end' => date::getThisMonth()['end']);
+$config->todo->dateRange['lastmonth'] = array('begin' => date::getLastMonth()['begin'], 'end' => date::getLastMonth()['end']);
+$config->todo->dateRange['thisseason'] = array('begin' => date::getThisSeason()['begin'], 'end' => date::getThisSeason()['end']);
+$config->todo->dateRange['thisyear'] = array('begin' => date::getThisYear()['begin'], 'end' => date::getThisYear()['end']);
diff --git a/module/todo/config/form.php b/module/todo/config/form.php
index 4128b5e791..43f4b11e94 100644
--- a/module/todo/config/form.php
+++ b/module/todo/config/form.php
@@ -39,7 +39,6 @@ $config->todo->batchClose->form['todoIDList'] = array('required' => true, 'type'
$config->todo->batchEdit = new stdClass;
$config->todo->batchEdit->form = array();
$config->todo->batchEdit->form['todoIDList'] = array('required' => true, 'type' => 'array');
-$config->todo->batchEdit->form['names'] = array('required' => true, 'type' => 'array');
$config->todo->batchFinish = new stdclass;
$config->todo->batchFinish->form = array();
@@ -52,4 +51,4 @@ $config->todo->editDate->form['todoIDList'] = array('required' => true, 'type' =
$config->todo->export = new stdClass;
$config->todo->export->form = array();
-$config->todo->export->form['exportType'] = array('required' => true, 'type' => 'string');
+$config->todo->export->form['exportType'] = array('required' => true, 'type' => 'string');
\ No newline at end of file
diff --git a/module/todo/control.php b/module/todo/control.php
index 631400c589..77ecbd147e 100755
--- a/module/todo/control.php
+++ b/module/todo/control.php
@@ -1,8 +1,6 @@
config->todo->create->form);
$todo = $this->todoZen->beforeCreate($formData);
- $todoID = $this->todo->create($todo);
+ $todoID = $this->todo->create($todo, $formData);
if($todoID === false) return print(js::error(dao::getError()));
$todo->id = $todoID;
- $this->todoZen->afterCreate($todo);
+ $this->todoZen->afterCreate($todo, $formData);
if(!empty($_POST['objectID'])) return $this->send(array('result' => 'success'));
@@ -66,25 +64,26 @@ class todo extends control
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $todoID));
if($this->viewType == 'xhtml') return print(js::locate($this->createLink('todo', 'view', "todoID=$todoID", 'html'), 'parent'));
if(isonlybody()) return print(js::closeModal('parent.parent'));
- return print(js::locate($this->createLink('my', 'todo', "type=all&userID=&status=all&orderBy=id_desc"), 'parent'));
+ return print(js::locate($this->createLink('my', 'todo', 'type=all&userID=&status=all&orderBy=id_desc'), 'parent'));
}
unset($this->lang->todo->typeList['cycle']);
$this->todoZen->buildCreateView($date);
- return 1;
}
/**
- * Batch create todo
+ * 批量创建待办。
+ * Batch create todo.
*
* @param string $date
* @access public
* @return void
*/
- public function batchCreate($date = 'today')
+ public function batchCreate(string $date = 'today')
{
if($date == 'today') $date = date(DT_DATE1, time());
+
if(!empty($_POST))
{
$todoIDList = $this->todo->batchCreate();
@@ -92,37 +91,17 @@ class todo extends control
/* Locate the browser. */
$date = str_replace('-', '', $this->post->date);
- if($date == '')
- {
- $date = 'future';
- }
- else if($date == date('Ymd'))
- {
- $date= 'today';
- }
+ if($date == '') $date = 'future';
+ if($date == date('Ymd')) $date= 'today';
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'idList' => $todoIDList));
if(isonlybody()) return print(js::reload('parent.parent'));
- return print(js::locate($this->createLink('my', 'todo', "type=$date"), 'parent'));
+ return print(js::locate($this->createLink('my', 'todo', "type={$date}"), 'parent'));
}
unset($this->lang->todo->typeList['cycle']);
- /* Set Custom*/
- foreach(explode(',', $this->config->todo->list->customBatchCreateFields) as $field) $customFields[$field] = $this->lang->todo->$field;
-
- $this->view->customFields = $customFields;
- $this->view->showFields = $this->config->todo->custom->batchCreateFields;
-
- $this->view->title = $this->lang->todo->common . $this->lang->colon . $this->lang->todo->batchCreate;
- $this->view->position[] = $this->lang->todo->common;
- $this->view->position[] = $this->lang->todo->batchCreate;
- $this->view->date = (int)$date == 0 ? $date : date('Y-m-d', strtotime($date));
- $this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta);
- $this->view->time = date::now();
- $this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted|noempty');
-
- $this->display();
+ $this->todoZen->buildBatchCreateView($date);
}
/**
@@ -176,19 +155,24 @@ class todo extends control
*
* @param string $from example:myTodo, todoBatchEdit.
* @param string $type
- * @param int $userID
+ * @param string $userID
* @param string $status
* @access public
- * @return void
*/
public function batchEdit(string $from = '', string $type = 'today', string $userID = '', string $status = 'all')
{
+ $formData = form::data($this->config->todo->batchEdit->form);
+ $userID = (int)$userID;
+
/* Get form data for my-todo. */
- if($from == 'myTodo') $this->todoZen->batchEditFromMyTodo($type, $userID, $status);
+ if($from == 'myTodo') $this->todoZen->batchEditFromMyTodo($formData, $type, $userID, $status);
if($from == 'todoBatchEdit')
{
- $formData = form::data($this->config->todo->batchEdit->form);
- $this->todoZen->batchEditFromTodoBatchEdit($formData);
+ $todos = $this->todoZen->beforeBatchEdit($formData);
+ $allChanges = $this->todo->batchUpdate($todos, $formData->data->todoIDList);
+ $this->todoZen->afterBatchEdit($allChanges);
+
+ return print(js::locate($this->session->todoList, 'parent'));
}
}
@@ -318,7 +302,7 @@ class todo extends control
$account = $this->app->user->account;
if($todo->private and $todo->account != $account) return print(js::error((string)$this->lang->todo->thisIsPrivate) . (string)js::locate('back'));
- if(!isonlybody()) $this->todoZen->setSessionLink($this->app->getURI(true));
+ if(!isonlybody()) $this->todoZen->setSessionUri($this->app->getURI(true));
/* Fix bug #936. */
if($account != $todo->account and $account != $todo->assignedTo and !common::hasPriv('my', 'team'))
@@ -498,7 +482,7 @@ class todo extends control
list($todos, $fields) = $this->todoZen->exportTodoInfo((array)$todos, (string)$this->config->todo->list->exportFields, $todoLang);
list($users, $bugs, $stories, $tasks, $testTasks) = $this->todoZen->exportAssociated('default', $account);
- $times = date::buildTimeList((string)$configTime->begin, (string)$configTime->end, (string)$configTime->delta);
+ $times = date::buildTimeList((int)$configTime->begin, (int)$configTime->end, (int)$configTime->delta);
$assemble = new stdClass();
$assemble->users = $users;
@@ -506,12 +490,13 @@ class todo extends control
$assemble->stories = $stories;
$assemble->tasks = $tasks;
$assemble->testTasks = $testTasks;
- if($this->config->edition == 'max'){
+ if($this->config->edition == 'max')
+ {
$iroData = $this->todoZen->exportInfo((string)$this->config->edition, $account);
$assemble->issues = $iroData[0];
$assemble->risks = $iroData[1];
$assemble->opportunities = $iroData[2];
- };
+ }
if(isset($this->config->qcVersion)) $assemble->reviews = $this->todoZen->exportInfo('qcVersion', $account);
$todos = $this->todoZen->assembleExportData((array)$todos, $assemble, $todoLang, (array)$times);
diff --git a/module/todo/css/assignto.ui.css b/module/todo/css/assignto.ui.css
new file mode 100644
index 0000000000..281271d2a6
--- /dev/null
+++ b/module/todo/css/assignto.ui.css
@@ -0,0 +1,2 @@
+.form-row .items-center {align-items: center;}
+.form-row .form-group.pl-3 {padding-left: 0.75rem;}
diff --git a/module/todo/css/common.ui.css b/module/todo/css/common.ui.css
new file mode 100644
index 0000000000..f63711e746
--- /dev/null
+++ b/module/todo/css/common.ui.css
@@ -0,0 +1,10 @@
+.private-row .checkbox-primary {margin-top: 5px;}
+.every-checkbox .checkbox-primary {width: 50px;}
+.cycle-config .tab-content>.tab-pane {padding-left: 0; padding-right: 0;}
+.cycle-config .tab-content>.tab-pane:first-child,
+.cycle-config .tab-content>.input-group {width: 44.5%;}
+.switch-time {min-height: 32px;}
+.form-row .form-group.align-center {align-items: center;}
+#nameInputBox {width: 80%;}
+#nameInputBox .form-control {width: 99.8%;}
+
diff --git a/module/todo/js/common.ui.js b/module/todo/js/common.ui.js
new file mode 100644
index 0000000000..6b2174ae3e
--- /dev/null
+++ b/module/todo/js/common.ui.js
@@ -0,0 +1,192 @@
+/**
+ * 切换日期选择的禁用状态。
+ * Toggle the disabled state of the date select.
+ *
+ * @param object switcher
+ * @return void
+ */
+function toggleDateTodo(switcher)
+{
+ $('#date').prop('disabled', switcher.checked);
+}
+
+/**
+ * Load data.
+ * @param type $type Type of selected todo.
+ * @param id $id ID of selected todo.
+ * @param objectID $objectID ID of the closed todo type.
+ * @return void
+ */
+function loadList(type, id, objectID)
+{
+ if(id)
+ {
+ divClass = '.name-box' + id;
+ divID = '#nameBox' + id;
+ }
+ else
+ {
+ divClass = '.name-box';
+ divID = '#nameBox';
+ }
+ id = id ? id : '';
+ var param = 'userID=' + userID + '&id=' + id;
+ if(type == "task") param += '&status=wait,doing';
+ if(defaultType && type == defaultType && objectID != 0) param += '&objectID=' + objectID;
+
+ if(moduleList.indexOf(type) !== -1)
+ {
+ link = '/index.php?m=' + type + '&f=' + objectsMethod[type] + '&' + param + '&t=html';
+ $.get(link, function(data, status)
+ {
+ if(data.length != 0)
+ {
+ $(divClass).find('#nameInputBox').html(data).find('select').chosen();
+ if(config.currentMethod == 'edit' || type == 'feedback') $(divClass).find('select').val(objectID).trigger('chosen:updated');
+ if($(divClass + " select").val() == null) $(divClass + " select").attr("data-placeholder", noOptions.replace("%s", chosenType[type])).trigger('chosen:updated');
+ }
+ else
+ {
+ $(divClass).html("").find('select').chosen();
+ }
+ });
+ }
+ else
+ {
+ $(divClass).html($(divID).html());
+ }
+
+ if(nameBoxLabel) return;
+ var formLabel = type == 'custom' ||(vision && vision == 'rnd') ? nameBoxLabel.custom : nameBoxLabel.objectID;
+ $('#nameBox .form-label').text(formLabel);
+}
+
+/**
+ * 选择开始时间后,自动给出默认终止时间。
+ * After selecting the start time, the default end time is automatically given.
+ *
+ * @return viod
+ */
+function selectNext()
+{
+ $("#end ")[0].selectedIndex = $("#begin ")[0].selectedIndex + 3;
+ $('#end').trigger('chosen:updated');
+}
+
+function setBeginsAndEnds(i, beginOrEnd)
+{
+ if(!i)
+ {
+ for(j = 0; j < batchCreateNum; j++)
+ {
+ if(j != 0) $("#begins" + j)[0].selectedIndex = $("#ends" + (j - 1))[0].selectedIndex;
+ $("#ends" + j)[0].selectedIndex = $("#begins" + j)[0].selectedIndex + 3;
+ $("#begins" + j, "#ends" + j).trigger('chosen:updated');
+ }
+ }
+ else
+ {
+ if(beginOrEnd == 'begin')
+ {
+ $("#ends" + i)[0].selectedIndex = $("#begins" + i)[0].selectedIndex + 3;
+ $("#ends" + i).trigger('chosen:updated');
+ }
+
+ if(batchCreateNum)
+ {
+ for(j = i+1; j < batchCreateNum; j++)
+ {
+ $("#begins" + j)[0].selectedIndex = $("#ends" + (j - 1))[0].selectedIndex;
+ $("#ends" + j)[0].selectedIndex = $("#begins" + j)[0].selectedIndex + 3;
+ $("#begins" + j, "#ends" + j).trigger('chosen:updated');
+ }
+ }
+ }
+}
+
+function switchTimeList(number)
+{
+ if($('#switchTime' + number).prop('checked'))
+ {
+ $('#begins' + number, '#ends' + number).attr('disabled', 'disabled').trigger('chosen:updated');
+ }
+ else
+ {
+ $('#begins' + number, '#ends' + number).removeAttr('disabled').trigger('chosen:updated');
+ }
+}
+
+function switchDateFeature(switcher)
+{
+ if(switcher.checked)
+ {
+ $('#begin, #end').attr('disabled','disabled').trigger('chosen:updated');
+ }
+ else
+ {
+ $('#begin, #end').removeAttr('disabled').trigger('chosen:updated');
+ }
+}
+
+/**
+ * 周期待办切换指定复选框时的交互展示。
+ * Interactive display when switching the specified checkbox for cycle.
+ *
+ * @param object switcher
+ * @return void
+ */
+function showSpecifiedDate(switcher)
+{
+ if(switcher.checked)
+ {
+ $('#everyInput').attr('disabled','disabled');
+ $('.specify').removeClass('hidden');
+ $('.every').addClass('hidden')
+ $('#configEvery').prop('checked', false);
+ }
+}
+
+/**
+ * 切换周期复选框的回调函数,用于页面交互展示。
+ * Switch the cycle checkbox for page interactive display.
+ *
+ * @param object switcher
+ * @return void
+ */
+function showEvery(switcher)
+{
+ if(switcher.checked)
+ {
+ $('#everyInput').removeAttr('disabled');
+ $('.specify').addClass('hidden');
+ $('.every').removeClass('hidden');
+ $('#cycleYear').removeAttr('checked');
+ $('#configSpecify, #configEvery').prop('checked', false);
+ }
+}
+
+/**
+ * 周期设置为天并为指定时,更改月份时获取天数。
+ * When the cycle is set to days and specified, obtain the number of days when changing the month.
+ *
+ * @param int $specifiedMonth
+ * @return void
+ */
+function setDays(specifiedMonth)
+{
+ /* Get last day in specified month. */
+ var date = new Date();
+ date.setMonth(specifiedMonth);
+ var month = date.getMonth() + 1;
+ date.setMonth(month);
+ date.setDate(0);
+ var specifiedMonthLastDay = date.getDate();
+
+ $('#specifiedDay').empty('');
+ for(var i = 1; i <= specifiedMonthLastDay; i++)
+ {
+ html = "";
+
+ $('#specifiedDay').append(html);
+ }
+}
diff --git a/module/todo/js/create.ui.js b/module/todo/js/create.ui.js
new file mode 100644
index 0000000000..fbb5e05204
--- /dev/null
+++ b/module/todo/js/create.ui.js
@@ -0,0 +1,60 @@
+/**
+ * 切换周期类型,用于展示周期类型的交互。
+ * Toggle cycle, used to display the interaction of cycle.
+ *
+ * @param object tab
+ * @return void
+ */
+function toggleCycle(switcher)
+{
+ if(switcher.checked)
+ {
+ $('#date').attr('disabled','disabled');
+ $('.cycle-config').removeClass('hidden');
+ $('#switchDate').closest('.checkbox-primary').addClass('hidden');
+ $('#type').closest('.form-row').addClass('hidden');
+ $('#type').val('custom');
+ loadList('custom'); //Fix bug 3278.
+ }
+ else
+ {
+ $('#date').removeAttr('disabled');
+ $('.cycle-config').addClass('hidden');
+ $('#switchDate').closest('.checkbox-primary').removeClass('hidden');
+ $('#type').closest('.form-row').removeClass('hidden');
+ }
+}
+
+/**
+ * 更改待办日期。
+ * Change todo date.
+ *
+ * @param object tab
+ * @return void
+ */
+function changeCreateDate(dateInput)
+{
+ var selectTime = $(dateInput).val() != today ? start : nowTime;
+ $('#begin').val(selectTime);
+ $('#begin').trigger("chosen:updated");
+ selectNext();
+}
+
+/**
+ * 切换标签页,用于更新标签页的样式和更新类型。
+ * Toggle tabs to update the style and type.
+ *
+ * @param object tab
+ * @return void
+ */
+function toggleNavTabs(tab)
+{
+ $(tab).parent().siblings().find('a').prop('class', '');
+ $(tab).addClass('active');
+ if($(tab).data('type'))$('input[id*=type][id*=config]').val($(tab).data('type'));
+}
+
+function changeType(typeSelect)
+{
+ loadList($(typeSelect).find('select').val(), '');
+}
diff --git a/module/todo/model.php b/module/todo/model.php
index fb56be1fd8..2e6375ed97 100755
--- a/module/todo/model.php
+++ b/module/todo/model.php
@@ -17,12 +17,13 @@ class todoModel extends model
* Create todo data.
*
* @param object $todo
+ * @param object $formData
* @access public
* @return int|false
*/
- public function create(object $todo): int|false
+ public function create(object $todo, object $formData): int|false
{
- $processedTodo = $this->todoTao->processCreateData($todo);
+ $processedTodo = $this->todoTao->processCreateData($todo, $formData);
if(!$processedTodo) return false;
$todoID = $this->todoTao->insert($processedTodo);
@@ -149,80 +150,43 @@ class todoModel extends model
}
/**
- * Batch update todos.
+ * 更新批量编辑待办数据。
+ * Update batch edit todo data.
*
- * @access public
- * @return array
+ * @param array $todos
+ * @param array $todoIdList
+ * @access protected
+ * @return array|int
*/
- public function batchUpdate()
+ public function batchUpdate(array $todos, array $todoIdList): array|int
{
- $todos = array();
+ if(empty($todos)) return $todos;
+
$allChanges = array();
- $data = fixer::input('post')->get();
- $todoIDList = $this->post->todoIDList ? $this->post->todoIDList : array();
- if(!empty($todoIDList))
+ /* Initialize todos from the post data. */
+ $oldTodos = $this->getTodosByIdList($todoIdList);
+ foreach($todos as $todoID => $todo)
{
- /* Initialize todos from the post data. */
- $oldTodos = $this->dao->select('*')->from(TABLE_TODO)->where('id')->in(array_keys($todos))->fetchAll('id');
- foreach($todoIDList as $todoID)
+ $oldTodo = $oldTodos[$todoID];
+ if(in_array($todo->type, $this->config->todo->moduleList)) $oldTodo->name = '';
+ $this->updateTodoDataByID($todoID, $todo);
+
+ if($oldTodo->status != 'done' and $todo->status == 'done') $this->loadModel('action')->create('todo', $todoID, 'finished', '', 'done');
+
+ if(!dao::isError())
{
- $oldTodo = $oldTodos[$todoID];
-
- $todo = new stdclass();
- $todo->date = $data->dates[$todoID];
- $todo->type = $data->types[$todoID];
- $todo->pri = $data->pris[$todoID];
- $todo->status = $data->status[$todoID];
- $todo->name = !in_array($todo->type, $this->config->todo->moduleList) ? $data->names[$todoID] : '';
- $todo->begin = isset($data->begins[$todoID]) ? $data->begins[$todoID] : 2400;
- $todo->end = isset($data->ends[$todoID]) ? $data->ends[$todoID] : 2400;
- $todo->assignedTo = isset($data->assignedTos[$todoID]) ? $data->assignedTos[$todoID] : $oldTodo->assignedTo;
-
- if(in_array($todo->type, $this->config->todo->moduleList))
+ if(($this->config->edition == 'biz' || $this->config->edition == 'max') && $todo->type == 'feedback' && $todo->objectID && !isset($feedbacks[$todo->objectID]))
{
- $todo->objectID = isset($data->{$this->config->todo->objectList[$todo->type]}[$todoID]) ? $data->{$this->config->todo->objectList[$todo->type]}[$todoID] : 0;
+ $feedbacks[$todo->objectID] = $todo->objectID;
+ $this->loadModel('feedback')->updateStatus('todo', $todo->objectID, $todo->status);
}
- if($todo->end < $todo->begin) return print(js::alert(sprintf($this->lang->error->gt, $this->lang->todo->end, $this->lang->todo->begin)));
- $todos[$todoID] = $todo;
+ $allChanges[$todoID] = common::createChanges($oldTodo, $todo);
}
-
- foreach($todos as $todoID => $todo)
+ else
{
- $oldTodo = $oldTodos[$todoID];
- if(in_array($todo->type, $this->config->todo->moduleList)) $oldTodo->name = '';
- $this->dao->update(TABLE_TODO)->data($todo)
- ->autoCheck()
- ->checkIF(!in_array($todo->type, $this->config->todo->moduleList), $this->config->todo->edit->requiredFields, 'notempty')
- ->checkIF($todo->type == 'bug' and $todo->objectID == 0, 'objectID', 'notempty')
- ->checkIF($todo->type == 'task' and $todo->objectID == 0, 'objectID', 'notempty')
- ->checkIF($todo->type == 'story' and $todo->objectID == 0, 'objectID', 'notempty')
- ->checkIF($todo->type == 'issue' and $todo->objectID == 0, 'objectID', 'notempty')
- ->checkIF($todo->type == 'risk' and $todo->objectID == 0, 'objectID', 'notempty')
- ->checkIF($todo->type == 'opportunity' and $todo->objectID == 0, 'objectID', 'notempty')
- ->checkIF($todo->type == 'review' and $todo->objectID == 0, 'objectID', 'notempty')
- ->checkIF($todo->type == 'testtask' and $todo->objectID == 0, 'objectID', 'notempty')
- ->checkIF($todo->type == 'feedback' and $todo->objectID == 0, 'objectID', 'notempty')
- ->where('id')->eq($todoID)
- ->exec();
-
- if($oldTodo->status != 'done' and $todo->status == 'done') $this->loadModel('action')->create('todo', $todoID, 'finished', '', 'done');
-
- if(!dao::isError())
- {
- if(($this->config->edition == 'biz' || $this->config->edition == 'max') && $todo->type == 'feedback' && $todo->objectID && !isset($feedbacks[$todo->objectID]))
- {
- $feedbacks[$todo->objectID] = $todo->objectID;
- $this->loadModel('feedback')->updateStatus('todo', $todo->objectID, $todo->status);
- }
-
- $allChanges[$todoID] = common::createChanges($oldTodo, $todo);
- }
- else
- {
- return print(js::error('todo#' . $todoID . dao::getError(true)));
- }
+ return print(js::error('todo#' . $todoID . dao::getError(true)));
}
}
@@ -293,18 +257,9 @@ class todoModel extends model
$todo = $this->loadModel('file')->replaceImgURL((object)$todo, 'desc');
if($setImgSize) $todo->desc = $this->file->setImgSize($todo->desc);
- if($todo->type == 'story') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_STORY)->fetch('title');
- if($todo->type == 'task') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_TASK)->fetch('name');
- if($todo->type == 'bug') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_BUG)->fetch('title');
- if($todo->type == 'issue' and $this->config->edition == 'max') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_ISSUE)->fetch('title');
- if($todo->type == 'risk' and $this->config->edition == 'max') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_RISK)->fetch('name');
- if($todo->type == 'opportunity' and $this->config->edition == 'max') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_OPPORTUNITY)->fetch('name');
- if($todo->type == 'review' and $this->config->edition == 'max') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_REVIEW)->fetch('title');
- if($todo->type == 'testtask') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_TESTTASK)->fetch('name');
- if($todo->type == 'feedback') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_FEEDBACK)->fetch('title');
$todo->date = str_replace('-', '', $todo->date);
- return $todo;
+ return $this->todoTao->setTodoNameByType($todo);
}
/**
@@ -317,93 +272,21 @@ class todoModel extends model
* @param object $pager
* @param string $orderBy
* @access public
- * @return void
+ * @return array
*/
- public function getList($type = 'today', $account = '', $status = 'all', $limit = 0, $pager = null, $orderBy="date, status, begin")
+ public function getList(string $type = 'today', string $account = '', string|array $status = 'all', int $limit = 0, object $pager = null, string $orderBy="date, status, begin"): array
{
$this->app->loadClass('date');
$todos = array();
$type = strtolower($type);
- if($type == 'all' or $type == 'assignedtoother')
- {
- $begin = '1970-01-01';
- $end = '2109-01-01';
- }
- elseif($type == 'today')
- {
- $begin = date::today();
- $end = $begin;
- }
- elseif($type == 'yesterday')
- {
- $begin = date::yesterday();
- $end = $begin;
- }
- elseif($type == 'thisweek')
- {
- extract(date::getThisWeek());
- }
- elseif($type == 'lastweek')
- {
- extract(date::getLastWeek());
- }
- elseif($type == 'thismonth')
- {
- extract(date::getThisMonth());
- }
- elseif($type == 'lastmonth')
- {
- extract(date::getLastMonth());
- }
- elseif($type == 'thisseason')
- {
- extract(date::getThisSeason());
- }
- elseif($type == 'thisyear')
- {
- extract(date::getThisYear());
- }
- elseif($type == 'future')
- {
- $begin = '2030-01-01';
- $end = $begin;
- }
- elseif($type == 'before')
- {
- $begin = '1970-01-01';
- $end = date::today();
- }
- elseif($type == 'cycle')
- {
- $begin = $end = '';
- }
- else
- {
- $begin = $end = $type;
- }
+ $dateRange = $this->config->todo->dateRange[$type] ? $this->config->todo->dateRange[$type] : array('begin' => $type, 'end' => $type);
+ $begin = (string)$dateRange['begin'];
+ $end = (string)$dateRange['end'];
if(empty($account)) $account = $this->app->user->account;
- $stmt = $this->dao->select('*')->from(TABLE_TODO)
- ->where('deleted')->eq('0')
- ->andWhere('vision')->eq($this->config->vision)
- ->beginIF($type == 'assignedtoother')->andWhere('account', true)->eq($account)->fi()
- ->beginIF($type != 'assignedtoother')->andWhere('assignedTo', true)->eq($account)->fi()
- ->orWhere('finishedBy')->eq($account)
- ->orWhere('closedBy')->eq($account)
- ->markRight(1)
- ->beginIF($begin)->andWhere('date')->ge($begin)->fi()
- ->beginIF($end)->andWhere('date')->le($end)->fi()
- ->beginIF($status != 'all' and $status != 'undone')->andWhere('status')->in($status)->fi()
- ->beginIF($status == 'undone')->andWhere('status')->notin('done,closed')->fi()
- ->beginIF($type == 'cycle')->andWhere('cycle')->eq('1')->fi()
- ->beginIF($type != 'cycle')->andWhere('cycle')->eq('0')->fi()
- ->beginIF($type == 'assignedtoother')->andWhere('assignedTo')->notin(array($account, ''))->fi()
- ->orderBy($orderBy)
- ->beginIF($limit > 0)->limit($limit)->fi()
- ->page($pager)
- ->query();
+ $stmt = $this->todoTao->getListQuery($type, $account, $status, $begin, $end, $pager, $limit, $orderBy);
/* Set session. */
$sql = explode('WHERE', $this->dao->get());
@@ -412,15 +295,7 @@ class todoModel extends model
while($todo = $stmt->fetch())
{
- if($todo->type == 'story') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_STORY)->fetch('title');
- if($todo->type == 'task') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_TASK)->fetch('name');
- if($todo->type == 'bug') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_BUG)->fetch('title');
- if($todo->type == 'testtask') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_TESTTASK)->fetch('name');
- if($todo->type == 'issue' && $this->config->edition == 'max') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_ISSUE)->fetch('title');
- if($todo->type == 'risk' && $this->config->edition == 'max') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_RISK)->fetch('name');
- if($todo->type == 'opportunity' && $this->config->edition == 'max') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_OPPORTUNITY)->fetch('name');
- if($todo->type == 'review' && $this->config->edition == 'max') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_REVIEW)->fetch('title');
- if($todo->type == 'feedback' and $this->config->edition != 'open') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_FEEDBACK)->fetch('title');
+ $todo = $this->todoTao->setTodoNameByType($todo);
$todo->begin = date::formatTime($todo->begin);
$todo->end = date::formatTime($todo->end);
@@ -434,11 +309,14 @@ class todoModel extends model
}
/**
- * Get by id list.
+ * 通过包含一个或多个待办ID的列表获取待办列表,这个列表是以todoID为key、以todo对象为value的数组。
+ * 如果待办ID列表为空则返回所有待办。
+ * Get a array with todos which todoID as key, todo object as value by todo id list.
+ * Return all todos if the todo id list is empty.
*
* @param array $todoIDList
* @access public
- * @return object
+ * @return array
*/
public function getByList($todoIDList = 0)
{
@@ -448,27 +326,22 @@ class todoModel extends model
}
/**
+ * 判断当前动作是否可以点击。
* Judge an action is clickable or not.
*
- * @param object $todo
- * @param string $action
+ * @param object $todo
+ * @param string $action
* @access public
* @return bool
*/
- public static function isClickable($todo, $action)
+ public static function isClickable(object $todo, string $action): bool
{
$action = strtolower($action);
- if($action == 'finish')
+ if($action == 'finish' || $action == 'start')
{
if(!empty($todo->cycle)) return false;
- return $todo->status != 'done';
- }
-
- if($action == 'start')
- {
- if(!empty($todo->cycle)) return false;
- return $todo->status == 'wait';
+ return $action == 'finish' ? ($todo->status != 'done') : ($todo->status == 'wait');
}
return true;
@@ -578,15 +451,16 @@ class todoModel extends model
*/
public function assignTo(object $todo): bool
{
- $result = $this->todoTao->updateRow((int)$todo->id, $todo);
+ $todoID = (int)$todo->id;
+ $result = $this->todoTao->updateRow($todoID, $todo);
if(!$result) return false;
- $this->loadModel('action')->create('todo', (int)$todo->id, 'assigned', '', $todo->assignedTo);
+ $this->loadModel('action')->create('todo', $todoID, 'assigned', '', $todo->assignedTo);
return !dao::isError();
}
/**
- * 查询待办数量。
+ * 获取待办事项的数量。
* Get todo count.
*
* @param string $account
@@ -654,7 +528,7 @@ class todoModel extends model
if(($this->config->edition == 'biz' || $this->config->edition == 'max'))
{
$todo = $this->todoTao->fetch($todoID);
- $feedbackID = $todo->idvalue ?? '' ;
+ $feedbackID = $todo->objectID ? $todo->objectID : '' ;
if($feedbackID) $this->loadModel('feedback')->updateStatus('todo', $feedbackID, 'done');
}
return true;
@@ -690,4 +564,30 @@ class todoModel extends model
->beginIF($formData->rawdata->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi()
->orderBy($orderBy)->fetchAll('id');
}
+
+ /**
+ * 根据待办ID获取多条待办。
+ * Get todo data by id list.
+ *
+ * @param array $todoIdList
+ * @access public
+ * @return array
+ */
+ public function getTodosByIdList(array $todoIdList): array
+ {
+ return $this->todoTao->fetchRows($todoIdList);
+ }
+
+ /**
+ * 根据待办ID更新待办数据。
+ * Update todo data by id.
+ *
+ * @param array $todoIdList
+ * @access public
+ * @return bool
+ */
+ public function updateTodoDataByID(int $todoID, object $todo): bool
+ {
+ return $this->todoTao->updateRow($todoID, $todo);
+ }
}
diff --git a/module/todo/tao.php b/module/todo/tao.php
index b4396baac1..e026d6c8b0 100644
--- a/module/todo/tao.php
+++ b/module/todo/tao.php
@@ -16,6 +16,18 @@ class todoTao extends todoModel
return $this->dao->select('*')->from(TABLE_TODO)->where('id')->eq($todoID)->fetch();
}
+ /**
+ * 获取多条待办。
+ * Get a todo.
+ *
+ * @param array $todoIdList
+ * @return array
+ */
+ protected function fetchRows(array $todoIdList): array
+ {
+ return $this->dao->select('*')->from(TABLE_TODO)->where('id')->in(array_keys($todoIdList))->fetchAll('id');
+ }
+
/**
* 获取待办数量。
* Get todo count.
@@ -118,10 +130,11 @@ class todoTao extends todoModel
* Process the data for the todo to be created.
*
* @param object $todoData
+ * @param object $formData
* @access protected
* @return object|false
*/
- protected function processCreateData(object $todoData): object|false
+ protected function processCreateData(object $todoData, object $formData): object|false
{
if(!isset($todoData->pri) and in_array($todoData->type, $this->config->todo->moduleList) and !in_array($todoData->type, array('review', 'feedback')))
{
@@ -153,7 +166,7 @@ class todoTao extends todoModel
}
if(empty($todoData->cycle)) unset($todoData->config);
- return $this->loadModel('file')->processImgURL($todoData, $this->config->todo->editor->create['id'], $this->post->uid);
+ return $this->loadModel('file')->processImgURL($todoData, $this->config->todo->editor->create['id'], $formData->rawdata->uid);
}
/**
@@ -359,4 +372,94 @@ class todoTao extends todoModel
$this->dao->update(TABLE_TODO)->set('date')->eq($date)->where('id')->in($todoIdList)->exec();
return !dao::isError();
}
+
+ /**
+ * 获取用户的待办事项数量。
+ * Get todo count on the account.
+ *
+ * @param string $account
+ * @access protected
+ * @return int
+ */
+ protected function getTodoCountByAccount(string $account): int
+ {
+ return $this->dao->select('count(*) as count')->from(TABLE_TODO)
+ ->where('cycle')->eq('0')
+ ->andWhere('deleted')->eq('0')
+ ->andWhere('vision')->eq($this->config->vision)
+ ->andWhere('account', true)->eq($account)
+ ->orWhere('assignedTo')->eq($account)
+ ->orWhere('finishedBy')->eq($account)
+ ->markRight(1)
+ ->fetch('count');
+ }
+
+ /**
+ * 根据待办类型设置待办名称。
+ * Set todo name by its type.
+ *
+ * @param object $todo
+ * @access protected
+ * @return object
+ */
+ protected function setTodoNameByType(object $todo): object
+ {
+ if($todo->type == 'story') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_STORY)->fetch('title');
+ if($todo->type == 'task') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_TASK)->fetch('name');
+ if($todo->type == 'bug') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_BUG)->fetch('title');
+ if($todo->type == 'testtask') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_TESTTASK)->fetch('name');
+
+ if($this->config->edition == 'max')
+ {
+ if($todo->type == 'risk' ) $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_RISK)->fetch('name');
+ if($todo->type == 'issue') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_ISSUE)->fetch('title');
+ if($todo->type == 'review') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_REVIEW)->fetch('title');
+ if($todo->type == 'opportunity') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_OPPORTUNITY)->fetch('name');
+ }
+
+ if($this->config->edition == 'biz' || $this->config->edition == 'max')
+ {
+ if($todo->type == 'feedback') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_FEEDBACK)->fetch('title');
+ }
+
+ return $todo;
+ }
+
+ /**
+ * 构造待办列表查询语句。
+ * Build query for todo list.
+ *
+ * @param string $type
+ * @param string $account
+ * @param string|array $status
+ * @param string $begin
+ * @param string $end
+ * @param object $pager
+ * @param int $limit
+ * @param string $orderBy
+ * @access protected
+ * @return object
+ */
+ protected function getListQuery(string $type, string $account, array|string $status, string $begin, string $end, object $pager = null, int $limit, string $orderBy): object
+ {
+ return $this->dao->select('*')->from(TABLE_TODO)
+ ->where('deleted')->eq('0')
+ ->andWhere('vision')->eq($this->config->vision)
+ ->beginIF($type == 'assignedtoother')->andWhere('account', true)->eq($account)->fi()
+ ->beginIF($type != 'assignedtoother')->andWhere('assignedTo', true)->eq($account)->fi()
+ ->orWhere('finishedBy')->eq($account)
+ ->orWhere('closedBy')->eq($account)
+ ->markRight(1)
+ ->beginIF($begin)->andWhere('date')->ge($begin)->fi()
+ ->beginIF($end)->andWhere('date')->le($end)->fi()
+ ->beginIF($status != 'all' and $status != 'undone')->andWhere('status')->in($status)->fi()
+ ->beginIF($status == 'undone')->andWhere('status')->notin('done,closed')->fi()
+ ->beginIF($type == 'cycle')->andWhere('cycle')->eq('1')->fi()
+ ->beginIF($type != 'cycle')->andWhere('cycle')->eq('0')->fi()
+ ->beginIF($type == 'assignedtoother')->andWhere('assignedTo')->notin(array($account, ''))->fi()
+ ->orderBy($orderBy)
+ ->beginIF($limit > 0)->limit($limit)->fi()
+ ->page($pager)
+ ->query();
+ }
}
diff --git a/module/todo/test/model/batchupdate.php b/module/todo/test/model/batchupdate.php
index 08c4909ee9..d152182172 100755
--- a/module/todo/test/model/batchupdate.php
+++ b/module/todo/test/model/batchupdate.php
@@ -4,30 +4,44 @@ include dirname(__FILE__, 5) . "/test/lib/init.php";
include dirname(__FILE__, 2) . '/todo.class.php';
su('admin');
+function initData()
+{
+ zdTable('todo')->config('batchupdate')->gen(5);
+}
+
/**
title=测试 todoModel->batchUpdate();
+timeout=0
cid=1
-pid=1
-
-批量修改todo类型 >> type,task,custom
-批量修改todo优先级 >> pri,2,1
-批量修改todo状态 >> status,wait,doing
*/
-$types = array('1' => 'custom', '2' => 'bug', '3' => 'custom');
-$pris = array('1' => '1', '2' => '1', '3' => '3');
-$status = array('1' => 'doing', '2' => 'doing', '3' => 'done');
-$bugs = array('2' => '1');
-$tasks = array('3' => '2');
+initData();
-$changeType = array('types' => $types, 'bugs' => $bugs);
-$changePri = array('pris' => $pris, 'bugs' => $bugs, 'tasks' => $tasks);
-$changeStatus = array('status' => $status, 'bugs' => $bugs, 'tasks' => $tasks);
+$todos = array();
+$todos[1] = new stdClass();
+$todos[2] = new stdClass();
+$todos[3] = new stdClass();
+$changeType = $todos;
+$changeType[1]->type = 'bug';
+$changeType[1]->objectID = 1;
+
+$todos = array();
+$todos[1] = new stdClass();
+$todos[2] = new stdClass();
+$todos[3] = new stdClass();
+$changePri = $todos;
+$changePri[2]->pri = 1;
+
+$todos = array();
+$todos[1] = new stdClass();
+$todos[2] = new stdClass();
+$todos[3] = new stdClass();
+$changeStatus = $todos;
+$changeStatus[3]->status = 'doing';
$todo = new todoTest();
-
-r($todo->batchUpdateTest($changeType, '3')) && p('0:field,old,new') && e('type,task,custom'); // 批量修改todo类型
-r($todo->batchUpdateTest($changePri, '2')) && p('0:field,old,new') && e('pri,2,1'); // 批量修改todo优先级
-r($todo->batchUpdateTest($changeStatus, '1')) && p('0:field,old,new') && e('status,wait,doing'); // 批量修改todo状态
+r($todo->batchUpdateTest($changeType, 1)) && p('0:field,old,new') && e('type,custom,bug'); // 批量修改todo类型
+r($todo->batchUpdateTest($changePri, 2)) && p('0:field,old,new') && e('pri,3,1'); // 批量修改todo优先级
+r($todo->batchUpdateTest($changeStatus, 3)) && p('0:field,old,new') && e('status,wait,doing'); // 批量修改todo状态
\ No newline at end of file
diff --git a/module/todo/test/model/close.php b/module/todo/test/model/close.php
index 3f76b7abdb..c63a4d93f7 100755
--- a/module/todo/test/model/close.php
+++ b/module/todo/test/model/close.php
@@ -21,3 +21,6 @@ zdTable('todo')->config('close')->gen(1);
r($tester->todo->getByID(1)) && p('status') && e('wait');
r($tester->todo->close(1)) && p() && e(1);
r($tester->todo->getByID(1)) && p('status') && e('closed');
+
+r($tester->todo->close(1)) && p() && e(1);
+r($tester->todo->getByID(1)) && p('status') && e('closed');
diff --git a/module/todo/test/model/create.php b/module/todo/test/model/create.php
index 5fcaa8ac2e..9ad2c7b3ec 100755
--- a/module/todo/test/model/create.php
+++ b/module/todo/test/model/create.php
@@ -1,105 +1,63 @@
#!/usr/bin/env php
id->range('1');
- $todo->name->prefix("待办")->range('1');
- $todo->date->range('`2023-04-23`');
- $todo->type->range('custom');
- $todo->gen(1, '', true);
-}
+su('admin');
/**
title=测试 todoModel->create();
+timeout=0
cid=1
-pid=1
+
+- 执行todoTest模块的createTest方法,参数是$todoWithoutName, $formData @0
+
+- 执行todoTest模块的createTest方法,参数是$todoInvalidEnd, $formData @0
+
+- 执行todoTest模块的createTest方法,参数是$todo, $formData @2
+
+- 执行todoTest模块的createTest方法,参数是$todoWithCycle, $formData @3
*/
-$accountList = array('admin', 'dev1', 'test1');
-
-$b_noname = new stdclass();
-$b_noname->name = '';
-$b_noname->date = 'today';
-$b_noname->type = 'custom';
-
-$todo1 = new stdclass();
-$todo1->name = '时间待定的月周期待办';
-$todo1->type = 'custom';
-$todo1->date = '+3 days';
-$todo1->config = array('day' => '', 'specify' => array('month' => 0, 'day' => 1), 'month' => array(1,3,5), 'type' => 'month', 'beforeDays' => 2, 'end' => '2025-01-01');
-
-$todo2 = new stdclass();
-$todo2->name = 'bug待办';
-$todo2->type = 'bug';
-$todo2->date = 'today';
-$todo2->bug = '313';
-$todo2->status = 'doing';
-$todo2->uid = '313';
-
-$todo3 = new stdclass();
-$todo3->name = 'task待办';
-$todo3->type = 'task';
-$todo3->date = 'today';
-$todo3->task = '1';
-$todo3->status = 'done';
-$todo3->uid = '1';
-
-$todo4 = new stdclass();
-$todo4->name = 'story待办';
-$todo4->type = 'story';
-$todo4->date = 'today';
-$todo4->story = '1';
-$todo4->status = 'closed';
-$todo4->uid = '1';
-
-$todo = new todoTest();
-
global $tester;
$tester->loadModel('todo');
-initData();
+zdTable('todo')->config('create')->gen(5);
+$today = date('Y-m-d');
-$todoWithoutName = new stdclass;
+$formData = new stdClass;
+$formData->rawdata = new stdclass;
+$formData->rawdata->uid = '';
+
+$todo = new stdclass;
+$todo->name = 'TODO Create Test';
+$todo->account = 'admin';
+$todo->date = $today;
+$todo->type = 'custom';
+$todo->begin = '0800';
+$todo->end = '1700';
+$todo->assignedTo = 'admin';
+$todo->assignedBy = 'admin';
+$todo->assignedDate = $today;
+
+$todoWithoutName = clone $todo;
$todoWithoutName->name = '';
-$todoWithoutName->date = date('Y-m-d');
-$todoWithoutName->type = 'custom';
-$todoInvalidDate = new stdclass;
-$todoInvalidDate->name = 'todoInvalidDate';
-$todoInvalidDate->date = 'today';
-$todoInvalidDate->type = 'custom';
+$todoInvalidEnd = clone $todo;
+$todoInvalidEnd->name = 'todoInvalidDate';
+$todoInvalidEnd->begin = '1000';
+$todoInvalidEnd->end = '0800';
-$todoValid = new stdclass;
-$todoValid->name = 'todoValid';
-$todoValid->date = date('Y-m-d');
-$todoValid->type = 'custom';
+$todoWithCycle = clone $todo;
+$todoWithCycle->type = 'cycle';
+$todoWithCycle->cycle = 1;
+$todoWithCycle->config = array('day' => 1, 'specify' => array('month' => 0, 'day' => 1), 'type' => 'day', 'beforeDays' => 1, 'end' => '');
+$todoWithCycle->objectID = 0;
-$todoValid1 = new stdclass;
-$todoValid1->name = 'todoValid1';
-$todoValid1->date = date('Y-m-d');
-$todoValid1->type = 'custom';
-
-/**
- * 1. 如果r函数返回的是一个复杂的结构,比如混合内容的数组或者嵌套的数组,p函数是无法获取返回值中的某些特定值的,需要自己编写助手函数,比如在../todo.class.php中编写。
- * 2. 如果ztf执行没有生成注释,需要检查php脚本是否执行报错,建议先使用php执行编写的测试用例再用ztf执行。
- */
-r($tester->todo->create($todoValid)) && p() && e('2');
-r($tester->todo->create($todoWithoutName)) && p() && e('0');
-r($tester->todo->create($todoInvalidDate)) && p() && e('0');
-r($tester->todo->create($todoValid1)) && p() && e('3');
-exit(0);
-
-r($todo->createTest($accountList[0], $b_noname)) && p() && e('『待办名称』不能为空。');
-r($todo->createTest($accountList[1], $todo1)) && p('name,type,status') && e('时间待定的月周期待办,custom,wait');
-r($todo->createTest($accountList[2], $todo2)) && p('name,type,status') && e('测试单转Bug13,bug,doing');
-r($todo->createTest($accountList[0], $todo3)) && p('name,type,status') && e('开发任务11,task,done');
-r($todo->createTest($accountList[0], $todo4)) && p('name,type,status') && e('用户需求1,story,closed');
+$todoTest = new todoTest();
+r($todoTest->createTest($todoWithoutName, $formData)) && p() && e('0');
+r($todoTest->createTest($todoInvalidEnd, $formData)) && p() && e('0');
+r($todoTest->createTest($todo, $formData)) && p() && e('6');
+r($todoTest->createTest($todoWithCycle, $formData)) && p() && e('7');
diff --git a/module/todo/test/model/editdate.php b/module/todo/test/model/editdate.php
index 7cf70fc4b9..d23a0f4274 100755
--- a/module/todo/test/model/editdate.php
+++ b/module/todo/test/model/editdate.php
@@ -1,20 +1,10 @@
#!/usr/bin/env php
id->range('1-5');
- $project->name->prefix("自定义的待办")->range('1-5');
- $project->type->range(1);
- $project->status->range("wait,doing,done,closed,closed");
- $project->gen(5);
-}
-
-
/**
title=测试 todoModel->editDateTest();
@@ -27,8 +17,7 @@ pid=1
global $tester;
$tester->loadModel('todo');
-initData();
+zdTable('todo')->config('editdate')->gen(5);
-r($tester->todo->editDate(array(1), '2023-06-07')) && p() && e(true); // 获取id为1的待办的日期
-r($tester->todo->editDate(array(2, 3), '2023-04-27')) && p() && e(true); // 获取id 为1,2待办的日期
-#r($tester->todo->editDate(array(9), '2023-04-17')) && p() && e('0'); // 修改不存在的待办的日期
+r($tester->todo->editDate(array(1), '2023-06-07')) && p() && e(true); // 修改id为1的待办的日期
+r($tester->todo->editDate(array(2, 3), '2023-04-27')) && p() && e(true); // 修改id为2,3的待办的日期
diff --git a/module/todo/test/model/getbyid.php b/module/todo/test/model/getbyid.php
index 24a46acdd2..c4937ce757 100755
--- a/module/todo/test/model/getbyid.php
+++ b/module/todo/test/model/getbyid.php
@@ -1,23 +1,19 @@
#!/usr/bin/env php
id->range('1-5');
- $project->name->prefix("自定义的待办")->range('1-5');
- $project->type->range(1);
- $project->status->range("wait,doing,done,closed,closed");
- $project->gen(5);
+ zdTable('todo')->config('getbyid')->gen(5);
}
-
/**
-title=测试 todoModel->getById();
+title=测试 todoModel->getByID();
cid=1
pid=1
@@ -29,7 +25,6 @@ $todo = new todoTest();
initData();
-r($todo->getByIdTest($todoIDList[0])) && p('name,status') && e('自定义的待办1,wait'); // 获取id为1的todo信息
-r($todo->getByIdTest($todoIDList[1])) && p('name,status') && e('自定义的待办2,doing'); // 获取id为2的todo信息
-r($todo->getByIdTest($todoIDList[3])) && p('name,status') && e('自定义的待办5,closed'); // 获取id为5的todo信息
-r($todo->getByIdTest($todoIDList[4])) && p() && e('0'); // 获取id不存在的todo信息
+r($todo->getByIDTest($todoIDList[0])) && p('name,status') && e('自定义的待办1,wait'); // 获取id为1的todo信息
+r($todo->getByIDTest($todoIDList[1])) && p('name,status') && e('自定义的待办2,doing'); // 获取id为2的todo信息
+r($todo->getByIDTest($todoIDList[3])) && p('name,status') && e('自定义的待办5,closed'); // 获取id为5的todo信息
diff --git a/module/todo/test/model/getbylist.php b/module/todo/test/model/getbylist.php
index 426f22dd00..3c5ce1f7ee 100755
--- a/module/todo/test/model/getbylist.php
+++ b/module/todo/test/model/getbylist.php
@@ -10,18 +10,16 @@ title=测试 todoModel->getByList();
cid=1
pid=1
-获取todo 1 2 3 4的名称 >> 自定义1的待办,BUG2的待办,任务3的待办,需求4的待办
-获取todo 5 6 7 8的名称 >> 测试单5的待办,自定义6的待办,BUG7的待办,任务8的待办
-获取todo 9 10 11 12的名称 >> 需求9的待办,测试单10的待办,自定义11的待办,BUG12的待办
-
*/
-$todoIDList1 = array('1', '2', '3', '4');
-$todoIDList2 = array('5', '6', '7', '8');
-$todoIDList3 = array('9', '10', '11', '12');
+$todoIDList1 = array('1');
+$todoIDList2 = array('1', '2', '3', '4');
+$todoIDList3 = array('9', '10', '11', '12'); /* Test not existed items. */
+$todoIDList4 = array(); /* Test empty todoIDList. */
$todo = new todoTest();
-r($todo->getByListTest($todoIDList1)) && p() && e('自定义1的待办,BUG2的待办,任务3的待办,需求4的待办'); // 获取todo 1 2 3 4的名称
-r($todo->getByListTest($todoIDList2)) && p() && e('测试单5的待办,自定义6的待办,BUG7的待办,任务8的待办'); // 获取todo 5 6 7 8的名称
-r($todo->getByListTest($todoIDList3)) && p() && e('需求9的待办,测试单10的待办,自定义11的待办,BUG12的待办'); // 获取todo 9 10 11 12的名称
\ No newline at end of file
+r($todo->getByListTest($todoIDList1)) && p() && e('1');
+r($todo->getByListTest($todoIDList2)) && p() && e('1234');
+r($todo->getByListTest($todoIDList3)) && p() && e('');
+r($todo->getByListTest($todoIDList4)) && p() && e('12345');
diff --git a/module/todo/test/model/yaml/batchupdate/batchupdate.yaml b/module/todo/test/model/yaml/batchupdate/batchupdate.yaml
new file mode 100644
index 0000000000..309bf7528b
--- /dev/null
+++ b/module/todo/test/model/yaml/batchupdate/batchupdate.yaml
@@ -0,0 +1,33 @@
+title: zt_batchupdate
+author: lanzongjun
+version: "1.0"
+fields:
+ - field: id
+ range: 1-5
+ - field: account
+ range: 'admin'
+ - field: date
+ range: 1-9
+ prefix: '2023-04-2'
+ - field: begin
+ range: 1000-1100
+ - field: end
+ range: 1200-1300
+ - field: type
+ range: 'custom'
+ - field: cycle
+ range: 0
+ - field: pri
+ range: 3
+ - field: name
+ range: 1-5
+ prefix: '我的待办'
+ - field: desc
+ range: 1-5
+ prefix: '这是待办描述'
+ - field: status
+ range: 'wait'
+
+
+
+
diff --git a/module/todo/test/model/yaml/close/close.yaml b/module/todo/test/model/yaml/close/close.yaml
index ff3b81c26e..9caadba7e6 100644
--- a/module/todo/test/model/yaml/close/close.yaml
+++ b/module/todo/test/model/yaml/close/close.yaml
@@ -13,3 +13,7 @@ fields:
range: wait
- field: id
range: 1
+ - field: finishedDate
+ range: '`2023-04-23`'
+ - field: closedDate
+ range: '`2023-04-23`'
diff --git a/module/todo/test/model/yaml/create/create.yaml b/module/todo/test/model/yaml/create/create.yaml
new file mode 100644
index 0000000000..d5f4baff63
--- /dev/null
+++ b/module/todo/test/model/yaml/create/create.yaml
@@ -0,0 +1,31 @@
+title: Create todos for todoModel::create UTC.
+desc: Create todos for todoModel::create UTC.
+author: xushenjie
+version: 1.0.0
+
+fields:
+ - field: account
+ range: 'admin'
+ - field: name
+ range: 1-5
+ prefix: '待办'
+ - field: date
+ range: 1-9
+ prefix: '2023-04-2'
+ - field: type
+ range: 'custom'
+ - field: begin
+ range: 1000-1100
+ - field: end
+ range: 1200-1300
+ - field: assignedTo
+ range: 'admin'
+ - field: desc
+ range: 1-5
+ prefix: '待办描述'
+ - field: status
+ range: 'wait,doing,doing,doing,wait'
+ - field: objectID
+ range: 0
+ - field: assignedBy
+ range: 'admin'
diff --git a/module/todo/test/model/yaml/editdate/editdate.yaml b/module/todo/test/model/yaml/editdate/editdate.yaml
new file mode 100644
index 0000000000..25a52e824e
--- /dev/null
+++ b/module/todo/test/model/yaml/editdate/editdate.yaml
@@ -0,0 +1,13 @@
+title: Create todos for todoModel::close UTC.
+desc: Create todos for todoModel::close UTC.
+version: 1.0.0
+
+fields:
+ - field: id
+ range: 1-5
+ - field: date
+ range: '`2023-05-03`'
+ - field: type
+ range: custom
+ - field: status
+ range: wait
diff --git a/module/todo/test/model/yaml/getbyid/getbyid.yaml b/module/todo/test/model/yaml/getbyid/getbyid.yaml
new file mode 100644
index 0000000000..96a2bffb6b
--- /dev/null
+++ b/module/todo/test/model/yaml/getbyid/getbyid.yaml
@@ -0,0 +1,37 @@
+title: zt_getbyid
+author: jukui
+version: "1.0"
+fields:
+ - field: id
+ range: 1-5
+ - field: account
+ range: 'admin'
+ - field: date
+ range: 1-9
+ prefix: '2023-04-2'
+ - field: begin
+ range: 1000-1100
+ - field: end
+ range: 1200-1300
+ - field: type
+ range: 'custom'
+ - field: cycle
+ range: 0
+ - field: pri
+ range: 3
+ - field: name
+ range: 1-5
+ prefix: '自定义的待办'
+ - field: desc
+ range: 1-5
+ prefix: '这是待办描述'
+ - field: status
+ range: 'wait,doing,done,closed,closed'
+ - field: finishedDate
+ range: 1-9
+ prefix: '2023-04-2'
+ - field: closedDate
+ range: 1-9
+ prefix: '2023-04-2'
+
+
diff --git a/module/todo/test/model/yaml/getbylist/getbylist.yaml b/module/todo/test/model/yaml/getbylist/getbylist.yaml
new file mode 100644
index 0000000000..c86e1a3a3e
--- /dev/null
+++ b/module/todo/test/model/yaml/getbylist/getbylist.yaml
@@ -0,0 +1,37 @@
+title: zt_getbylist
+author: jukui
+version: "1.0"
+fields:
+ - field: id
+ range: 1-5
+ - field: account
+ range: 'admin'
+ - field: date
+ range: 1-9
+ prefix: '2023-04-2'
+ - field: begin
+ range: 1000-1100
+ - field: end
+ range: 1200-1300
+ - field: type
+ range: 'custom'
+ - field: cycle
+ range: 0
+ - field: pri
+ range: 3
+ - field: name
+ range: 1-5
+ prefix: '自定义的待办'
+ - field: desc
+ range: 1-5
+ prefix: '这是待办描述'
+ - field: status
+ range: 'wait,doing,done,closed,closed'
+ - field: finishedDate
+ range: 1-9
+ prefix: '2023-04-2'
+ - field: closedDate
+ range: 1-9
+ prefix: '2023-04-2'
+
+
diff --git a/module/todo/test/todo.class.php b/module/todo/test/todo.class.php
index 94d51fc3fe..b6ec49d2d4 100755
--- a/module/todo/test/todo.class.php
+++ b/module/todo/test/todo.class.php
@@ -12,37 +12,16 @@ class todoTest
/**
* Test create a todo.
*
- * @param string $account
- * @param array $param
+ * @param object $todoData
+ * @param object $formData
* @access public
- * @return object
+ * @return int
*/
- public function createTest($account, $param = array())
+ public function createTest($todoData, $formData)
{
- $config = array('day' => '', 'specify' => array('month' => 0, 'day' => 1), 'type' => 'day', 'beforeDays' => 0, 'end' => '');
- if(isset($param->date)) $param->date = $param->date == 'today' ? date('Y-m-d',time()) : date('Y-m-d',strtotime('+3 days'));
+ $objectID = $this->objectModel->create($todoData, $formData);
- $createFields['config'] = $config;
- $createFields['type'] = 'custom';
- $createFields['name'] = '';
- $createFields['pri'] = 3;
- $createFields['desc'] = '';
- $createFields['status'] = 'wait';
- $createFields['begin'] = '0830';
- $createFields['end'] = '0900';
-
- foreach($createFields as $field => $defaultValue) $_POST[$field] = $defaultValue;
-
- foreach($param as $key => $value) $_POST[$key] = $value;
-
- $objectID = $this->objectModel->create(date('Y').date('m'), $account);
-
- unset($_POST);
-
- if(dao::isError()) return array_values(dao::getError())[0][0];
-
- $object = $objectID ? $this->objectModel->getByID($objectID) : 0;
- return $object;
+ return $objectID ?: 0;
}
/**
@@ -114,35 +93,10 @@ class todoTest
* @access public
* @return array
*/
- public function batchUpdateTest($param, $todoID)
+ public function batchUpdateTest(array $todos, int $todoID)
{
- $todoIDList = array('1' => '1', '2' => '2', '3' => '3');
- $dates = array('1' => date('Y-m-d',strtotime('+1 month')), '2' => date('Y-m-d',strtotime('-1 month +1 day')), '3' => date('Y-m-d',strtotime('-1 month +2 day')));
- $types = array('1' => 'custom', '2' => 'bug', '3' => 'task');
- $pris = array('1' => '1', '2' => '2', '3' => '3');
- $names = array('1' => '自定义1的待办', '2' => 'BUG2的待办', '3' => '任务3的待办');
- $descs = array('1' => '这是一个待办的描述1', '2' => '这是一个待办的描述2', '3' => '这是一个待办的描述3');
- $begins = array('1' => '1000', '2' => '1002', '3' => '1004');
- $ends = array('1' => '1400', '2' => '1402', '3' => '1404');
- $status = array('1' => 'wait', '2' => 'doing', '3' => 'done');
-
- $batchUpdateFields['todoIDList'] = $todoIDList;
- $batchUpdateFields['dates'] = $dates;
- $batchUpdateFields['types'] = $types;
- $batchUpdateFields['pris'] = $pris;
- $batchUpdateFields['names'] = $names;
- $batchUpdateFields['descs'] = $descs;
- $batchUpdateFields['begins'] = $begins;
- $batchUpdateFields['ends'] = $ends;
- $batchUpdateFields['status'] = $status;
-
- foreach($batchUpdateFields as $field => $value) $_POST[$field] = $value;
-
- foreach($param as $key => $value) $_POST[$key] = $value;
-
- $changes = $this->objectModel->batchUpdate();
-
- unset($_POST);
+ $todoIDList = array($todoID => $todoID);
+ $changes = $this->objectModel->batchUpdate($todos, $todoIDList);
if(dao::isError()) return dao::getError();
@@ -263,23 +217,22 @@ class todoTest
}
/**
- * Test get todo by id list.
+ * Test todoModel::getByList.
*
- * @parami array $todoIDList
+ * @param array $todoIDList
* @access public
- * @return void
+ * @return string
*/
public function getByListTest($todoIDList = 0)
{
$objects = $this->objectModel->getByList($todoIDList);
-
- $name = '';
- foreach($objects as $todo) $name .= ',' . $todo->name;
- $name = trim($name, ',');
-
- if(dao::isError()) return dao::getError();
-
- return $name;
+ $result = '';
+ foreach($objects as $id => $todo)
+ {
+ $result .= (string) $todo->id;
+ }
+ if(empty($result)) return "pass";
+ return $result;
}
/**
diff --git a/module/todo/ui/create.html.php b/module/todo/ui/create.html.php
new file mode 100644
index 0000000000..2cf75144b2
--- /dev/null
+++ b/module/todo/ui/create.html.php
@@ -0,0 +1,458 @@
+
+ * @package todo
+ * @link http://www.zentao.net
+ */
+namespace zin;
+
+jsVar('noTodo', $lang->todo->noTodo);
+jsVar('moduleList', $config->todo->moduleList);
+jsVar('objectsMethod', $config->todo->getUserObjectsMethod);
+jsVar('nameBoxLabel', array('custom' => $lang->todo->name, 'idvalue' => isset($lang->todo->idvalue) ? $lang->todo->idvalue : null));
+jsVar('vision', $config->vision);
+jsVar('noOptions', $lang->todo->noOptions);
+jsVar('chosenType', $lang->todo->typeList);
+jsVar('today', date('Y-m-d'));
+jsVar('nowTime', $time);
+jsVar('start', key($times));
+jsVar('userID', $app->user->id);
+jsVar('defaultType', '');
+
+/**
+ * 构建周期设置的天的标签内容,待办为周期类型进行展示。
+ * Build tab-pane content of day.
+ *
+ * @return mixed Any type supported by zin widget function 任何 zin 部件函数参数支持的类型。
+ */
+function buildDayPane(): mixed
+{
+ global $lang, $app;
+
+ return fragment
+ (
+ inputGroup
+ (
+ set::class('every'),
+ span
+ (
+ set::class('input-group-addon'),
+ $lang->todo->every
+ ),
+
+ input
+ (
+ set::id('everyInput'),
+ set::name('config[day]')
+ ),
+ span
+ (
+ set::class('input-group-addon'),
+ $lang->todo->cycleDay
+ ),
+ div
+ (
+ set::class('pl-3 flex items-center input-group-addon every-checkbox'),
+ checkbox
+ (
+ set::id('configSpecify'),
+ set::name('config[specifiedDate]'),
+ set::text($lang->todo->specify),
+ set::value(1),
+ on::change('showSpecifiedDate(this)')
+ )
+ )
+ ),
+
+ inputGroup
+ (
+ set::class('specify hidden'),
+ span
+ (
+ set::class('input-group-addon'),
+ $lang->todo->specify
+ ),
+ select
+ (
+ set::id('config[specify][month]'),
+ set::name('config[specify][month]'),
+ set::items($lang->datepicker->monthNames),
+ set::value(0),
+ set::multiple(false),
+ on::change('setDays(this.value)')
+ ),
+ select
+ (
+ set::id('specifiedDay'),
+ set::name('config[specify][day]'),
+ set::items($lang->todo->specifiedDay),
+ set::multiple(false),
+ set::value(1)
+ ),
+ span
+ (
+ set::class('input-group-addon', strpos($app->getClientLang(), 'zh') !== false ? '' : 'hidden'),
+ $lang->todo->day
+ ),
+ div
+ (
+ set::class('w-36 pl-3 flex items-center gap-3 input-group-addon'),
+ checkbox
+ (
+ set::id('cycleYear'),
+ set::name('config[cycleYear]'),
+ set::value(1),
+ set::text($lang->todo->everyYear)
+ ),
+ checkbox
+ (
+ set::id('configEvery'),
+ set::name('configEvery'),
+ set::value(1),
+ set::text($lang->todo->every),
+ on::change('showEvery(this)')
+ )
+ )
+ )
+ );
+}
+
+/**
+ * 构建月的标签页,用于周期设置。
+ * Build tab-pane content of month.
+ *
+ * @return mixed Any type supported by zin widget function 任何 zin 部件函数参数支持的类型。
+ */
+
+function buildMonthDays(): mixed
+{
+ $days = array();
+ for($i = 1; $i <= 31; $i ++) $days[$i] = $i;
+
+ return checkList
+ (
+ set::class('flex-wrap gap-4'),
+ set::name('config[month]'),
+ set::inline(true),
+ set::items($days),
+ );
+}
+
+/**
+ * 构建周期设置的标签导航,待办为周期类型进行展示。
+ * Build navTabs header for cycle.
+ *
+ * @return mixed Any type supported by zin widget function 任何 zin 部件函数参数支持的类型。
+ */
+
+function buildNavTabsBar(): mixed
+{
+ global $lang;
+
+ $navTabs = [
+ [
+ 'type' => 'day',
+ 'text' => $lang->todo->cycleDay,
+ 'class' => ' active'
+ ],
+ [
+ 'type' => 'week',
+ 'text' => $lang->todo->cycleWeek,
+ 'class' => ''
+ ],
+ [
+ 'type' => 'month',
+ 'text' => $lang->todo->cycleMonth,
+ 'class' => '',
+ ],
+ ];
+
+ $nav = ul(set::class('nav nav-tabs'));
+ foreach($navTabs as $tab)
+ {
+ $nav->add(
+ li
+ (
+ set::class('nav-item'. $tab['class']),
+ a
+ (
+ set::href('#' . $tab['type']),
+ set::class($tab['class']),
+ set('data-toggle', 'tab'),
+ $tab['text'],
+ on::click('toggleNavTabs(this)')
+ )
+ ),
+ );
+ }
+
+ return $nav;
+}
+
+/**
+ * 构建周期设置的标签页,当待办为周期时进行展示。
+ * Build navTabs for cycle.
+ *
+ * @return mixed Any type supported by zin widget function 任何 zin 部件函数参数支持的类型。
+ */
+function buildNavTabs(): mixed
+{
+ global $lang;
+
+ return div
+ (
+ set::class('w-full'),
+ buildNavTabsBar(),
+ div
+ (
+ set::class('tab-content'),
+ div
+ (
+ set::class('tab-pane active'),
+ set::id('day'),
+ buildDayPane(),
+ ),
+ div
+ (
+ set::class('tab-pane'),
+ set::id('week'),
+ checkList
+ (
+ set::primary(true),
+ set::id('config[week]'),
+ set::name('config[week]'),
+ set::inline(true),
+ set::items($lang->todo->dayNames),
+ ),
+ ),
+ div
+ (
+ set::class('tab-pane h-28'),
+ set::id('month'),
+ buildMonthDays(),
+ ),
+ inputGroup
+ (
+ div
+ (
+ set::class('input-group-addon'),
+ '提前',
+ ),
+ input
+ (
+ set::id('name'),
+ set::name('config[beforeDays]'),
+ set::value(0),
+ ),
+ div
+ (
+ set::class('input-group-addon'),
+ '天生成待办',
+ ),
+ ),
+
+ ),
+ );
+}
+
+formPanel
+(
+ formRow
+ (
+ formGroup
+ (
+ set::width('1/2'),
+ set::label($lang->todo->date),
+ set::strong(true),
+ set::class('align-center'),
+ inputGroup
+ (
+ input
+ (
+ set::name('date'),
+ set::value(date('Y-m-d')),
+ set::type('date'),
+ set::width('1/3'),
+ on::change('changeCreateDate(this)')
+ ),
+ div
+ (
+ set::class('flex items-center gap-3 pl-3 input-group-addon'),
+ checkbox
+ (
+ set::id('switchDate'),
+ set::name('switchDate'),
+ set::text($lang->todo->periods['future']),
+ set::width('100px'),
+ on::change('toggleDateTodo(this)')
+ ),
+ checkbox
+ (
+ set::id('cycle'),
+ set::name('cycle'),
+ set::value(1),
+ set::text($lang->todo->cycle),
+ on::change('toggleCycle(this)')
+ )
+ )
+
+ )
+
+ )
+ ),
+ formRow
+ (
+ set::class('cycle-config hidden'),
+ formGroup
+ (
+ set::label($lang->todo->cycleConfig),
+ set::strong(true),
+ buildNavTabs()
+ )
+ ),
+ formRow
+ (
+ set::class('cycle-config hidden'),
+ formGroup
+ (
+ set::width('1/2'),
+ set::label($lang->todo->deadline),
+ set::strong(true),
+ input
+ (
+ set::type('date'),
+ set::name('config[end]')
+ )
+ )
+ ),
+ formGroup
+ (
+ set::width('1/2'),
+ set::name('type'),
+ set::strong(true),
+ set::label($lang->todo->type),
+ set::items($lang->todo->typeList),
+ on::change('changeType(this)'),
+ ),
+ formGroup
+ (
+ set::width('1/2'),
+ set::name('assignedTo'),
+ set::strong(true),
+ set::label($lang->todo->assignTo),
+ set::items($users),
+ set::value($app->user->account)
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::id('nameBox'),
+ set::class('name-box'),
+ set::label($lang->todo->name),
+ set::strong(true),
+ set::required(true),
+ inputGroup
+ (
+ set::class('title-group'),
+ div
+ (
+ set::id('nameInputBox'),
+ input
+ (
+ set::id('name'),
+ set::name('name')
+ )
+ ),
+ div
+ (
+ set::class('input-group-addon fix-border br-0'),
+ $lang->todo->pri
+ ),
+ select
+ (
+ set::class('w-20'),
+ set::id('pri'),
+ set::name('pri'),
+ set::items($lang->todo->priList),
+ set::value(3)
+ )
+ )
+ )
+ ),
+
+ formGroup
+ (
+ set::name('desc'),
+ set::strong(true),
+ set::type('textarea'),
+ set::label($lang->todo->desc)
+ ),
+ formGroup
+ (
+ set::width('1/2'),
+ set::id('status'),
+ set::name('status'),
+ set::items($lang->todo->statusList),
+ set::label($lang->todo->status),
+ set::strong(true)
+ ),
+ formRow
+ (
+ set::class('items-center'),
+ formGroup
+ (
+ set::width('1/2'),
+ set::label($lang->todo->beginAndEnd),
+ set::strong(true),
+ inputGroup
+ (
+ select
+ (
+ set::id('begin'),
+ set::name('begin'),
+ set::items($times),
+ set::value(date('Y-m-d') != $date ? key($times) : $time),
+ on::change('selectNext()')
+ ),
+ select
+ (
+ set::id('end'),
+ set::name('end'),
+ set::items($times)
+ )
+ ),
+ div
+ (
+ set::class('ml-3 flex items-center switch-time'),
+ checkbox
+ (
+ set::id('switchTime'),
+ set::name('switchTime'),
+ set::text($lang->todo->lblDisableDate),
+ on::change('switchDateFeature(this)')
+ )
+ )
+
+ )
+ ),
+ formGroup
+ (
+ set::label($lang->todo->private),
+ set::strong(true),
+ set::class('private-row'),
+ checkbox
+ (
+ set::id('private'),
+ set::name('private'),
+ set::value(1)
+ )
+ )
+);
+
+render();
diff --git a/module/todo/zen.php b/module/todo/zen.php
index fe9138677c..25afbcd8df 100755
--- a/module/todo/zen.php
+++ b/module/todo/zen.php
@@ -11,7 +11,7 @@ class todoZen extends todo
* @access protected
* @return void
*/
- protected function buildCreateView(string $date): void
+ protected function buildCreateView(string $date)
{
$this->view->title = $this->lang->todo->common . $this->lang->colon . $this->lang->todo->create;
$this->view->date = date('Y-m-d', strtotime($date));
@@ -22,6 +22,33 @@ class todoZen extends todo
$this->display();
}
+ /**
+ * 生成批量创建待办视图数据。
+ * Build batch create form data.
+ *
+ * @param string $date
+ * @access protected
+ * @return void
+ */
+ protected function buildBatchCreateView(string $date)
+ {
+ /* Set Custom. */
+ foreach(explode(',', $this->config->todo->list->customBatchCreateFields) as $field) $customFields[$field] = $this->lang->todo->$field;
+
+ $this->view->customFields = $customFields;
+ $this->view->showFields = $this->config->todo->custom->batchCreateFields;
+
+ $this->view->title = $this->lang->todo->common . $this->lang->colon . $this->lang->todo->batchCreate;
+ $this->view->position[] = $this->lang->todo->common;
+ $this->view->position[] = $this->lang->todo->batchCreate;
+ $this->view->date = (int)$date == 0 ? $date : date('Y-m-d', strtotime($date));
+ $this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta);
+ $this->view->time = date::now();
+ $this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted|noempty');
+
+ $this->display();
+ }
+
/**
* 生成编辑待办视图数据。
* Build create form data.
@@ -71,11 +98,12 @@ class todoZen extends todo
*/
protected function beforeCreate(object $formData): object
{
- $objectType = $this->post->type;
+ $rowData = $formData->rawdata;
+ $objectType = $rowData->type;
$hasObject = in_array($objectType, $this->config->todo->moduleList);
$objectID = 0;
- if($hasObject && $objectType) $objectID = $this->post->uid ? $this->post->$objectType : $this->post->objectID;
+ if($hasObject && $objectType) $objectID = $rowData->uid ? $rowData->$objectType : $rowData->objectID;
$data = $formData->add('account', $this->app->user->account)
->setDefault('objectID', 0)
@@ -85,11 +113,11 @@ class todoZen extends todo
->setDefault('assignedDate', helper::now())
->cleanInt('pri, begin, end, private')
->setIF($hasObject && $objectType, 'objectID', $objectID)
- ->setIF($this->post->date == false, 'date', '2030-01-01')
- ->setIF($this->post->begin == false, 'begin', '2400')
- ->setIF($this->post->begin == false or $this->post->end == false, 'end', '2400')
- ->setIF($this->post->status == 'done', 'finishedBy', $this->app->user->account)
- ->setIF($this->post->status == 'done', 'finishedDate', helper::now())
+ ->setIF($rowData->date == false, 'date', '2030-01-01')
+ ->setIF($rowData->begin == false, 'begin', '2400')
+ ->setIF($rowData->begin == false or $rowData->end == false, 'end', '2400')
+ ->setIF($rowData->status == 'done', 'finishedBy', $this->app->user->account)
+ ->setIF($rowData->status == 'done', 'finishedDate', helper::now())
->stripTags($this->config->todo->editor->create['id'], $this->config->allowedTags)
->remove(implode(',', $this->config->todo->moduleList) . ',uid')
->get();
@@ -102,12 +130,13 @@ class todoZen extends todo
* Create a todo after data processing.
*
* @param object $todo
+ * @param object $formData
* @access protected
* @return object
*/
- protected function afterCreate(object $todo): object
+ protected function afterCreate(object $todo, object $formData): object
{
- $this->loadModel('file')->updateObjectID($this->post->uid, $todo->id, 'todo');
+ $this->loadModel('file')->updateObjectID($formData->rawdata->uid, $todo->id, 'todo');
$this->loadModel('score')->create('todo', 'create', $todo->id);
@@ -176,7 +205,7 @@ class todoZen extends todo
}
/**
- * 编辑完成待办后数据处理
+ * 编辑完成待办后数据处理。
* Handle data after edit todo.
*
* @param object $todo
@@ -191,89 +220,180 @@ class todoZen extends todo
$this->action->logHistory($actionID, $changes);
}
- protected function batchEditFromMyTodo($type, $userID, $status)
+ /**
+ * 批量编辑页面渲染。
+ * Batch edit view display.
+ *
+ * @param object $formData
+ * @param string $type
+ * @param int $userID
+ * @param string $status
+ * @access protected
+ * @return void
+ */
+ protected function batchEditFromMyTodo(object $formData, string $type, int $userID, string $status): void
{
/* Initialize vars. */
- $editedTodos = array();
- $todoIDList = array();
- $reviews = array();
- $columns = 7;
+ $editedTodos = $objectIdList = $reviews = array();
+ $columns = 7;
+ unset($this->lang->todo->typeList['cycle']);
- if($userID == '') $userID = $this->app->user->id;
+ if(empty($userID)) $userID = $this->app->user->id;
$user = $this->loadModel('user')->getById($userID, 'id');
$account = $user->account;
- if($this->config->edition == 'max') $reviews = $this->loadModel('review')->getUserReviewPairs($account);
- $allTodos = $this->todo->getList($type, $account, $status);
- if($this->post->todoIDList) $todoIDList = $this->post->todoIDList;
+ list($editedTodos, $objectIdList) = $this->getBatchEditInitTodos($formData, $type, $account, $status);
- /* Initialize todos whose need to edited. */
- foreach($allTodos as $todo)
- {
- if(in_array($todo->id, $todoIDList))
- {
- $editedTodos[$todo->id] = $todo;
- if($todo->type != 'custom')
- {
- if(!isset($objectIDList[$todo->type])) $objectIDList[$todo->type] = array();
- $objectIDList[$todo->type][$todo->objectID] = $todo->objectID;
- }
- }
- }
-
- $bugs = $this->bug->getUserBugPairs($account, true, 0, '', '', isset($objectIDList['bug']) ? $objectIDList['bug'] : '');
- $tasks = $this->task->getUserTaskPairs($account, 'wait,doing', '', isset($objectIDList['task']) ? $objectIDList['task'] : '');
- $storys = $this->loadModel('story')->getUserStoryPairs($account, 10, 'story', '', isset($objectIDList['story']) ? $objectIDList['story'] : '');
- if($this->config->edition != 'open') $this->view->feedbacks = $this->loadModel('feedback')->getUserFeedbackPairs($account, '', isset($objectIDList['feedback']) ? $objectIDList['feedback'] : '');
+ $bugs = $this->bug->getUserBugPairs($account, true, 0, '', '', isset($objectIdList['bug']) ? $objectIdList['bug'] : '');
+ $tasks = $this->task->getUserTaskPairs($account, 'wait,doing', '', isset($objectIdList['task']) ? $objectIdList['task'] : '');
+ $storys = $this->loadModel('story')->getUserStoryPairs($account, 10, 'story', '', isset($objectIdList['story']) ? $objectIdList['story'] : '');
+ $users = $this->loadModel('user')->getPairs('noclosed|nodeleted|noempty');
+ $testtasks = $this->loadModel('testtask')->getUserTestTaskPairs($account);
+ if($this->config->edition == 'biz' || $this->config->edition == 'max') $feedbacks = $this->loadModel('feedback')->getUserFeedbackPairs($account, '', isset($objectIdList['feedback']) ? $objectIdList['feedback'] : '');
if($this->config->edition == 'max')
{
$issues = $this->loadModel('issue')->getUserIssuePairs($account);
$risks = $this->loadmodel('risk')->getUserRiskPairs($account);
$opportunities = $this->loadmodel('opportunity')->getUserOpportunityPairs($account);
+ $reviews = $this->loadModel('review')->getUserReviewPairs($account);
}
- $testtasks = $this->loadModel('testtask')->getUserTestTaskPairs($account);
/* Judge whether the edited todos is too large. */
$countInputVars = count($editedTodos) * $columns;
$showSuhosinInfo = common::judgeSuhosinSetting($countInputVars);
- unset($this->lang->todo->typeList['cycle']);
- /* Set Custom*/
- foreach(explode(',', $this->config->todo->list->customBatchEditFields) as $field) $customFields[$field] = $this->lang->todo->$field;
- $this->view->customFields = $customFields;
- $this->view->showFields = $this->config->todo->custom->batchEditFields;
-
- /* Assign. */
- $title = $this->lang->todo->common . $this->lang->colon . $this->lang->todo->batchEdit;
- $position[] = html::a($this->createLink('my', 'todo'), $this->lang->my->todo);
- $position[] = $this->lang->todo->common;
- $position[] = $this->lang->todo->batchEdit;
-
if($showSuhosinInfo) $this->view->suhosinInfo = extension_loaded('suhosin') ? sprintf($this->lang->suhosinInfo, $countInputVars) : sprintf($this->lang->maxVarsInfo, $countInputVars);
- $this->view->bugs = $bugs;
- $this->view->tasks = $tasks;
- $this->view->storys = $storys;
+ $this->view->bugs = $bugs;
+ $this->view->tasks = $tasks;
+ $this->view->storys = $storys;
+ $this->view->reviews = $reviews;
+ $this->view->testtasks = $testtasks;
+ $this->view->editedTodos = $editedTodos;
+ $this->view->users = $users;
+ if($this->config->edition == 'biz' || $this->config->edition == 'max') $this->view->feedback = $feedbacks;
if($this->config->edition == 'max')
{
$this->view->issues = $issues;
$this->view->risks = $risks;
$this->view->opportunities = $opportunities;
}
- $this->view->reviews = $reviews;
- $this->view->testtasks = $testtasks;
- $this->view->editedTodos = $editedTodos;
- $this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta);
- $this->view->time = date::now();
- $this->view->title = $title;
- $this->view->position = $position;
- $this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted|noempty');
+
+ $this->buildBatchEditView();
+ return;
+ }
+
+ /**
+ * 获取批量编辑页面初始化待办数据。
+ * Get batch edit page initialization todo data.
+ *
+ * @param object $formData
+ * @param string $type
+ * @param string $account
+ * @param string $status
+ * @access protected
+ * @return array
+ */
+ private function getBatchEditInitTodos(object $formData, string $type, string $account, string $status): array
+ {
+ $editedTodos = array();
+ $objectIdList = array();
+ $todoIdList = array();
+
+ $allTodos = $this->todo->getList($type, $account, $status);
+ if($formData->data->todoIDList) $todoIdList = $formData->data->todoIDList;
+
+ /* Initialize todos whose need to edited. */
+ foreach($allTodos as $todo)
+ {
+ if(in_array($todo->id, $todoIdList))
+ {
+ $editedTodos[$todo->id] = $todo;
+ if($todo->type != 'custom')
+ {
+ if(!isset($objectIdList[$todo->type])) $objectIdList[$todo->type] = array();
+ $objectIdList[$todo->type][$todo->objectID] = $todo->objectID;
+ }
+ }
+ }
+
+ return array($editedTodos, $objectIdList);
+ }
+
+ /**
+ * 生成批量创建待办视图数据。
+ * Build batch edit view.
+ *
+ * @access private
+ * @return void
+ */
+ private function buildBatchEditView(): void
+ {
+ /* Set Custom*/
+ foreach(explode(',', $this->config->todo->list->customBatchEditFields) as $field) $customFields[$field] = $this->lang->todo->$field;
+ $this->view->customFields = $customFields;
+ $this->view->showFields = $this->config->todo->custom->batchEditFields;
+ $this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta);
+ $this->view->time = date::now();
+ $this->view->title = $this->lang->todo->common . $this->lang->colon . $this->lang->todo->batchEdit;
$this->display();
}
- protected function batchEditFromTodoBatchEdit($formData)
+ /**
+ * 处理批量编辑待办数据。
+ * Build batch edit view.
+ *
+ * @param object $formData
+ * @access protected
+ * @return array
+ */
+ protected function beforeBatchEdit(object $formData): array
+ {
+ $todos = array();
+ $data = $formData->rawdata;
+ $todoIdList = $formData->data->todoIDList ? $formData->data->todoIDList : array();
+
+ if(!empty($todoIdList))
+ {
+ /* Initialize todos from the post data. */
+ $oldTodos = $this->todo->getTodosByIdList($todoIdList);
+ foreach($todoIdList as $todoID)
+ {
+ $oldTodo = $oldTodos[$todoID];
+
+ $todo = new stdclass();
+ $todo->date = $data->dates[$todoID];
+ $todo->type = $data->types[$todoID];
+ $todo->pri = $data->pris[$todoID];
+ $todo->status = $data->status[$todoID];
+ $todo->name = !in_array($todo->type, $this->config->todo->moduleList) ? $data->names[$todoID] : '';
+ $todo->begin = isset($data->begins[$todoID]) ? $data->begins[$todoID] : 2400;
+ $todo->end = isset($data->ends[$todoID]) ? $data->ends[$todoID] : 2400;
+ $todo->assignedTo = isset($data->assignedTos[$todoID]) ? $data->assignedTos[$todoID] : $oldTodo->assignedTo;
+
+ if(in_array($todo->type, $this->config->todo->moduleList))
+ {
+ $todo->objectID = isset($data->{$this->config->todo->objectList[$todo->type]}[$todoID]) ? $data->{$this->config->todo->objectList[$todo->type]}[$todoID] : 0;
+ }
+ if($todo->end < $todo->begin) return print(js::alert(sprintf($this->lang->error->gt, $this->lang->todo->end, $this->lang->todo->begin)));
+
+ $todos[$todoID] = $todo;
+ }
+ }
+
+ return $todos;
+ }
+
+ /**
+ * 批量编辑完成待办后数据处理。
+ * After Batch edit todo data.
+ *
+ * @param array $allChanges
+ * @access protected
+ * @return void
+ */
+ protected function afterBatchEdit(array $allChanges): void
{
- $allChanges = $this->todo->batchUpdate();
foreach($allChanges as $todoID => $changes)
{
if(empty($changes)) continue;
@@ -281,8 +401,6 @@ class todoZen extends todo
$actionID = $this->loadModel('action')->create('todo', $todoID, 'edited');
$this->action->logHistory($actionID, $changes);
}
-
- return print(js::locate($this->session->todoList, 'parent'));
}
/**
@@ -488,9 +606,9 @@ class todoZen extends todo
* @access protected
* @return true
*/
- protected function setSessionUri($uri): bool
+ protected function setSessionUri(string $uri): bool
{
- foreach($this->config->todo->sessionUri as $key => $value) $this->sesstion->set($key, $uri, $value);
+ foreach($this->config->todo->sessionUri as $key => $value) $this->session->set($key, $uri, $value);
return true;
}
@@ -538,7 +656,7 @@ class todoZen extends todo
$this->loadModel('opportunity')->getUserOpportunityPairs($account),
);
}
- else if($type == 'qcVersion')
+ elseif($type == 'qcVersion')
{
return $this->loadModel('review')->getUserReviewPairs($account, 0, 'wait');
}
diff --git a/sonar-project.properties b/sonar-project.properties
index e787def4f9..0ecd58d8aa 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -3,4 +3,4 @@ sonar.sourceEncoding=UTF-8
sonar.qualitygate.wait=true
sonar.coverage.exclusions=**/*.*
sonar.inclusions=**/**.php
-sonar.exclusions=**/*.bak,**/*.sql,**/*.js,**/*.css,**/*.yaml,**/*.zip,**/*.out,**/lang/*,**/test/**
+sonar.exclusions=**/*.bak,**/*.sql,**/*.js,**/*.css,**/*.yaml,**/*.zip,**/*.out,**/lang/*,**/test/**,doc/*
diff --git a/test/data/bug.yaml b/test/data/bug.yaml
index bb6ba8333e..95b1952f9a 100644
--- a/test/data/bug.yaml
+++ b/test/data/bug.yaml
@@ -1,6 +1,7 @@
title: zt_bug
-desc: Bug表
-version: 1.0
+desc: "Bug表"
+author: automated export
+version: "1.0"
fields:
- field: id
range: 1-10000
@@ -33,29 +34,29 @@ fields:
- field: title2
range: 1-10000
- field: keywords
- range: []
+ range: "[]"
- field: severity
range: 1-4
- field: pri
range: 1-4
- field: type
- range: [codeerror,config,install,security,performance,standard,automation,designdefect,others]
+ range: "[codeerror,config,install,security,performance,standard,automation,designdefect,others]"
- field: os
- range: []{2},[win10,windows,android,ios]
+ range: "[]{2},[win10,windows,android,ios]"
- field: browser
- range: []
+ range: "[]"
- field: hardware
- range: []
+ range: "[]"
- field: found
- range: []
+ range: "[]"
- field: steps
- range: [【步骤】
【结果】
【期望】
,【步骤】进入成果展示
【结果】乱码
【期望】正常显示
]
+ range: "[【步骤】
【结果】
【期望】
,【步骤】进入成果展示
【结果】乱码
【期望】正常显示
]"
- field: status
range: active{50},resolved{30},closed{20}
- field: subStatus
- range: []
+ range: "[]"
- field: color
- range: [#3da7f5,#75c941,#2dbdb2,#797ec9,#ffaf38,#ff4e3e]
+ range: "[#3da7f5,#75c941,#2dbdb2,#797ec9,#ffaf38,#ff4e3e]"
- field: confirmed
range: 0,1
- field: activatedCount
@@ -71,7 +72,7 @@ fields:
- field: openedBuild
range: 1,0,1,trunk{97}
- field: assignedTo
- range: [admin,dev1,test1]{30},[]{20},[admin,dev1,test1]{20},[]{10},closed{20}
+ range: "[admin,dev1,test1]{30},[]{20},[admin,dev1,test1]{20},[]{10},closed{20}"
- field: assignedDate
range: "(-1M)-(+1w):-1D"
type: timestamp
@@ -84,11 +85,11 @@ fields:
loop: 0
format: "YYYY-MM-DD"
- field: resolvedBy
- range: []{50},$assignedTo{30},admin{20}
+ range: "[]{50},$assignedTo{30},admin{20}"
- field: resolution
- range: []{50},bydesign{5},duplicate{5},external{5},fixed{5},notrepro{2},postponed{3},willnotfix{5},fixed{10},bydesign,external,notrepro,postponed,willnotfix,duplicate{5}
+ range: "[]{50},bydesign{5},duplicate{5},external{5},fixed{5},notrepro{2},postponed{3},willnotfix{5},fixed{10},bydesign,external,notrepro,postponed,willnotfix,duplicate{5}"
- field: resolvedBuild
- range: []{55},trunk{15},[]{25},trunk{5}
+ range: "[]{55},trunk{15},[]{25},trunk{5}"
- field: resolvedDate
range: "(+1w)-(-2w):-1D"
type: timestamp
@@ -97,7 +98,7 @@ fields:
loop: 0
format: "YYYY-MM-DD"
- field: closedBy
- range: []{50},admin{30}
+ range: "[]{50},admin{30}"
- field: closedDate
range:
- field: duplicateBug
diff --git a/test/data/case.yaml b/test/data/case.yaml
index 0b83ec487f..1a6832d914 100644
--- a/test/data/case.yaml
+++ b/test/data/case.yaml
@@ -65,8 +65,11 @@ fields:
range: ""
- field: scriptedDate
note: "脚本创建日期"
- from: common.date.v1.yaml
- use: dateB
+ range: "(M)-(w)"
+ type: timestamp
+ prefix: "DateTime"
+ postfix: ""
+ format: "YY/MM/DD"
- field: scriptStatus
note: "脚本状态"
range: ""
@@ -81,8 +84,6 @@ fields:
range: ""
- field: color
note: "标题颜色"
- from: common.color.v1.yaml
- use: color
- field: frequency
note: "使用频率"
range: 1-3
diff --git a/test/data/design.yaml b/test/data/design.yaml
index 15f4140653..14589e469d 100644
--- a/test/data/design.yaml
+++ b/test/data/design.yaml
@@ -59,40 +59,35 @@ fields:
format: "YYYY-MM-DD hh:mm:ss"
- field: editedBy
note: "由谁编辑"
- from: common.user.v1.yaml
- use: user
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- field: editedDate
note: "编辑者"
- from: common.user.v1.yaml
- use: user
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- field: assignedTo
note: "指派给"
- from: common.user.v1.yaml
- use: user
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- field: assignedBy
note: "由谁指派"
- from: common.user.v1.yaml
- use: user
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- field: assignedDate
note: "指派日期"
- from: common.date.v1.yaml
- use: dateA
+ range: ""
prefix: ""
postfix: ""
loop: 0
diff --git a/test/data/doc.yaml b/test/data/doc.yaml
index 5219381342..947984c634 100644
--- a/test/data/doc.yaml
+++ b/test/data/doc.yaml
@@ -147,12 +147,11 @@ fields:
format: ""
- field: editedDate
note: "编辑日期"
- from: common.date.v1.yaml
- use: dateA
+ range: Y-m-d
prefix: ""
+ type: timestamp
postfix: ""
- loop: 0
- format: ""
+ format: "YYYY-MM-DD"
- field: acl
note: "权限"
range: open,custom,private
diff --git a/test/data/entry.yaml b/test/data/entry.yaml
index 8a1051f06c..5559327993 100644
--- a/test/data/entry.yaml
+++ b/test/data/entry.yaml
@@ -83,20 +83,14 @@ fields:
format: ""
- field: editedBy
note: "编辑者"
- from: common.user.v1.yaml
- use: user
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- field: editedDate
note: "编辑日期"
- from: common.date.v1.yaml
- use: dateA
- prefix: ""
- postfix: ""
- loop: 0
- format: ""
+ range: ""
- field: deleted
note: "是否删除"
range: 0
diff --git a/test/data/file.yaml b/test/data/file.yaml
index b07d5660aa..2dffc90296 100644
--- a/test/data/file.yaml
+++ b/test/data/file.yaml
@@ -12,16 +12,12 @@ fields:
format: ""
- field: pathname
note: "路径名称"
- from: common.file.v1.yaml
- use: pathname
- loop: 0
- format: ""
+ range: ""
- field: title
note: "文件标题"
- from: common.file.v1.yaml
- use: title
+ range: 1-1000000
+ prefix: "文件标题"
postfix: ""
- loop: 0
format: ""
- field: extension
note: "文件后缀"
@@ -60,12 +56,11 @@ fields:
format: ""
- field: addedDate
note: "添加时间"
- from: common.date.v1.yaml
- use: dateA
- prefix: ""
+ range: "(M)-(w)"
+ type: timestamp
+ prefix: "DateTime"
postfix: ""
- loop: 0
- format: ""
+ format: "YY/MM/DD"
- field: downloads
note: "下载次数"
range: "0-100"
diff --git a/test/data/job.yaml b/test/data/job.yaml
index 0d324458f5..091d65a815 100644
--- a/test/data/job.yaml
+++ b/test/data/job.yaml
@@ -105,40 +105,35 @@ fields:
format: ""
- field: createdBy
note: "创建者"
- from: common.user.v1.yaml
- use: user
+ range: admin
prefix: ""
postfix: ""
loop: 0
format: ""
- field: createdDate
note: "创建日期"
- from: common.date.v1.yaml
- use: dateA
- prefix: ""
+ range: "(M)-(w)"
+ type: timestamp
+ prefix: "DateTime"
postfix: ""
- loop: 0
- format: ""
+ format: "YY/MM/DD"
- field: editedBy
note: "编辑者"
- from: common.user.v1.yaml
- use: user
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- field: editedDate
note: "编辑日期"
- from: common.date.v1.yaml
- use: dateA
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- field: lastExec
note: "最后执行时间"
- from: common.date.v1.yaml
- use: dateA
+ range: ""
prefix: ""
postfix: ""
loop: 0
diff --git a/test/data/project.yaml b/test/data/project.yaml
index 2c9bc17a08..18cfabde77 100644
--- a/test/data/project.yaml
+++ b/test/data/project.yaml
@@ -81,5 +81,10 @@ fields:
range: 5-10000:5
- field: openedVersion
range: "16.5"
+ - field: openedDate
+ range: "(-3M)-(+M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
- field: deleted
range: 0
diff --git a/test/data/story.yaml b/test/data/story.yaml
index ab254831ae..5bad0a6f55 100644
--- a/test/data/story.yaml
+++ b/test/data/story.yaml
@@ -114,31 +114,28 @@ fields:
format: ""
- field: color
note: "标题颜色"
- from: common.color.v1.yaml
- use: color
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- field: stage
note: "所处阶段"
- range: [],wait,[],planned,[],projected,[],developing,[],developed,[],testing,[],tested,[],verified,[],released,[],closed
+ range: "[],wait,[],planned,[],projected,[],developing,[],developed,[],testing,[],tested,[],verified,[],released,[],closed"
prefix: ""
postfix: ""
loop: 0
format: ""
- field: stagedBy
note: "设置阶段者"
- from: common.user.v1.yaml
- use: user
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- field: mailto
note: "抄送给"
- from: common.user.v1.yaml
- use: user
+ range: ""
prefix: ""
postfix: ""
loop: 0
@@ -156,12 +153,11 @@ fields:
format: ""
- field: openedDate
note: "创建日期"
- from: common.date.v1.yaml
- use: dateA
- prefix: ""
+ range: "(M)-(w)"
+ type: timestamp
+ prefix: "DateTime"
postfix: ""
- loop: 0
- format: ""
+ format: "YY/MM/DD"
- field: assignedTo
note: "指派给"
fields:
@@ -175,28 +171,21 @@ fields:
format: ""
- field: assignedDate
note: "指派日期"
- from: common.date.v1.yaml
- use: dateA
- prefix: ""
+ range: "(M)-(w)"
+ type: timestamp
+ prefix: "DateTime"
postfix: ""
- loop: 0
- format: ""
+ format: "YY/MM/DD"
- field: lastEditedBy
note: "最后修改者"
- from: common.user.v1.yaml
- use: user
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- field: lastEditedDate
note: "最后修改日期"
- from: common.date.v1.yaml
- use: dateA
- prefix: ""
- postfix: ""
- loop: 0
- format: ""
+ range: ""
- field: reviewedBy
note: "评审者"
fields:
@@ -209,12 +198,7 @@ fields:
format: ""
- field: reviewedDate
note: "评审日期"
- from: common.date.v1.yaml
- use: dateA
- prefix: ""
- postfix: ""
- loop: 0
- format: ""
+ range: ""
- field: closedBy
note: "关闭者"
fields:
@@ -228,12 +212,7 @@ fields:
format: ""
- field: closedDate
note: "关闭日期"
- from: common.date.v1.yaml
- use: dateA
- prefix: ""
- postfix: ""
- loop: 0
- format: ""
+ range: ""
- field: closedReason
note: "关闭原因"
range: done,subdivided,duplicate,postponed,willnotdo,cancel,bydesign
diff --git a/test/data/task.yaml b/test/data/task.yaml
index 8adca0b47c..2237efc177 100644
--- a/test/data/task.yaml
+++ b/test/data/task.yaml
@@ -120,7 +120,6 @@ fields:
range: "(+1w)-(-1M):-1D"
prefix: ""
postfix: ""
- loop: 0
type: timestamp
format: "YY/MM/DD"
- field: status
@@ -139,20 +138,14 @@ fields:
format: ""
- field: color
note: "标题颜色"
- from: common.color.v1.yaml
- use: color
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- field: mailto
note: "抄送给"
- from: common.user.v1.yaml
- use: user
- prefix: ""
- postfix: ""
- loop: 0
- format: ""
+ range: ""
- field: desc
note: "任务描述"
range: 1-10000
@@ -169,20 +162,16 @@ fields:
format: ""
- field: openedBy
note: "由谁创建"
- from: common.user.v1.yaml
- use: user
+ range: admin
prefix: ""
postfix: ""
loop: 0
format: ""
- field: openedDate
note: "创建日期"
- from: common.date.v1.yaml
- use: dateA
- prefix: ""
- postfix: ""
- loop: 0
- format: ""
+ range: "(M)-(w)"
+ type: timestamp
+ format: "YY/MM/DD"
- field: assignedTo
note: "指派给"
range: ""
@@ -192,12 +181,9 @@ fields:
format: ""
- field: assignedDate
note: "指派日期"
- from: common.date.v1.yaml
- use: dateA
- prefix: ""
- postfix: ""
- loop: 0
- format: ""
+ range: "(M)-(w)"
+ type: timestamp
+ format: "YY/MM/DD"
- field: estStarted
note: "预计开始"
range: "2022-01-27"
@@ -208,72 +194,29 @@ fields:
format: "YY/MM/DD"
- field: realStarted
note: "实际开始"
- from: common.date.v1.yaml
- use: dateB
- prefix: ""
- postfix: ""
- loop: 0
- format: "YY/MM/DD"
+ range: "(M)-(w)"
type: timestamp
+ format: "YY/MM/DD"
- field: finishedBy
note: "由谁完成"
- from: common.user.v1.yaml
- use: user
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- - field: finishedDate
- note: "完成日期"
- from: common.date.v1.yaml
- use: dateA
- prefix: ""
- postfix: ""
- loop: 0
- format: "YY/MM/DD"
- type: timestamp
- field: finishedList
note: "完成者列表"
- from: common.user.v1.yaml
- use: user
- prefix: ""
- postfix: ""
- loop: 0
- format: ""
+ range: ""
- field: canceledBy
note: "由谁取消"
- from: common.user.v1.yaml
- use: user
- prefix: ""
- postfix: ""
- loop: 0
- format: ""
- - field: canceledDate
- note: "取消日期"
- from: common.date.v1.yaml
- use: dateA
- prefix: ""
- postfix: ""
- loop: 0
- format: "YY/MM/DD"
- type: timestamp
+ range: ""
- field: closedBy
note: "由谁关闭"
- from: common.user.v1.yaml
- use: user
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- - field: closedDate
- note: "关闭日期"
- from: common.date.v1.yaml
- use: dateA
- prefix: ""
- postfix: ""
- loop: 0
- format: "YY/MM/DD"
- type: timestamp
- field: realDuration
note: "实际持续时长"
range: 1
@@ -297,30 +240,10 @@ fields:
format: ""
- field: lastEditedBy
note: "最后修改者"
- from: common.user.v1.yaml
- use: user
+ range: ""
prefix: ""
postfix: ""
- loop: 0
format: ""
- - field: lastEditedDate
- note: "最后修改时间"
- from: common.date.v1.yaml
- use: dateA
- prefix: ""
- postfix: ""
- loop: 0
- format: "YY/MM/DD"
- type: timestamp
- - field: activatedDate
- note: "重新激活日期"
- from: common.date.v1.yaml
- use: dateB
- prefix: ""
- postfix: ""
- loop: 0
- format: "YY/MM/DD"
- type: timestamp
- field: deleted
note: "是否删除"
range: 0
diff --git a/test/data/taskspec.yaml b/test/data/taskspec.yaml
index 3e37ac5718..febb226f21 100644
--- a/test/data/taskspec.yaml
+++ b/test/data/taskspec.yaml
@@ -30,16 +30,14 @@ fields:
format: ""
- field: estStarted
note: "预计开始"
- from: common.date.v1.yaml
- use: dateB
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- field: deadline
note: "截止时间"
- from: common.date.v1.yaml
- use: dateB
+ range: ""
prefix: ""
postfix: ""
loop: 0
diff --git a/test/data/team.yaml b/test/data/team.yaml
index db08ac1352..99ea1c6781 100644
--- a/test/data/team.yaml
+++ b/test/data/team.yaml
@@ -32,7 +32,7 @@ fields:
- field: account1
range: admin,user{98},test{100},pm{100},po{100}
- field: account2
- range: [],3-100,1-100,1-100,1-100
+ range: "[],3-100,1-100,1-100,1-100"
prefix: ""
postfix: ""
loop: 0
diff --git a/test/data/todo.yaml b/test/data/todo.yaml
index bc232b8951..5fa53b09c3 100644
--- a/test/data/todo.yaml
+++ b/test/data/todo.yaml
@@ -16,7 +16,7 @@ fields:
- field: account1
range: admin,user{99},test{100},dev{100},pm{100},po{100},td{100},pd{100},qd{100},top{100},outside{100}
- field: account2
- range: [],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100
+ range: "[],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100"
prefix: ""
postfix: ""
loop: 0
@@ -50,7 +50,7 @@ fields:
postfix: ""
loop: 0
format: ""
- - field: idvalue
+ - field: objectID
note: "关联编号"
range: 0,1-20,1-20,1-20,1-20
prefix: ""
@@ -108,7 +108,7 @@ fields:
- field: ass1
range: admin,user{99},test{100},dev{100},pm{100},po{100},td{100},pd{100},qd{100},top{100},outside{100}
- field: ass2
- range: [],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100
+ range: "[],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100"
prefix: ""
postfix: ""
format: ""
@@ -118,7 +118,7 @@ fields:
- field: ass1
range: admin,user{99},test{100},dev{100},pm{100},po{100},td{100},pd{100},qd{100},top{100},outside{100}
- field: ass2
- range: [],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100
+ range: "[],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100"
prefix: ""
postfix: ""
format: ""
@@ -131,33 +131,25 @@ fields:
format: "YY-MM-DD hh:mm:ss"
- field: finishedBy
note: "由谁完成"
- from: common.user.v1.yaml
- use: user
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- field: finishedDate
note: "完成时间"
- from: common.date.v1.yaml
- use: dateA
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- field: closedBy
note: "由谁关闭"
- from: common.user.v1.yaml
- use: user
+ range: ""
prefix: ""
postfix: ""
loop: 0
format: ""
- field: closedDate
note: "关闭时间"
- from: common.date.v1.yaml
- use: dateA
- prefix: ""
- postfix: ""
- loop: 0
- format: ""
+ range: ""
diff --git a/test/data/user.yaml b/test/data/user.yaml
index 8cd98914ea..bd2aa6dc32 100644
--- a/test/data/user.yaml
+++ b/test/data/user.yaml
@@ -26,7 +26,7 @@ fields:
- field: account1
range: admin,user{99},test{100},dev{100},pm{100},po{100},td{100},pd{100},qd{100},top{100},outside{100},others{100},a,bb,ccc,qwuiadsd?!2as@#%$aasd~aj1!@#1
- field: account2
- range: [],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,[]{4}
+ range: "[],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,[]{4}"
- field: password
note: "密码"
range: 123Qwe!@#{346}
@@ -44,7 +44,7 @@ fields:
- field: realname1
range: admin,用户{99},测试{100},开发{100},项目经理{100},产品经理{100},研发主管{100},产品主管{100},测试主管{100},高层管理{100},外用户{100},其他{100},A,BB,CCC,非常长非常长的用户名怎么这么长?
- field: realname2
- range: [],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,[]{4}
+ range: "[],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,[]{4}"
- field: nickname
note: "昵称"
- field: commiter
@@ -53,10 +53,10 @@ fields:
- field: commiter1
range: admin,user{99},test{100},dev{100},pm{100},po{100},td{100},pd{100},qd{100},top{100},outside{100},others{100},a,bb,ccc,qwuiadsd?!2as@#%$aasd~aj1!@#1
- field: commiter2
- range: [],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,[]{4}
+ range: "[],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,[]{4}"
- field: avatar
note: ""
- range: []
+ range: ""
format: ""
- field: birthday
note: "生日"
@@ -78,7 +78,7 @@ fields:
- field: email2
range: 1000-9999:2
- field: email3
- range: [@qq.com,@163.com,@gmail.com]
+ range: "[@qq.com,@163.com,@gmail.com]"
- field: skype
note: "Skype"
range: Skype
@@ -123,12 +123,10 @@ fields:
note: "邮编"
- field: join
note: "入职日期"
- from: common.date.v1.yaml
- use: dateB
- prefix: ""
+ range: "(M)-(w)"
+ type: timestamp
postfix: ""
- loop: 0
- format: ""
+ format: "YY/MM/DD hh:mm:ss"
- field: visits
note: "访问次数"
range: 0-10000:R
@@ -155,7 +153,7 @@ fields:
range: 1-10000
- field: locked
note: "锁定时间"
- range: 0
+ range: "`2023-01-02 10:00:00`"
- field: company
note: "公司"
range: 1
@@ -165,12 +163,13 @@ fields:
- field: account1
range: admin,user{99},test{100},dev{100},pm{100},po{100},td{100},pd{100},qd{100},top{100},outside{100},others{100},a,bb,ccc,qwuiadsd?!2as@#%$aasd~aj1!@#1
- field: account2
- range: [],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,[]{4}
+ range: "[],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,[]{4}"
- field: score
note: "积分"
range: 1-10000:R
- field: scoreLevel
note: "积分等级"
+ range: 0
- field: deleted
note: "是否删除"
range: 0
diff --git a/test/devdata/action.yaml b/test/devdata/action.yaml
new file mode 100644
index 0000000000..6e4202e1cc
--- /dev/null
+++ b/test/devdata/action.yaml
@@ -0,0 +1,78 @@
+title: table zt_action
+desc: "系统日志"
+author: automated export
+version: "1.0"
+fields:
+ - field: objectType
+ note: "对象类型"
+ range: product{1000},story{30000},productplan{1000},project{10000},task{300000},bug{300000},user{10000},todo{2000}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: objectID
+ note: "对象ID"
+ range: 1-1000,1-30000,1-1000,1-10000,1-300000,1-300000,1-10000,1-2000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: product
+ note: "产品"
+ range: 1-1000
+ prefix: ","
+ postfix: ","
+ loop: 0
+ format: ""
+ - field: project
+ note: "项目"
+ range: 1001-20000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: actor
+ note: "操作者"
+ fields:
+ - field: actor1
+ range: admin,dev,test,pm,po
+ - field: actor2
+ range: [],1-1000,1-1000,1-1000,1-1000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: action
+ note: "动作"
+ range: common,extra,opened,created,changed,edited,assigned,closed,deleted,deletedfile,editfile,erased,undeleted,hidden,commented,activated,blocked,moved,confirmed,caseconfirmed,bugconfirmed,frombug,started,restarted,delayed,suspended,recordestimate,editestimate,deleteestimate,canceled,svncommited,gitcommited,finished,paused,verified,diff1,diff2,diff3,linked2bug
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: date
+ note: "日期"
+ range: "(-1M)-(w):1D"
+ type: timestamp
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: comment
+ note: "备注"
+ range: 1-100000
+ prefix: "这是一个系统日志测试备注"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: extra
+ note: "附加参数"
+ range: 1{4},11,1{3}, 2 ,1{18},33,1{22},101,1{22},131,1{22},161,1{3}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ - field: read
+ note: ""
+ range: "0,1"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/asset.yaml b/test/devdata/asset.yaml
new file mode 100644
index 0000000000..db6e0aea57
--- /dev/null
+++ b/test/devdata/asset.yaml
@@ -0,0 +1,20 @@
+title: zt_asset
+author: Zeng gang
+version: "1.0"
+fields:
+ - field: id
+ range: 1
+ - field: name
+ range: host_test
+ - field: status
+ range: normal
+ - field: type
+ range: host
+ - field: createdBy
+ range: admin
+ - field: createdDate
+ range: [2022-03-07 10:44:23]
+ - field: registerDate
+ range: [2022-03-07 10:44:23]
+ - field: deleted
+ range: 0
diff --git a/test/devdata/block.yaml b/test/devdata/block.yaml
new file mode 100644
index 0000000000..fc569bbf3d
--- /dev/null
+++ b/test/devdata/block.yaml
@@ -0,0 +1,32 @@
+title: zt_block
+author: Tian shujie
+version: "1.0"
+fields:
+ - field: id
+ range: 1-10000
+ - field: account
+ fields:
+ - field: account1
+ range:
+ - field: account2
+ range:
+ - field: module
+ range: my{16},product{5},project{5},qa{4}
+ - field: type
+ range: []{21},scrum{5},[]{4}
+ - field: title
+ range: [欢迎,最新动态,我的贡献,待处理,我的待办,项目统计,我近期参与的项目,项目人力投入,项目列表,版本列表,执行统计,执行总览,执行列表,任务列表,产品统计,测试统计,产品统计,未关闭的产品,指派给我的软件需求,发布列表,计划列表,项目概况,迭代列表,待测版本,迭代总览,最新动态,测试统计,由我创建的Bug,指派给我的用例,所有版本列表]
+ - field: source
+ range: []{4},todo,project{4},execution{5},product,qa,product{5},project{5},qa{4}
+ - field: block
+ range: [welcome,dynamic,contribute,assigntome,list,statistic,recentproject,projectteam,project,build,statistic,overview,list,task,statistic,statistic,statistic,list,story,release,plan,scrumoverview,scrumlist,scrumtest,sprint,projectdynamic,statistic,bug,case,testtask]
+ - field: params
+ range: []{3},`{"todoCount":"20","taskCount":"20","bugCount":"20","riskCount":"20","issueCount":"20","storyCount":"20","meetingCount":"20"}`,`{"count":"10"}`,`{"type":"undone","count":"15"}`, , ,`{"orderBy":"id_desc","count":"15"}`,`{"count":"20"}`,`{"type":"undone","count":"20"}`, ,`{"type":"doing","count":"20"}`,`{"type":"assignedTo","count":"20","orderBy":"id_desc"}`,`{"type":"all","count":"20"}`,`{"type":"all","count":"20"}`,`{"type":"closed","count":"20"}`,`{"count":"15","type":"noclosed"}`,`{"count":"15","orderBy":"id_desc","type":"assignedTo"}`,`{"count":"10"}`,`{"count":"10"}`,`{"count":"10"}`,`{"type":"involved","count":"10"}`,`{"type":"wait","count":"15"}`, , ,`{"type":"noclosed","count":"20"}`,`{"count":"15","orderBy":"id_asc","type":"openedBy"}`,`{"count":"15","orderBy":"pri_asc","type":"assigntome"}`,`{"count":"15","orderBy":"id_desc","type":"all"}`
+ - field: order
+ range: 1-16,1-5,1-5,1-4
+ - field: grid
+ range: 8{2},4,8,4{3},8{4},4,8{5},4{3},8,4{2},8{4},4{2},8
+ - field: height
+ range: 0
+ - field: hidden
+ range: 0
diff --git a/test/devdata/branch.yaml b/test/devdata/branch.yaml
new file mode 100644
index 0000000000..6617f10ca2
--- /dev/null
+++ b/test/devdata/branch.yaml
@@ -0,0 +1,30 @@
+title: table zt_branch
+desc: "平台/分支"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ - field: product
+ note: "所属产品"
+ range: 41-120{2},1-3{2}, 141-180{2}
+ - field: name
+ note: "名称"
+ fields:
+ - field: name1
+ range: 分支
+ - field: name2
+ range: 1-10000
+ - field: status
+ range: active,closed
+ - field: order
+ note: "排序"
+ range: 1-2
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
diff --git a/test/devdata/bug.yaml b/test/devdata/bug.yaml
new file mode 100644
index 0000000000..85bee95f81
--- /dev/null
+++ b/test/devdata/bug.yaml
@@ -0,0 +1,89 @@
+title: zt_bug
+desc: Bug表
+version: 1.0
+fields:
+ - field: id
+ range: 1-500000
+ - field: project
+ range: 1001-20000{20},1001-13000{10}
+ - field: product
+ range: 1-1000{500}
+ - field: branch
+ range: 0
+ - field: module
+ range: 0
+ - field: execution
+ range: 20001-50000{10},20001-40000{10}
+ - field: plan
+ range: 1-1000{500}
+ - field: story
+ range: 1-50000{100}
+ - field: storyVersion
+ range: 1
+ - field: task
+ range: 0
+ - field: toTask
+ range: 0
+ - field: toStory
+ range: 0
+ - field: title
+ fields:
+ - field: title1
+ range: BUG
+ - field: title2
+ range: 1-1000000
+ - field: severity
+ range: 1-4
+ - field: pri
+ range: 1-4
+ - field: type
+ range: [codeerror,config,install,security,performance,standard,automation,designdefect,others]
+ - field: os
+ range: []{2},[win10,windows,android,ios]
+ - field: steps
+ range: steps
+ - field: status
+ range: active
+ - field: color
+ range: [#3da7f5,#75c941,#2dbdb2,#797ec9,#ffaf38,#ff4e3e]
+ - field: confirmed
+ range: 0,1
+ - field: activatedCount
+ range: 0
+ - field: mailto
+ range: admin{100},[]{200}
+ - field: openedBy
+ range: admin
+ - field: openedDate
+ range: "(-1M)-(+1w):-1D"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: openedBuild
+ range: 1,0,1,trunk{97}
+ - field: assignedTo
+ range: [admin,dev1,test1]{30},[]{20},[admin,dev1,test1]{20},[]{10},closed{20}
+ - field: assignedDate
+ range: "(-1M)-(+1w):-1D"
+ type: timestamp
+ format: "YYYY-MM-DD"
+ - field: deadline
+ range: "(-1M)-(+1w):-1D"
+ type: timestamp
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: "YYYY-MM-DD"
+ - field: duplicateBug
+ range: 0
+ - field: case
+ range: 0
+ - field: caseVersion
+ range: 0
+ - field: result
+ range: 0
+ - field: repo
+ range: 0
+ - field: testtask
+ range: 0
+ - field: deleted
+ range: 0
diff --git a/test/devdata/bugmodule.yaml b/test/devdata/bugmodule.yaml
new file mode 100644
index 0000000000..ebf7c70837
--- /dev/null
+++ b/test/devdata/bugmodule.yaml
@@ -0,0 +1,79 @@
+title: table zt_module
+desc: "模块"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 4221-4320
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: root
+ note: "根目录"
+ range: 1-100
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: branch
+ note: "分支"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "模块名称"
+ range: 1-10000
+ prefix: "bug模块"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父ID"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: path
+ note: "ID路径"
+ fields:
+ - field: path1
+ range: 4221-4320
+ prefix: ","
+ postfix: ","
+ - field: path2
+ range: []
+ postfix: ""
+ format: ""
+ - field: grade
+ note: "等级"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 10-100:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "对象类型"
+ range: bug
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/bugmoduleson.yaml b/test/devdata/bugmoduleson.yaml
new file mode 100644
index 0000000000..5acaca688a
--- /dev/null
+++ b/test/devdata/bugmoduleson.yaml
@@ -0,0 +1,79 @@
+title: table zt_module
+desc: "模块"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 4321-4520
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: root
+ note: "根目录"
+ range: 1-100{2}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: branch
+ note: "分支"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "模块名称"
+ range: 1-10000
+ prefix: "bug子模块"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父ID"
+ range: 4221-4320{2}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: path
+ note: "ID路径"
+ fields:
+ - field: path1
+ range: 4221-4320{2}
+ prefix: ","
+ postfix: ","
+ - field: path2
+ range: 4321-4520
+ postfix: ","
+ format: ""
+ - field: grade
+ note: "等级"
+ range: 2
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 10-100:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "对象类型"
+ range: bug
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/build.yaml b/test/devdata/build.yaml
new file mode 100644
index 0000000000..c2d5024c03
--- /dev/null
+++ b/test/devdata/build.yaml
@@ -0,0 +1,73 @@
+title: table zt_build
+desc: ""
+version: "1.0"
+fields:
+ - field: id
+ range: 1-1000
+
+ - field: project
+ range: 0
+
+ - field: product
+ range: 1-1000
+
+ - field: branch
+ range: 0
+
+ - field: execution
+ range: 20001-21000
+
+ - field: name
+ fields:
+ - field: name1
+ range: 执行版本
+
+ - field: name3
+ range: 1-1000
+
+ - field: scmPath
+ fields:
+ - field: scmPath1
+ range: [git.zcorp.cc/easycorp/,svn.zcorp.cc/easysoft/trunk/zentaoext/]{3},[]{2}
+
+ - field: scmPath2
+ range: zentaopms,xuanxuan,zdoo,zentaopro,zentaobiz,zentaomax,[]{2}
+
+ - field: scmPath3
+ range: [.git]{3},[]{5}
+
+ - field: filePath
+ range: [www.csdn.net/,www.baidu.com/,www.juejin.cn/]{2},[]{2}
+
+ - field: date
+ range: "(-1M)-(+1w):60"
+ type: timestamp
+ format: "YYYY-MM-DD"
+
+ - field: stories
+ fields:
+ - field: story1
+ range: 2-400:4
+ prefix: ""
+ postfix: ","
+ - field: story2
+ range: 4-400:4
+
+ - field: bugs
+ fields:
+ - field: bug1
+ range: 1-300:3
+ prefix: ""
+ postfix: ","
+ - field: bug2
+ range: 2-400:3
+
+ - field: builder
+ range: 1-1000
+ prefix: "test"
+
+ - field: desc
+ range: 司法局阿里水电费加快了时代峰峻辣三丁防 显卡鲁大师,,,asdf,,
qoqao穷OA怄气袄怄气欧文饿哦啊OAof噢诶区文诗 熊熊0哦到OA山东全文怄气袄安全o
zmvzxcmv啊,。你啊是否为欧舒斯蒂芬你先吃,哪吒,门下车,哦企鹅跑跑水电费,充满着那些,聪明在,需自行车,起伏阿萨德从,名字
+
+ - field: deleted
+ range: 0
diff --git a/test/devdata/case.yaml b/test/devdata/case.yaml
new file mode 100644
index 0000000000..ff89d37edf
--- /dev/null
+++ b/test/devdata/case.yaml
@@ -0,0 +1,148 @@
+title: table zt_case
+desc: "测试用例"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-100000
+ - field: product
+ note: "产品ID"
+ range: 1-1000{10}
+ - field: branch
+ note: "分支ID"
+ range: 0
+ - field: execution
+ note: "执行ID"
+ range: 20001-50000{3},20001-30000
+ - field: lib
+ note: "所属库"
+ range: 0
+ - field: module
+ note: "所属模块"
+ range: 0
+ - field: path
+ note: ""
+ range: "0"
+ - field: story
+ note: "相关需求"
+ range: 1-50000{2}
+ - field: storyVersion
+ note: "需求版本"
+ range: "1"
+ - field: title
+ note: "用例标题"
+ range: "1-100000"
+ prefix: "这个是测试用例"
+ - field: precondition
+ note: "前置条件"
+ range: "1-100000"
+ prefix: "这是前置条件"
+ - field: keywords
+ note: "关键词"
+ range: "1-100000"
+ prefix: "这是关键词"
+ - field: pri
+ note: "优先级"
+ range: 1-4
+ - field: type
+ note: "用例类型"
+ range: feature,performance,config,install,security,interface,other
+ - field: auto
+ note: "是否是自动化测试用例"
+ range: "no"
+ - field: frame
+ note: "自动化测试框架"
+ range: ""
+ - field: stage
+ note: "适用阶段"
+ range: unittest,feature,intergrate,system,smoke,bvt
+ - field: howRun
+ note: "测试方式"
+ range: ""
+ - field: scriptedBy
+ note: "脚本由谁创建"
+ range: ""
+ - field: scriptedDate
+ note: "脚本创建日期"
+ range: "(M)-(w)"
+ type: timestamp
+ postfix: ""
+ format: "YY/MM/DD"
+ - field: scriptStatus
+ note: "脚本状态"
+ range: ""
+ - field: scriptLocation
+ note: "脚本地址"
+ range: ""
+ - field: status
+ note: "用例状态"
+ range: wait,normal,blocked,investigate
+ - field: subStatus
+ note: "子状态"
+ range: ""
+ - field: color
+ note: "标题颜色"
+ from: common.color.v1.yaml
+ use: color
+ - field: frequency
+ note: "使用频率"
+ range: 1-3
+ - field: order
+ note: "排序"
+ range: 1-30
+ - field: openedBy
+ note: "由谁创建"
+ range: 1-1000
+ prefix: "test"
+ - field: openedDate
+ note: "创建日期"
+ range: "-:600"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: reviewedBy
+ note: "由谁评审"
+ range: admin
+ - field: reviewedDate
+ note: "评审时间"
+ range: "-:300"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: lastEditedBy
+ note: "最后修改者"
+ range: admin
+ - field: lastEditedDate
+ note: "修改日期"
+ range: "-:300"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: version
+ note: "用例版本"
+ range: "1"
+ - field: linkCase
+ note: "相关用例"
+ range: 0
+ - field: fromBug
+ note: "来源Bug"
+ range: 0
+ - field: fromCaseID
+ note: ""
+ range: 0
+ - field: fromCaseVersion
+ note: ""
+ range: 1
+ - field: deleted
+ note: "是否删除"
+ range: 0{99950},1{50}
+ - field: lastRunner
+ note: "执行人"
+ range: 1-1000
+ prefix: "test"
+ - field: lastRunDate
+ note: "执行时间"
+ range: "-:500"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: lastRunResult
+ note: "结果"
+ range: [pass,fail]
diff --git a/test/devdata/casemodule.yaml b/test/devdata/casemodule.yaml
new file mode 100644
index 0000000000..8fb415f48c
--- /dev/null
+++ b/test/devdata/casemodule.yaml
@@ -0,0 +1,79 @@
+title: table zt_module
+desc: "模块"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 3921-4020
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: root
+ note: "根目录"
+ range: 1-100
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: branch
+ note: "分支"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "模块名称"
+ range: 1-10000
+ prefix: "用例模块"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父ID"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: path
+ note: "ID路径"
+ fields:
+ - field: path1
+ range: 3921-4020
+ prefix: ","
+ postfix: ","
+ - field: path2
+ range: []
+ postfix: ""
+ format: ""
+ - field: grade
+ note: "等级"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 10-100:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "对象类型"
+ range: case
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/casemoduleson.yaml b/test/devdata/casemoduleson.yaml
new file mode 100644
index 0000000000..fda32f9d6c
--- /dev/null
+++ b/test/devdata/casemoduleson.yaml
@@ -0,0 +1,79 @@
+title: table zt_module
+desc: "模块"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 4021-4220
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: root
+ note: "根目录"
+ range: 1-100{2}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: branch
+ note: "分支"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "模块名称"
+ range: 1-10000
+ prefix: "用例子模块"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父ID"
+ range: 3921-4020{2}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: path
+ note: "ID路径"
+ fields:
+ - field: path1
+ range: 3921-4020{2}
+ prefix: ","
+ postfix: ","
+ - field: path2
+ range: 4021-4220
+ postfix: ","
+ format: ""
+ - field: grade
+ note: "等级"
+ range: 2
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 10-100:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "对象类型"
+ range: case
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/casestep.yaml b/test/devdata/casestep.yaml
new file mode 100644
index 0000000000..f3788588cd
--- /dev/null
+++ b/test/devdata/casestep.yaml
@@ -0,0 +1,54 @@
+title: table zt_casestep
+desc: "用例步骤"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: "1-100000"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "上级ID"
+ range: "0"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: case
+ note: "所属用例ID"
+ range: "1-100000"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: version
+ note: "用例版本"
+ range: "1"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "用例类型"
+ range: "step"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: desc
+ note: "用例步骤"
+ range: "1-100000"
+ prefix: "用例步骤描述"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: expect
+ note: "预期"
+ range: "1-100000"
+ prefix: "这是用例预期结果"
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/childstory.yaml b/test/devdata/childstory.yaml
new file mode 100644
index 0000000000..d29bd61ef0
--- /dev/null
+++ b/test/devdata/childstory.yaml
@@ -0,0 +1,283 @@
+title: table zt_story
+desc: "需求"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ range: 401-10000
+ - field: parent
+ note: "父需求ID"
+ range: 351-400
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: product
+ note: "所属产品"
+ range: 88{2},89-100{4}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: branch
+ note: "分支/平台"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: module
+ note: "所属模块"
+ range: 2171-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: plan
+ note: "所属计划"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: source
+ note: "需求来源"
+ range: customer,user,po,market,service,operation,support,competitor,partner,dev,tester,bug,forum,other
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: sourceNote
+ note: "来源备注"
+ range: 1-10000
+ prefix: "这里是需求来源备注"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: fromBug
+ note: "来源Bug"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: title
+ note: "需求名称"
+ fields:
+ - field: field1
+ range: [用户子需求,软件子需求]
+ - field: field2
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: keywords
+ note: "关键词"
+ range: 1-10000
+ prefix: "关键词"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "需求类型"
+ range: requirement,story
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: pri
+ note: "优先级"
+ range: 1-4
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: estimate
+ note: "预计工时"
+ range: 0-20:2
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: status
+ note: "当前状态"
+ range: draft,active,closed,changed
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: subStatus
+ note: "子状态"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: color
+ note: "标题颜色"
+ from: common.color.v1.yaml
+ use: color
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: stage
+ note: "所处阶段"
+ range: wait,planned,projected,developing,developed,testing,tested,verified,released,closed
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: stagedBy
+ note: "设置阶段者"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: mailto
+ note: "抄送给"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: openedBy
+ note: "由谁创建"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: openedDate
+ note: "创建日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: assignedTo
+ note: "指派给"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: assignedDate
+ note: "指派日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: lastEditedBy
+ note: "最后修改者"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: lastEditedDate
+ note: "最后修改日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: reviewedBy
+ note: "评审者"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: reviewedDate
+ note: "评审日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedBy
+ note: "关闭者"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedDate
+ note: "关闭日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedReason
+ note: "关闭原因"
+ range: done,subdivided,duplicate,postponed,willnotdo,cancel,bydesign
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: toBug
+ note: "转Bug"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: childStories
+ note: "细分需求"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: linkStories
+ note: "相关需求"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: duplicateStory
+ note: "重复需求ID"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: version
+ note: "版本号"
+ range: 1{50}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: URChanged
+ note: "用户需求变更"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/common/color/v1.yaml b/test/devdata/common/color/v1.yaml
new file mode 100644
index 0000000000..ea7b4f5b8a
--- /dev/null
+++ b/test/devdata/common/color/v1.yaml
@@ -0,0 +1,13 @@
+title: color
+desc: 标题颜色
+author: ly
+version: 1.0
+
+field: color
+instances:
+ - instance: color
+ note: 标题颜色
+ fields:
+ - field: color
+ range: 3da7f5,75c941,2dbdb2,797ec9,ffaf38,ff4e3e
+ prefix: "#"
diff --git a/test/devdata/common/date/v1.yaml b/test/devdata/common/date/v1.yaml
new file mode 100644
index 0000000000..776a992201
--- /dev/null
+++ b/test/devdata/common/date/v1.yaml
@@ -0,0 +1,44 @@
+title: date
+desc: 系统可用日期类型
+author: ly
+version: 1.0
+
+field: date
+instances:
+ - instance: datetime
+ fields:
+ - field: year
+ range: 2019-2022
+ postfix: "-"
+ - field: month
+ range: 1-12
+ format: "%02d"
+ postfix: "-"
+ - field: day
+ range: 1-27
+ format: "%02d"
+ postfix: " "
+ - field: hour
+ range: 0-23
+ format: "%02d"
+ postfix: ":"
+ - field: minute
+ range: 0-59
+ format: "%02d"
+ postfix: ":"
+ - field: second
+ range: 0-59
+ format: "%02d"
+
+ - instance: date
+ fields:
+ - field: year
+ range: 2019-2022
+ postfix: "-"
+ - field: month
+ range: 1-12
+ format: "%02d"
+ postfix: "-"
+ - field: day
+ range: 1-27
+ format: "%02d"
diff --git a/test/devdata/common/file/v1.yaml b/test/devdata/common/file/v1.yaml
new file mode 100644
index 0000000000..342ed9a64f
--- /dev/null
+++ b/test/devdata/common/file/v1.yaml
@@ -0,0 +1,27 @@
+title: file
+desc: 文件上传相关
+author: ly
+version: 1.0
+
+instances:
+ - instance: pathname
+ note: 文件路径名称
+ fields:
+ - field: item1
+ range: "202001-202009"
+ postfix: "/"
+ - field: item2
+ range: "10001-20000"
+ prefix: "04142250066"
+ - field: item3
+ range: "txt,doc,docx,dot,wps,wri,pdf,ppt,pptx,xls,xlsx,ett,xlt,xlsm,csv,jpg,jpeg,png,psd,gif,ico,bmp,swf,avi,rmvb,rm,mp3,mp4,3gp,flv,mov,movie,rar,zip,bz,bz2,tar,gz,mpp,rp,pdm,vsdx,vsd,sql"
+ prefix: "."
+ - instance: title
+ note: 文件名称
+ fields:
+ - field: item1
+ range: "1-10000"
+ prefix: "这是一个文件名称"
+ - field: item2
+ range: "txt,doc,docx,dot,wps,wri,pdf,ppt,pptx,xls,xlsx,ett,xlt,xlsm,csv,jpg,jpeg,png,psd,gif,ico,bmp,swf,avi,rmvb,rm,mp3,mp4,3gp,flv,mov,movie,rar,zip,bz,bz2,tar,gz,mpp,rp,pdm,vsdx,vsd,sql"
+ prefix: "."
diff --git a/test/devdata/common/groups/v1.yaml b/test/devdata/common/groups/v1.yaml
new file mode 100644
index 0000000000..7c3780a9c3
--- /dev/null
+++ b/test/devdata/common/groups/v1.yaml
@@ -0,0 +1,45 @@
+title: groups
+desc: 权限白名单组合
+author: ly
+version: 1.0
+
+field: groups
+instances:
+ - instance: groups
+ note: 权限白名单组合
+ fields:
+ - field: item1
+ range: 1
+ postfix: ","
+ - field: item2
+ range: 2
+ postfix: ","
+ - field: item3
+ range: 3
+ postfix: ","
+ - field: item4
+ range: 4
+ postfix: ","
+ - field: item5
+ range: 5
+ postfix: ","
+ - field: item6
+ range: 6
+ postfix: ","
+ - field: item7
+ range: 7
+ postfix: ","
+ - field: item8
+ range: 8
+ postfix: ","
+ - field: item9
+ range: 9
+ postfix: ","
+ - field: item10
+ range: 10
+ postfix: ","
+ - field: item11
+ range: 11
+ postfix: ","
+ - field: item12
+ range: 12
diff --git a/test/devdata/common/ip/v1.yaml b/test/devdata/common/ip/v1.yaml
new file mode 100644
index 0000000000..5fc8482a39
--- /dev/null
+++ b/test/devdata/common/ip/v1.yaml
@@ -0,0 +1,33 @@
+title: ip
+desc: IP地址
+author:
+version: 1.0
+
+field: ip
+instances:
+ - instance: ipA
+ note: A类IP地址
+ prefix: 192.168.
+ postfix: ""
+ loop: 0
+ fields:
+ - field: part3
+ range: 0-254
+ postfix: .
+ - field: part4
+ range: 1-254
+
+ - instance: ipB
+ note: B类IP地址
+ prefix: 172.
+ postfix: ""
+ loop: 0
+ fields:
+ - field: part2
+ range: 16-31
+ postfix: .
+ - field: part3
+ range: 0-255
+ postfix: .
+ - field: part4
+ range: 0-255
diff --git a/test/devdata/common/phone/v1.yaml b/test/devdata/common/phone/v1.yaml
new file mode 100644
index 0000000000..19252334d3
--- /dev/null
+++ b/test/devdata/common/phone/v1.yaml
@@ -0,0 +1,31 @@
+title: phone
+desc: 手机号
+author:
+version: 1.0
+
+field: phone
+instances:
+ - instance: phone
+ note: 手机号
+ prefix: 1
+ postfix: ""
+ loop: 0
+ fields:
+ - field: part1
+ range: 30-99:R
+ - field: part2
+ range: 0-9:R
+ - field: part3
+ range: 0-9:R
+ - field: part4
+ range: 0-9:R
+ - field: part5
+ range: 0-9:R
+ - field: part6
+ range: 0-9:R
+ - field: part7
+ range: 0-9:R
+ - field: part8
+ range: 0-9:R
+ - field: part9
+ range: 0-9:R
diff --git a/test/devdata/common/user/v1.yaml b/test/devdata/common/user/v1.yaml
new file mode 100644
index 0000000000..ea2b932cd6
--- /dev/null
+++ b/test/devdata/common/user/v1.yaml
@@ -0,0 +1,51 @@
+title: user
+desc: 创建一些默认用户
+author: ly
+version: 1.0
+
+field: user
+instances:
+ - instance: empty
+ fields:
+ - field: user
+ range:
+ - instance: one
+ fields:
+ - field: user
+ range: admin,dev1,dev2,dev3,test1,test2,test3
+
+ - instance: two
+ fields:
+ - field: user1
+ range: admin
+ postfix: ","
+ - field: user2
+ range: dev1
+ postfix: ","
+
+ - instance: three
+ fields:
+ - field: user1
+ range: admin
+ postfix: ","
+ - field: user2
+ range: dev1
+ postfix: ","
+ - field: user3
+ range: dev2
+ postfix: ","
+
+ - instance: four
+ fields:
+ - field: user1
+ range: admin
+ postfix: ","
+ - field: user2
+ range: dev1
+ postfix: ","
+ - field: user3
+ range: dev2
+ postfix: ","
+ - field: user4
+ range: dev3
+ postfix: ","
diff --git a/test/devdata/common/version/v1.yaml b/test/devdata/common/version/v1.yaml
new file mode 100644
index 0000000000..95dd699c57
--- /dev/null
+++ b/test/devdata/common/version/v1.yaml
@@ -0,0 +1,15 @@
+title: version
+desc: 版本记录
+author:
+version: 1.0
+
+field: version
+instances:
+ - instance: version
+ note: 版本列表
+ prefix: ""
+ postfix: ""
+ loop: 0
+ fields:
+ - field: v1
+ range: 10.0.alpha,10.0.bate,10.0,10.3.1,10.4,10.5.1,11.1,11.2,11.3,11.4.1,11.4,11.5.2,11.5,11.6.4,11.6.5,11.6,11.7,12.0.1,12.1,12.2
diff --git a/test/devdata/company.yaml b/test/devdata/company.yaml
new file mode 100644
index 0000000000..c9ab35ff84
--- /dev/null
+++ b/test/devdata/company.yaml
@@ -0,0 +1,31 @@
+title: table zt_company
+desc: "公司信息"
+author: sgm,har,zx
+version: "1.0"
+fields:
+ - field: id
+ note: "id"
+ range: 1-2
+ - field: name
+ note: "公司名"
+ range: 易软天创网络科技有限公司,外部公司
+ - field: admins
+ note: "管理员"
+ prefix: ","
+ range: admin
+ postfix: ","
+ - field: phone
+ note: "电话"
+ range: 15666933065
+ - field: zipcode
+ note: "邮编"
+ range: "100000"
+ - field: website
+ note: "网站"
+ range: www.zentao.net
+ - field: guest
+ note: "匿名登录"
+ range: 0
+ - field: deleted
+ note: "是否删除"
+ range: 0
diff --git a/test/devdata/dept.yaml b/test/devdata/dept.yaml
new file mode 100644
index 0000000000..87e7e0264f
--- /dev/null
+++ b/test/devdata/dept.yaml
@@ -0,0 +1,28 @@
+title: table zt_dept
+desc: "部门"
+author: Li yuchun
+version: "1.0"
+fields:
+ - field: id
+ range: 1-10000
+ - field: name
+ fields:
+ - field: name1
+ range: 产品部,开发部,测试部,运营部,开发部1,开发部2,测试名称长度能有多长并且包含特殊字符的一个长长的字符串!@#¥%……&×()哈哈哈哈,[一级部门,二级部门,三级部门]{10},其他部门{10000}
+ - field: name2
+ range: []{7},1-10,1-10,1-10,1-10000
+ - field: order
+ note: "排序"
+ range: 1-10000
+ - field: path
+ note: "路径"
+ range: 1-10000
+ prefix: ","
+ postfix: ","
+ - field: grade
+ note: "层级"
+ range: 1
+ - field: position
+ range: ""
+ - field: function
+ range: ""
diff --git a/test/devdata/design.yaml b/test/devdata/design.yaml
new file mode 100644
index 0000000000..15f4140653
--- /dev/null
+++ b/test/devdata/design.yaml
@@ -0,0 +1,134 @@
+title: table zt_design
+desc: "项目设计"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: project
+ note: "所属项目"
+ range: 41-70{4}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: product
+ note: "所属产品"
+ range: 31-60{4}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: commit
+ note: "相关提交"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "设计名称"
+ range: 1-10000
+ prefix: "这是一个设计"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: status
+ note: "状态"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: createdBy
+ note: "由谁创建"
+ range: admin
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: createdDate
+ note: "创建日期"
+ range: "(M)-(w)"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: editedBy
+ note: "由谁编辑"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: editedDate
+ note: "编辑者"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: assignedTo
+ note: "指派给"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: assignedBy
+ note: "由谁指派"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: assignedDate
+ note: "指派日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: story
+ note: "相关需求"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: desc
+ note: "描述"
+ range: 1-10000
+ prefix: "这是设计描述"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: version
+ note: "版本号"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "类型"
+ range: HLDS,DDS,DBDS,ADS
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/designspec.yaml b/test/devdata/designspec.yaml
new file mode 100644
index 0000000000..882ae4730f
--- /dev/null
+++ b/test/devdata/designspec.yaml
@@ -0,0 +1,35 @@
+title: table zt_designspec
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: design
+ note: ""
+ range: 1-120
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: version
+ note: ""
+ range: 1
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: name
+ note: ""
+ range: 1-10000
+ prefix: "这是一个设计"
+ postfix: ""
+ format: ""
+ - field: desc
+ note: ""
+ range: 1-10000
+ prefix: "这是设计描述"
+ postfix: ""
+ format: ""
+ - field: files
+ note: ""
+ range: ""
+ prefix: ""
+ postfix: ""
+ format: ""
diff --git a/test/devdata/doc.yaml b/test/devdata/doc.yaml
new file mode 100644
index 0000000000..ae39a9c7ca
--- /dev/null
+++ b/test/devdata/doc.yaml
@@ -0,0 +1,186 @@
+title: table zt_doc
+desc: "文档"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "文档编号"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: product
+ note: "所属产品"
+ range: 1-100,0{90},0{630},0{80}
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: project
+ note: "所属项目"
+ range: 0{100},11-100,0{630},0{80}
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: execution
+ note: "所属迭代"
+ range: 0{100},0{90},101-730,0{80}
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: lib
+ note: "所属文档库"
+ range: 1-900
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: template
+ note: "模板"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: templateType
+ note: "模板类型"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: chapterType
+ note: "章节类型"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: module
+ note: "模块"
+ range: 3621-3630,0{890}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: title
+ note: "文档标题"
+ range: 1-10000
+ prefix: "文档标题"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: keywords
+ note: "关键词"
+ range: 1-10000
+ prefix: "关键词"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "文档类型"
+ range: text,markdown,url
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父级ID"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: path
+ note: ""
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: grade
+ note: ""
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: views
+ note: ""
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: collects
+ note: "是否收藏"
+ range: 0,1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: addedBy
+ note: "添加者"
+ range: admin
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: addedDate
+ note: "添加日期"
+ range: Y-m-d
+ prefix: ""
+ type: timestamp
+ postfix: ""
+ format: "YYYY-MM-DD"
+ - field: editedBy
+ note: "编辑者"
+ range: admin
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: editedDate
+ note: "编辑日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: acl
+ note: "权限"
+ range: open,custom,private
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: groups
+ note: "分组"
+ range: 0,1,1
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: users
+ note: "用户"
+ range: 0,admin,admin
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: version
+ note: "版本号"
+ range: 2{10},1{890}
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ format: ""
diff --git a/test/devdata/doccontent.yaml b/test/devdata/doccontent.yaml
new file mode 100644
index 0000000000..0a9d65af62
--- /dev/null
+++ b/test/devdata/doccontent.yaml
@@ -0,0 +1,64 @@
+title: table zt_doccontent
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: doc
+ note: "文档ID"
+ range: 1-900
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: title
+ note: "文档标题"
+ range: 1-10000
+ prefix: "文档标题"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: digest
+ note: "文档摘要"
+ range: 1-10000
+ prefix: "文档摘要"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: content
+ note: "文档正文"
+ fields:
+ - field: content1
+ range: 文档正文,文档正文,www.baidu.com
+ - field: content2
+ range: 1-2,[]
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: files
+ note: "附件ID"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "文档类型"
+ range: text,markdown,html
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: version
+ note: "版本号"
+ range: 1{900},2{10}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/doclib.yaml b/test/devdata/doclib.yaml
new file mode 100644
index 0000000000..31b3ee360d
--- /dev/null
+++ b/test/devdata/doclib.yaml
@@ -0,0 +1,95 @@
+title: table zt_doclib
+desc: "文档库"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "文档类型"
+ range: product{100},project{90},execution{630},custom{80},api{10}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: product
+ note: "产品库"
+ range: 1-100,0{90},0{630},0{90}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: project
+ note: "项目库"
+ range: 0{100},11-100,0{630},0{90}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: execution
+ note: "执行库"
+ range: 0{100},0{90},101-730,0{90}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "文档库名称"
+ range: 产品主库{100},项目主库{90},迭代主库{30},阶段主库{30},看板主库{30},迭代主库{30},阶段主库{30},看板主库{30},迭代主库{30},阶段主库{30},看板主库{30},迭代主库{30},阶段主库{30},看板主库{30},迭代主库{30},阶段主库{30},看板主库{30},迭代主库{30},阶段主库{30},看板主库{30},迭代主库{30},阶段主库{30},阶段主库{30},自定义库{80},接口库{10}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: acl
+ note: "权限"
+ range: default{820},open{80},private{2},open{5},custom{3}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: groups
+ note: "权限分组"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: users
+ note: "用户"
+ range: "admin"
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: main
+ note: "文档主库"
+ range: 0{820},1{80},0{10}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: collector
+ note: "是否收藏"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 10-100:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/docmodule.yaml b/test/devdata/docmodule.yaml
new file mode 100644
index 0000000000..f17e67fab1
--- /dev/null
+++ b/test/devdata/docmodule.yaml
@@ -0,0 +1,79 @@
+title: table zt_module
+desc: "模块"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 3621-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: root
+ note: "根目录"
+ range: 1-100
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: branch
+ note: "分支"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "模块名称"
+ range: 1-10000
+ prefix: "目录"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父ID"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: path
+ note: "ID路径"
+ fields:
+ - field: path1
+ range: 3621-3720
+ prefix: ","
+ postfix: ","
+ - field: path2
+ range: []
+ postfix: ""
+ format: ""
+ - field: grade
+ note: "等级"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 10-100:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "对象类型"
+ range: doc
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/docmoduleson.yaml b/test/devdata/docmoduleson.yaml
new file mode 100644
index 0000000000..cd67afc94b
--- /dev/null
+++ b/test/devdata/docmoduleson.yaml
@@ -0,0 +1,79 @@
+title: table zt_module
+desc: "模块"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 3721-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: root
+ note: "根目录"
+ range: 1-100{2}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: branch
+ note: "分支"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "模块名称"
+ range: 1-10000
+ prefix: "子目录"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父ID"
+ range: 3621-3720{2}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: path
+ note: "ID路径"
+ fields:
+ - field: path1
+ range: 3621-3720{2}
+ prefix: ","
+ postfix: ","
+ - field: path2
+ range: 3721-3920
+ postfix: ","
+ format: ""
+ - field: grade
+ note: "等级"
+ range: 2
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 10-100:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "对象类型"
+ range: doc
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/effort.yaml b/test/devdata/effort.yaml
new file mode 100644
index 0000000000..16699b5e26
--- /dev/null
+++ b/test/devdata/effort.yaml
@@ -0,0 +1,89 @@
+title: table zt_effort
+desc: "任务工时记录"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: "1-10000"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: objectType
+ note: "对象类型"
+ range: "custom"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: objectID
+ note: "对象ID"
+ range: "0"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: product
+ note: "产品ID"
+ range: "0"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: project
+ note: "项目ID"
+ range: "0"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: account
+ note: "用户账号"
+ fields:
+ - field: account1
+ range: admin,user{99}
+ - field: account2
+ range: [],1-99
+ format: ""
+ - field: work
+ note: "工作内容"
+ range: "1-10000"
+ prefix: "这是工作内容"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: date
+ note: "创建日期"
+ range: "(M)-(w)"
+ type: timestamp
+ postfix: ""
+ format: "YY/MM/DD"
+ - field: left
+ note: "剩余"
+ range: "0"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: consumed
+ note: "消耗"
+ range: 1-100:5
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: begin
+ note: "开始"
+ range: 1000-1059:2
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: end
+ note: "结束"
+ range: 1400-1459:2
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/entry.yaml b/test/devdata/entry.yaml
new file mode 100644
index 0000000000..8a1051f06c
--- /dev/null
+++ b/test/devdata/entry.yaml
@@ -0,0 +1,106 @@
+title: table zt_entry
+desc: "应用"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "名称"
+ range: 1-10000
+ prefix: "这是应用名称"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: account
+ note: "账号"
+ range: admin
+ prefix: "account"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: code
+ note: "代号"
+ range: 1-10000
+ prefix: "code"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: key
+ note: "密钥"
+ range: 792b9b972157d2d8531b43e04c0af021
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: freePasswd
+ note: "免密登录"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: ip
+ note: "IP"
+ range: "*"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: desc
+ note: "描述"
+ range: 1-10000
+ prefix: "这是应用描述"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: createdBy
+ note: "创建者"
+ range: "admin"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: createdDate
+ note: "创建日期"
+ range: "(-1M)-(+1w):60"
+ type: timestamp
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: calledTime
+ note: "调用时间戳"
+ range: "0"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: editedBy
+ note: "编辑者"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: editedDate
+ note: "编辑日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/execution.yaml b/test/devdata/execution.yaml
new file mode 100644
index 0000000000..18f757fccf
--- /dev/null
+++ b/test/devdata/execution.yaml
@@ -0,0 +1,85 @@
+title: table zt_execution
+author: Zhu Jinyong
+version: "1.0"
+fields:
+ - field: id
+ range: 20001-50000
+ - field: name
+ note: "名称"
+ fields:
+ - field: name1
+ range: 迭代{9000},阶段{5000},看板{5000}
+ - field: name2
+ range: 1-100000
+ - field: project
+ range: 1001-20000
+ - field: model
+ range: []
+ - field: type
+ range: sprint{9000},stage{5000},kanban{5000}
+ - field: budget
+ range: 800000-1:100
+ - field: status
+ range: wait,doing
+ - field: percent
+ range: 0{30},10{30},0{30}
+ - field: milestone
+ range: 0{30},1{10},0{10},1{10},0{30}
+ - field: auth
+ range: "extend"
+ - field: desc
+ range: 1-100000
+ prefix: "迭代描述"
+ - field: begin
+ range: "(-2M)-(+M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: end
+ range: "(+1w)-(+2M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: realBegan
+ range: "(-2M)-(+M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: realEnd
+ range: "(+1w)-(+2M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: grade
+ range: 1
+ - field: parent
+ range: 1001-10000,10001-15000,15001-20000
+ - field: path
+ fields:
+ - field: path1
+ prefix: ","
+ range: 1001-20000
+ - field: path2
+ prefix: ","
+ range: 20001-50000
+ postfix: ","
+ - field: acl
+ range: open{4},private{4}
+ - field: openedVersion
+ range: "16.5"
+ - field: whitelist
+ froms:
+ - from: common.user.v1.yaml
+ use: empty{8}
+ - from: common.user.v1.yaml
+ use: empty{8}
+ prefix: ","
+ - from: common.user.v1.yaml
+ use: one{8}
+ prefix: ","
+ - from: common.user.v1.yaml
+ use: two{8}
+ prefix: ","
+ - from: common.user.v1.yaml
+ use: three{8}
+ prefix: ","
diff --git a/test/devdata/executionson.yaml b/test/devdata/executionson.yaml
new file mode 100644
index 0000000000..3d0a0abf8b
--- /dev/null
+++ b/test/devdata/executionson.yaml
@@ -0,0 +1,86 @@
+title: table zt_execution
+author: Zhu Jinyong
+version: "1.0"
+fields:
+ - field: id
+ range: 701-730
+ - field: name
+ note: "名称"
+ fields:
+ - field: name1
+ range: 子阶段
+ - field: name2
+ range: 1-10000
+ - field: project
+ range: 41-70
+ - field: model
+ range: []
+ - field: type
+ range: stage
+ - field: budget
+ range: 700000-1:100
+ - field: status
+ range: wait,doing
+ - field: percent
+ range: 0
+ - field: auth
+ range: "extend"
+ - field: desc
+ range: 1-10000
+ prefix: "迭代描述"
+ - field: grade
+ range: 2
+ - field: parent
+ range: 131-160
+ - field: path
+ fields:
+ - field: path1
+ prefix: ","
+ range: 41-70
+ - field: path2
+ prefix: ","
+ postfix: ","
+ range: 131-160
+ - field: path6
+ range: 701-730
+ postfix: ","
+ - field: acl
+ range: open{4},private{4}
+ - field: PO
+ range: admin
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: PM
+ range: admin
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: QD
+ range: admin
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: RD
+ range: admin
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: openedVersion
+ range: "16.5"
+ - field: whitelist
+ froms:
+ - from: common.user.v1.yaml
+ use: empty{8}
+ - from: common.user.v1.yaml
+ use: empty{8}
+ prefix: ","
+ - from: common.user.v1.yaml
+ use: one{8}
+ prefix: ","
+ - from: common.user.v1.yaml
+ use: two{8}
+ prefix: ","
+ - from: common.user.v1.yaml
+ use: three{8}
+ prefix: ","
diff --git a/test/devdata/executionstory.yaml b/test/devdata/executionstory.yaml
new file mode 100644
index 0000000000..a4cc474cba
--- /dev/null
+++ b/test/devdata/executionstory.yaml
@@ -0,0 +1,40 @@
+title: table zt_projectstory
+desc: "项目需求关系"
+author: automated export
+version: "1.0"
+fields:
+ - field: project
+ note: "项目ID"
+ range: 20001-50000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: product
+ note: "产品ID"
+ range: 1-1000{2}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: story
+ note: "需求ID"
+ range: 1-50000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: version
+ note: "版本"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 1,2
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/exefather.yaml b/test/devdata/exefather.yaml
new file mode 100644
index 0000000000..0d05e4c5da
--- /dev/null
+++ b/test/devdata/exefather.yaml
@@ -0,0 +1,52 @@
+title: table zt_execution
+author: Zhu Jinyong
+version: "1.0"
+fields:
+ - field: name
+ note: "名称"
+ fields:
+ - field: name1
+ range: 父阶段
+ - field: name2
+ range: 1-10000
+ - field: project
+ range: 41-70
+ - field: model
+ range: []
+ - field: type
+ range: stage
+ - field: status
+ range: wait,doing
+ - field: percent
+ range: 0
+ - field: auth
+ range:
+ - field: desc
+ range: 1-10000
+ prefix: "迭代描述"
+ - field: grade
+ range: 1
+ - field: parent
+ range: -1
+ - field: path
+ prefix: ","
+ postfix: ","
+ range: 701-730
+ - field: acl
+ range: open{4},private{4}
+ - field: whitelist
+ froms:
+ - from: common.user.v1.yaml
+ use: empty{8}
+ - from: common.user.v1.yaml
+ use: empty{8}
+ prefix: ","
+ - from: common.user.v1.yaml
+ use: one{8}
+ prefix: ","
+ - from: common.user.v1.yaml
+ use: two{8}
+ prefix: ","
+ - from: common.user.v1.yaml
+ use: three{8}
+ prefix: ","
diff --git a/test/devdata/expect.yaml b/test/devdata/expect.yaml
new file mode 100644
index 0000000000..b9d2d95621
--- /dev/null
+++ b/test/devdata/expect.yaml
@@ -0,0 +1,25 @@
+title: table zt_expect
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ range: 1-1000
+ - field: userID
+ range: 32-301
+ - field: project
+ range: 1001-20000{3}
+ - field: expect
+ range: 1-1000
+ prefix: "期望内容"
+ - field: progress
+ range: 1-1000
+ prefix: "达成进展"
+ - field: createdBy
+ range: admin
+ - field: createdDate
+ range: "(M)-(w):60s"
+ type: timestamp
+ format: "YYYY-MM-DD"
+ - field: deleted
+ range: 0
diff --git a/test/devdata/extension.yaml b/test/devdata/extension.yaml
new file mode 100644
index 0000000000..7a77875917
--- /dev/null
+++ b/test/devdata/extension.yaml
@@ -0,0 +1,109 @@
+title: table zt_extension
+desc: "插件"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "插件名称"
+ range: 1-10000
+ prefix: "这是插件名称"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: code
+ note: "代号"
+ range: 1-10000
+ prefix: "code"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: version
+ note: "版本号"
+ range: 1-3
+ prefix: "version"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: author
+ note: "作者"
+ range: 1-10000
+ prefix: "author"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: desc
+ note: "描述"
+ range: 1-10000
+ prefix: "这是插件描述"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: license
+ note: "授权"
+ range: LGPL
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "类型"
+ range: extension
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: site
+ note: "官网"
+ range: zentao
+ prefix: "http://"
+ postfix: ".net"
+ loop: 0
+ format: ""
+ - field: zentaoCompatible
+ note: "适用版本"
+ range: all
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: installedTime
+ note: "安装时间"
+ range: "(M)-(w)"
+ type: timestamp
+ postfix: ""
+ format: "YY/MM/DD"
+ - field: depends
+ note: "依赖"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: dirs
+ note: "安装目录"
+ range: []
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: files
+ note: "安装文件"
+ range: 1-10000
+ prefix: "json格式文件内容"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: status
+ note: "安装状态"
+ range: installed,deactivated
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/feedback.yaml b/test/devdata/feedback.yaml
new file mode 100644
index 0000000000..66cefc5864
--- /dev/null
+++ b/test/devdata/feedback.yaml
@@ -0,0 +1,209 @@
+title: table zt_feedback
+desc: "模块"
+author: zongjun.lan
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-1000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: product
+ note: "所属产品"
+ range: 1-100{4}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: module
+ note: "所属模块"
+ range: 4521-4820{1}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: title
+ note: "标题"
+ range: 1-10000
+ prefix: "反馈标题"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "反馈类型"
+ range: story,task,bug,todo,advice,issue,risk,opportunity
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: solution
+ note: "处理方案"
+ range: tobug,tostory,touserstory,totask,totodo
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: desc
+ note: "描述"
+ range: 1-10000
+ prefix: "这是反馈描述"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: status
+ note: "状态"
+ range: noreview,clarify,wait,commenting,replied,asked,closed
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: subStatus
+ note: "子状态"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: public
+ note: "公开"
+ range: 0,1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: notify
+ note: "通知"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: notifyEmail
+ note: "通知邮箱"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: likes
+ note: "点赞人"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: result
+ note: "转化结果"
+ range: 1-8
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: faq
+ note: "FAQ"
+ range: 1-8
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: openedBy
+ note: "反馈创建人"
+ range: admin
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: openedDate
+ range: "(-1M)-(+1w):-1D"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: reviewedBy
+ note: "由谁评审"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: reviewedDate
+ note: "评审时间"
+ range: "-:300"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: processedBy
+ note: "由谁处理"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: processedDate
+ note: "处理时间"
+ range: "-:400"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: closedBy
+ note: "由谁关闭"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedDate
+ note: "关闭时间"
+ range: "-:400"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: closedReason
+ note: "关闭原因"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: editedBy
+ note: "最后处理人"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: editedDate
+ note: "最后修改时间"
+ range: "-:400"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: assignedTo
+ note: "指派给"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: assignedDate
+ note: "指派时间"
+ range: "-:300"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: feedbackBy
+ note: "反馈者"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: mailto
+ note: "抄送给"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/feedbackmodule.yaml b/test/devdata/feedbackmodule.yaml
new file mode 100644
index 0000000000..aa138815db
--- /dev/null
+++ b/test/devdata/feedbackmodule.yaml
@@ -0,0 +1,79 @@
+title: table zt_module
+desc: "模块"
+author: zongjun.lan
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 4521-4620
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: root
+ note: "根目录"
+ range: 1-100
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: branch
+ note: "分支"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "模块名称"
+ range: 1-10000
+ prefix: "feedback模块"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父ID"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: path
+ note: "ID路径"
+ fields:
+ - field: path1
+ range: 4521-4620
+ prefix: ","
+ postfix: ","
+ - field: path2
+ range: []
+ postfix: ""
+ format: ""
+ - field: grade
+ note: "等级"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 10-100:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "对象类型"
+ range: feedback
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/feedbackmoduleson.yaml b/test/devdata/feedbackmoduleson.yaml
new file mode 100644
index 0000000000..681b458972
--- /dev/null
+++ b/test/devdata/feedbackmoduleson.yaml
@@ -0,0 +1,79 @@
+title: table zt_module
+desc: "模块"
+author: zongjun.lan
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 4621-4820
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: root
+ note: "根目录"
+ range: 1-100{2}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: branch
+ note: "分支"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "模块名称"
+ range: 1-10000
+ prefix: "feedback子模块"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父ID"
+ range: 4521-4620{2}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: path
+ note: "ID路径"
+ fields:
+ - field: path1
+ range: 4521-4620{2}
+ prefix: ","
+ postfix: ","
+ - field: path2
+ range: 4621-4820
+ postfix: ","
+ format: ""
+ - field: grade
+ note: "等级"
+ range: 2
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 10-100:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "对象类型"
+ range: feedback
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/file.yaml b/test/devdata/file.yaml
new file mode 100644
index 0000000000..4789aa56de
--- /dev/null
+++ b/test/devdata/file.yaml
@@ -0,0 +1,87 @@
+title: table zt_file
+desc: "文件上传记录"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ range: "1-10000"
+ note: "ID"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: pathname
+ note: "路径名称"
+ from: common.file.v1.yaml
+ use: pathname
+ loop: 0
+ format: ""
+ - field: title
+ note: "文件标题"
+ from: common.file.v1.yaml
+ use: title
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: extension
+ note: "文件后缀"
+ range: "txt,doc,docx,dot,wps,wri,pdf,ppt,pptx,xls,xlsx,ett,xlt,xlsm,csv,jpg,jpeg,png,psd,gif,ico,bmp,swf,avi,rmvb,rm,mp3,mp4,3gp,flv,mov,movie,rar,zip,bz,bz2,tar,gz,mpp,rp,pdm,vsdx,vsd,sql"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: size
+ note: "文件大小"
+ range: "1000-40000:R"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: objectType
+ note: "对象类型"
+ range: task,bug,story,testcase,traincourse,traincontents
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: objectID
+ note: "对象ID"
+ range: "1-10000"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: addedBy
+ range: admin
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: addedDate
+ note: "添加时间"
+ range: "(M)-(w)"
+ type: timestamp
+ postfix: ""
+ format: "YY/MM/DD"
+ - field: downloads
+ note: "下载次数"
+ range: "0-100"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: extra
+ note: "备注"
+ range: "0"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: "0"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/history.yaml b/test/devdata/history.yaml
new file mode 100644
index 0000000000..e6dd41e176
--- /dev/null
+++ b/test/devdata/history.yaml
@@ -0,0 +1,47 @@
+title: table zt_history
+desc: "操作历史"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-500000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: action
+ note: "关联日志"
+ range: 1-500000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: field
+ note: "字段"
+ range: "resolution,resolvedBuild,resolvedDate,status"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: old
+ note: "旧值"
+ range: [1,2,2020-01-01,doing]
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: new
+ note: "新值"
+ range: [2,3,2020-01-17,done]
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: diff
+ note: "不同"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/holiday.yaml b/test/devdata/holiday.yaml
new file mode 100644
index 0000000000..3367030f61
--- /dev/null
+++ b/test/devdata/holiday.yaml
@@ -0,0 +1,56 @@
+title: table zt_holiday
+desc: "节日假期"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "名称"
+ range: 1-10000
+ prefix: "这是一个节假日"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "节假日类型"
+ range: holiday,working
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: desc
+ note: "描述"
+ range: 1-10000
+ prefix: "这个是节假日的描述"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: year
+ note: "年份"
+ range: 2022
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: begin
+ note: "开始日期"
+ range: "(-1M)-(+1w):1D"
+ type: timestamp
+ format: "YYYY-MM-DD"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ - field: end
+ note: "结束日期"
+ range: "(1M)-(1w):1D"
+ type: timestamp
+ format: "YYYY-MM-DD"
+ prefix: ""
+ postfix: ""
+ loop: 0
diff --git a/test/devdata/host.yaml b/test/devdata/host.yaml
new file mode 100644
index 0000000000..bd0eb33f1c
--- /dev/null
+++ b/test/devdata/host.yaml
@@ -0,0 +1,34 @@
+title: zt_host
+author: Zeng gang
+version: "1.0"
+fields:
+ - field: id
+ range: 1
+ - field: assetID
+ range: 1
+ - field: hardwareType
+ range: server
+ - field: hostType
+ range: virtual
+ - field: unit
+ range: GB
+ - field: privateIP
+ range: 192.168.1.215
+ - field: address
+ range: 192.168.1.215
+ - field: osName
+ range: linux
+ - field: status
+ range: online
+ - field: agentPort
+ range: 8086
+ - field: instanceNum
+ range: 1
+ - field: pri
+ range: 100
+ - field: tags
+ range: vm
+ - field: provider
+ range: native
+ - field: bridgeID
+ range: br0
diff --git a/test/devdata/job.yaml b/test/devdata/job.yaml
new file mode 100644
index 0000000000..f803659bda
--- /dev/null
+++ b/test/devdata/job.yaml
@@ -0,0 +1,160 @@
+title: table zt_job
+desc: "构建任务"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "名称"
+ range: 1-10000
+ prefix: "这是一个Job"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: repo
+ note: "代码库"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: product
+ note: "关联产品"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: frame
+ note: "工具/框架"
+ range: sonarqube,junit,testng,phpunit,pytest,jtest,cppunit,gtest,qtest
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: engine
+ note: "引擎"
+ range: jenkins,gitlab
+ - field: server
+ note: "服务器ID"
+ range: 3,1
+ - field: pipeline
+ note: "流水线"
+ range: dave,[{"project":"1569","reference":"master"}]
+ - field: triggerType
+ note: "触发方式"
+ range: tag,commit,schedule
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: sonarqubeServer
+ note: "Sonarqube服务器"
+ range: 2,0{8}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: projectKey
+ note: "Sonarqube项目"
+ range: zentaopms
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: svnDir
+ note: "SVN监控路径"
+ range: caselib,effort,git,mail,output
+ prefix: "/module/"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: atDay
+ note: "自定义日期"
+ range: 0-6
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: atTime
+ note: "执行时间"
+ range: "22:05"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: customParam
+ note: "自定义构建参数"
+ range: ''
+ prefix: "["
+ postfix: "]"
+ loop: 0
+ format: ""
+ - field: comment
+ note: "匹配关键字"
+ range: a-z
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: createdBy
+ note: "创建者"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: createdDate
+ note: "创建日期"
+ range: "(M)-(w)"
+ type: timestamp
+ postfix: ""
+ format: "YY/MM/DD"
+ - field: editedBy
+ note: "编辑者"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: editedDate
+ note: "编辑日期"
+ range: "(M)-(w)"
+ type: timestamp
+ postfix: ""
+ format: "YY/MM/DD"
+ - field: lastExec
+ note: "最后执行时间"
+ range: "(M)-(w)"
+ type: timestamp
+ postfix: ""
+ format: "YY/MM/DD"
+ - field: lastStatus
+ note: "最后执行状态"
+ range: "a-z"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: lastTag
+ note: "最后执行标签"
+ range: "a-z"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/kanban.yaml b/test/devdata/kanban.yaml
new file mode 100644
index 0000000000..0df05382ee
--- /dev/null
+++ b/test/devdata/kanban.yaml
@@ -0,0 +1,81 @@
+title: table zt_kanban
+desc: "看板表"
+author: automated export
+version: "1.0"
+fields:
+ - field: space
+ range: 1-50{2}
+ - field: name
+ fields:
+ - field: name1
+ range: 通用看板
+ - field: name2
+ range: 1-10000
+ - field: owner
+ fields:
+ - field: owner1
+ range: po{10},user{10},test{10},pm{10},po{10}
+ - field: owner2
+ range: 15-100{2},3-100{2},1-100{2},1-100{2},1-100{2}
+ - field: team
+ fields:
+ - field: team1
+ prefix: ","
+ range: user{10},test{10},pm{10},po{10},po{10}
+ - field: team2
+ range: 3-100{2},1-100{2},1-100{2},1-100{2},35-100{2}
+ postfix: ","
+ - field: team3
+ range: po{10},pm{10},test{10},user[10],user{10}
+ - field: team4
+ range: 15-100{2},15-100{2},15-100{2},15-100{2},35-100{2}
+ postfix: ","
+ - field: desc
+ range: "看板详情"
+ - field: acl
+ range: extend,open
+ - field: whitelist
+ note: "白名单"
+ fields:
+ - field: whitelist1
+ prefix: ","
+ range: user{10},test{10},pm{10},po{10},po{10}
+ - field: whitelist2
+ range: 3-100{2},1-100{2},1-100{2},1-100{2},35-100{2}
+ postfix: ","
+ - field: whitelist3
+ range: po{10},pm{10},test{10},user[10],user{10}
+ - field: whitelist4
+ range: 15-100{2},15-100{2},15-100{2},15-100{2},35-100{2}
+ - field: archived
+ range: "1"
+ - field: performable
+ range: "0"
+ - field: status
+ range: "active"
+ - field: order
+ range: 5-10000:5
+ - field: displayCards
+ range: "0"
+ - field: fluidBoard
+ range: "0"
+ - field: object
+ range: ""
+ prefix: "plans,releases,builds,executions,cards"
+ - field: createdBy
+ range: "admin"
+ - field: createdDate
+ range: "(-1M)-(+M):1D"
+ type: timestamp
+ format: "YYYY-MM-DD"
+ prefix: "\t"
+ - field: lastEditedBy
+ range: ""
+ - field: lastEditedDate
+ range: ""
+ - field: closedBy
+ range: ""
+ - field: closedDate
+ range: ""
+ - field: deleted
+ range: "0"
diff --git a/test/devdata/kanbancard.yaml b/test/devdata/kanbancard.yaml
new file mode 100644
index 0000000000..8b41cb3652
--- /dev/null
+++ b/test/devdata/kanbancard.yaml
@@ -0,0 +1,77 @@
+title: table zt_kanbancard
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: kanban
+ range: 1-100{8}
+ - field: region
+ range: 1-100{8}
+ - field: group
+ range: 1-100{8}
+ - field: fromID
+ range: 0{800},1-70,1-10,101-200,1-20
+ - field: fromType
+ range: []{800},productplan{70},release{10},execution{100},build{20}
+ - field: name
+ fields:
+ - field: name1
+ range: 卡片{800},[]{200}
+ - field: name2
+ range: 1-800,[]{200}
+ - field: status
+ range: doing,doing,done
+ - field: pri
+ range: 3{800},0{200}
+ - field: assignedTo
+ range: admin{800},[]{200}
+ - field: desc
+ range: ""
+ - field: begin
+ range: "(-2M)-(+M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: end
+ range: "(+1w)-(+2M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: estimate
+ range: "0"
+ - field: progress
+ range: 0,50,100
+ - field: color
+ range: "#fff"
+ - field: acl
+ range: "open"
+ - field: whitelist
+ range: ""
+ - field: order
+ range: 1-2
+ - field: archived
+ range: "0"
+ - field: createdBy
+ range: "admin"
+ - field: createdDate
+ range: "(-2M)-(+M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: lastEditedBy
+ range: ""
+ - field: lastEditedDate
+ range: ""
+ - field: archivedBy
+ range: ""
+ - field: archivedDate
+ range: ""
+ - field: assignedBy
+ range: ""
+ - field: assignedDate
+ range: "(-2M)-(+M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: deleted
+ range: "0"
diff --git a/test/devdata/kanbancell.yaml b/test/devdata/kanbancell.yaml
new file mode 100644
index 0000000000..901509dee9
--- /dev/null
+++ b/test/devdata/kanbancell.yaml
@@ -0,0 +1,25 @@
+title: table zt_kanbancell
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: kanban
+ range: 1-100{4}
+ - field: lane
+ range: 1-100{4}
+ - field: column
+ range: 1-400
+ - field: type
+ range: "common"
+ - field: cards
+ fields:
+ - field: card1
+ prefix: ","
+ postfix: ","
+ range: 1-1000:2
+ - field: card2
+ postfix: ","
+ range: 2-1000:2
+ - field: card3
+ postfix: ","
+ range: 801-1000:2
diff --git a/test/devdata/kanbancellproject.yaml b/test/devdata/kanbancellproject.yaml
new file mode 100644
index 0000000000..78265efcd9
--- /dev/null
+++ b/test/devdata/kanbancellproject.yaml
@@ -0,0 +1,17 @@
+title: table zt_kanbancell
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ range: 401-10000
+ - field: kanban
+ range: 161-190{27},251-180{27},341-370{27},431-460{27},521-550{27},611-640{27}
+ - field: lane
+ range: 1-100{4}
+ - field: column
+ range: 401-5260
+ - field: type
+ range: story{11},bug{9},task{7}
+ - field: cards
+ range: ""
diff --git a/test/devdata/kanbancolumn.yaml b/test/devdata/kanbancolumn.yaml
new file mode 100644
index 0000000000..ad5cd87243
--- /dev/null
+++ b/test/devdata/kanbancolumn.yaml
@@ -0,0 +1,26 @@
+title: table zt_kanbancolumn
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: parent
+ range: "0"
+ - field: type
+ range: 1-400
+ prefix: "column"
+ - field: region
+ range: 1-100{4}
+ - field: group
+ range: 1-100{4}
+ - field: name
+ range: 未开始,进行中,已完成,已关闭
+ - field: color
+ range: "#333"
+ - field: limit
+ range: ""
+ - field: order
+ range: 1-4
+ - field: archived
+ range: "0"
+ - field: deleted
+ range: "0"
diff --git a/test/devdata/kanbancolumnproject.yaml b/test/devdata/kanbancolumnproject.yaml
new file mode 100644
index 0000000000..1ae6f3cd0f
--- /dev/null
+++ b/test/devdata/kanbancolumnproject.yaml
@@ -0,0 +1,27 @@
+title: table zt_kanbancolumn
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ range: 401-100000
+ - field: parent
+ range: "0"
+ - field: type
+ range: [backlog,ready,develop,developing,developed,test,testing,tested,verified,released,closed,unconfirmed,confirmed,resolving,fixing,fixed,test,testing,tested,closed,wait,develop,developing,developed,pause,canceled,closed]
+ - field: region
+ range: 101-280{27}
+ - field: group
+ range: "0"
+ - field: name
+ range: Backlog,准备好,开发,进行中,完成,测试,进行中,完成,已验收,已发布,已关闭,待确认,已确认,解决中,进行中,完成,测试,测试中,测试完毕,已关闭,未开始,开发,研发中,研发完毕,已暂停,已取消,已关闭
+ - field: color
+ range: "#333"
+ - field: limit
+ range: ""
+ - field: order
+ range: "0"
+ - field: archived
+ range: "0"
+ - field: deleted
+ range: "0"
diff --git a/test/devdata/kanbangroup.yaml b/test/devdata/kanbangroup.yaml
new file mode 100644
index 0000000000..cfdc8fb0aa
--- /dev/null
+++ b/test/devdata/kanbangroup.yaml
@@ -0,0 +1,11 @@
+title: table zt_kanbangroup
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: kanban
+ range: 1-100
+ - field: region
+ range: 1-100
+ - field: order
+ range: 5-100000:5
diff --git a/test/devdata/kanbangroupproject.yaml b/test/devdata/kanbangroupproject.yaml
new file mode 100644
index 0000000000..76b36b4d45
--- /dev/null
+++ b/test/devdata/kanbangroupproject.yaml
@@ -0,0 +1,13 @@
+title: table zt_kanbangroup
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ range: 101-10000
+ - field: kanban
+ range: 161-190,251-180,341-370,431-460,521-550,611-640
+ - field: region
+ range: 101-10000{3}
+ - field: order
+ range: 1-3
diff --git a/test/devdata/kanbanlane.yaml b/test/devdata/kanbanlane.yaml
new file mode 100644
index 0000000000..52e329671b
--- /dev/null
+++ b/test/devdata/kanbanlane.yaml
@@ -0,0 +1,27 @@
+title: table zt_kanbanlane
+desc: "看板泳道"
+author: automated export
+version: "1.0"
+fields:
+ - field: execution
+ range: "0"
+ - field: type
+ range: "common"
+ - field: region
+ range: 1-100
+ - field: group
+ range: 1-100
+ - field: groupby
+ range: ""
+ - field: extra
+ range: ""
+ - field: name
+ range: "默认泳道"
+ - field: color
+ range: "#7ec5ff"
+ - field: order
+ range: 5-10000:5
+ - field: lastEditedTime
+ range: ""
+ - field: deleted
+ range: "0"
diff --git a/test/devdata/kanbanlaneproject.yaml b/test/devdata/kanbanlaneproject.yaml
new file mode 100644
index 0000000000..14fb861c10
--- /dev/null
+++ b/test/devdata/kanbanlaneproject.yaml
@@ -0,0 +1,27 @@
+title: table zt_kanbanlane
+desc: "看板泳道"
+author: automated export
+version: "1.0"
+fields:
+ - field: execution
+ range: 161-190{3},251-180{3},341-370{3},431-460{3},521-550{3},611-640{3}
+ - field: type
+ range: story,bug,task
+ - field: region
+ range: 101-280{3}
+ - field: group
+ range: 101-640
+ - field: groupby
+ range: ""
+ - field: extra
+ range: ""
+ - field: name
+ range: 研发需求,Bug,任务
+ - field: color
+ range: [#7ec5ff,#333,#2b529c]
+ - field: order
+ range: 5-15:5
+ - field: lastEditedTime
+ range: ""
+ - field: deleted
+ range: "0"
diff --git a/test/devdata/kanbanregion.yaml b/test/devdata/kanbanregion.yaml
new file mode 100644
index 0000000000..47c980e689
--- /dev/null
+++ b/test/devdata/kanbanregion.yaml
@@ -0,0 +1,25 @@
+title: table zt_kanbanregion
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: space
+ range: 1-50{2}
+ - field: kanban
+ range: 1-100
+ - field: name
+ range: "默认区域"
+ - field: order
+ range: 5-10000:5
+ - field: createdDate
+ range: "(-1M)-(+M):1D"
+ type: timestamp
+ format: "YYYY-MM-DD"
+ - field: createdBy
+ range: "admin"
+ - field: lastEditedBy
+ range: ""
+ - field: lastEditedDate
+ range: ""
+ - field: deleted
+ range: "0"
diff --git a/test/devdata/kanbanregionproject.yaml b/test/devdata/kanbanregionproject.yaml
new file mode 100644
index 0000000000..7786857225
--- /dev/null
+++ b/test/devdata/kanbanregionproject.yaml
@@ -0,0 +1,27 @@
+title: table zt_kanbanregion
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ range: 101-10000
+ - field: space
+ range: 0
+ - field: kanban
+ range: 161-190,251-180,341-370,431-460,521-550,611-640
+ - field: name
+ range: "默认区域"
+ - field: order
+ range: 1
+ - field: createdDate
+ range: "(-1M)-(+M):1D"
+ type: timestamp
+ format: "YYYY-MM-DD"
+ - field: createdBy
+ range: "admin"
+ - field: lastEditedBy
+ range: ""
+ - field: lastEditedDate
+ range: ""
+ - field: deleted
+ range: "0"
diff --git a/test/devdata/kanbanspace.yaml b/test/devdata/kanbanspace.yaml
new file mode 100644
index 0000000000..084dff8607
--- /dev/null
+++ b/test/devdata/kanbanspace.yaml
@@ -0,0 +1,96 @@
+title: table zt_kanbanspace
+desc: "看板空间"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ fields:
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: name
+ note: "名字"
+ fields:
+ - field: name1
+ range: 协作空间,私有空间,公共空间
+ - field: name2
+ range: 1-100,1-100,1-100
+ - field: type
+ note: "类型"
+ range: cooperation,private,public
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: team
+ note: "团队"
+ fields:
+ - field: team1
+ prefix: ","
+ range: user{10},test{10},pm{10},po{10},po{10}
+ - field: team2
+ range: 3-100,1-100,1-100,1-100,35-100
+ postfix: ","
+ - field: team3
+ range: po{10},pm{10},test{10},user[10],user{10}
+ - field: team4
+ range: 15-100,15-100,15-100,15-100,35-100
+ postfix: ","
+ - field: whitelist
+ note: "白名单"
+ fields:
+ - field: whitelist1
+ prefix: ","
+ range: user{10},test{10},pm{10},po{10},po{10}
+ - field: whitelist2
+ range: 3-100,1-100,1-100,1-100,35-100
+ postfix: ","
+ - field: whitelist3
+ range: po{10},pm{10},test{10},user[10],user{10}
+ - field: whitelist4
+ range: 15-100,15-100,15-100,15-100,35-100
+ postfix: ","
+ - field: owner
+ note: "所属者"
+ fields:
+ - field: account1
+ range: po{10},user{10},test{10},pm{10},po{10}
+ - field: account2
+ range: 15-100,3-100,1-100,1-100,1-100
+ prefix: ""
+ postfix: ""
+ - field: acl
+ note: "权限"
+ range: open,private
+ prefix: ""
+ postfix: ""
+ - field: createdBy
+ note: "创建者"
+ range: admin
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: createdDate
+ note: "创建日期"
+ range: "(-1M)-(+M):1D"
+ prefix: "\t"
+ type: timestamp
+ format: "YYYY-MM-DD"
+ - field: lastEditedDate
+ note: "最后编辑日期"
+ range: ""
+ prefix: ""
+ postfix: ""
+ tampoop: 0
+ - field: closedDate
+ note: "关闭时间"
+ range: ""
+ prefix: ""
+ postfix: ""
+ - field: deleted
+ note: ""
+ range: 0
+ prefix: ""
+ postfix: ""
diff --git a/test/devdata/libcase.yaml b/test/devdata/libcase.yaml
new file mode 100644
index 0000000000..8dbe31ff3b
--- /dev/null
+++ b/test/devdata/libcase.yaml
@@ -0,0 +1,148 @@
+title: table zt_case
+desc: "测试用例"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 100001-100010
+ - field: product
+ note: "产品ID"
+ range: 0
+ - field: branch
+ note: "分支ID"
+ range: 0
+ - field: execution
+ note: "执行ID"
+ range: 0
+ - field: lib
+ note: "所属库"
+ range: 201
+ - field: module
+ note: "所属模块"
+ range: 0
+ - field: path
+ note: ""
+ range: "0"
+ - field: story
+ note: "相关需求"
+ range: ""
+ - field: storyVersion
+ note: "需求版本"
+ range: "1"
+ - field: title
+ note: "用例标题"
+ range: "1-10"
+ prefix: "用例库用例"
+ - field: precondition
+ note: "前置条件"
+ range: "1-10"
+ prefix: "这是前置条件"
+ - field: keywords
+ note: "关键词"
+ range: "1-10"
+ prefix: "这是关键词"
+ - field: pri
+ note: "优先级"
+ range: 1-4
+ - field: type
+ note: "用例类型"
+ range: feature,performance,config,install,security,interface,other
+ - field: auto
+ note: "是否是自动化测试用例"
+ range: "no"
+ - field: frame
+ note: "自动化测试框架"
+ range: ""
+ - field: stage
+ note: "适用阶段"
+ range: unittest,feature,intergrate,system,smoke,bvt
+ - field: howRun
+ note: "测试方式"
+ range: ""
+ - field: scriptedBy
+ note: "脚本由谁创建"
+ range: ""
+ - field: scriptedDate
+ note: "脚本创建日期"
+ range: "(M)-(w)"
+ type: timestamp
+ postfix: ""
+ format: "YY/MM/DD"
+ - field: scriptStatus
+ note: "脚本状态"
+ range: ""
+ - field: scriptLocation
+ note: "脚本地址"
+ range: ""
+ - field: status
+ note: "用例状态"
+ range: wait,normal,blocked,investigate
+ - field: subStatus
+ note: "子状态"
+ range: ""
+ - field: color
+ note: "标题颜色"
+ from: common.color.v1.yaml
+ use: color
+ - field: frequency
+ note: "使用频率"
+ range: 1-3
+ - field: order
+ note: "排序"
+ range: 1-500:5
+ - field: openedBy
+ note: "由谁创建"
+ range: 1-100
+ prefix: "test"
+ - field: openedDate
+ note: "创建日期"
+ range: "-:600"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: reviewedBy
+ note: "由谁评审"
+ range: admin
+ - field: reviewedDate
+ note: "评审时间"
+ range: "-:300"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: lastEditedBy
+ note: "最后修改者"
+ range: admin
+ - field: lastEditedDate
+ note: "修改日期"
+ range: "-:300"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: version
+ note: "用例版本"
+ range: "1"
+ - field: linkCase
+ note: "相关用例"
+ range: 0
+ - field: fromBug
+ note: "来源Bug"
+ range: 0
+ - field: fromCaseID
+ note: ""
+ range: 0
+ - field: fromCaseVersion
+ note: ""
+ range: 1
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ - field: lastRunner
+ note: "执行人"
+ range: 1-100
+ prefix: "test"
+ - field: lastRunDate
+ note: "执行时间"
+ range: "-:500"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: lastRunResult
+ note: "结果"
+ range: ""
diff --git a/test/devdata/log.yaml b/test/devdata/log.yaml
new file mode 100644
index 0000000000..9ac693b34a
--- /dev/null
+++ b/test/devdata/log.yaml
@@ -0,0 +1,68 @@
+title: table zt_log
+desc: "接口日志"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: objectType
+ note: "对象类型"
+ range: entry,webhook{9}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: objectID
+ note: "对象ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: action
+ note: "操作日志ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: date
+ note: "日期"
+ range: "(-1M)-(1w)"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ prefix: ""
+ postfix: ""
+ - field: url
+ note: "请求地址"
+ range: "qcmmi"
+ prefix: "http://"
+ postfix: ".com"
+ loop: 0
+ format: ""
+ - field: contentType
+ note: "内容类型"
+ range: "application/json"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: data
+ note: "数据"
+ range: a-z
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: result
+ note: "结果"
+ range: a-z
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/meeting.yaml b/test/devdata/meeting.yaml
new file mode 100644
index 0000000000..81db5a6581
--- /dev/null
+++ b/test/devdata/meeting.yaml
@@ -0,0 +1,83 @@
+title: table_meeting
+desc: ""
+version: "1.0"
+fields:
+ - field: id
+ range: 1-1000
+
+ - field: project
+ range: 11-20
+
+ - field: execution
+ range: 101-110
+
+ - field: name
+ range: 1-100
+ prefix: "会议"
+
+ - field: type
+ range: ""
+
+ - field: begin
+ range: "(-1M)-(+1w)"
+ type: timestamp
+ format: "hh:mm:ss"
+
+ - field: end
+ range: "(-1M)-(+1w):1h"
+ type: timestamp
+ format: "hh:mm:ss"
+
+ - field: dept
+ range: 1-10
+
+ - field: mode
+ range: both,online,outline
+
+ - field: host
+ range: admin
+
+ - field: participant
+ range: admin
+ prefix: ","
+ postfix: ","
+
+ - field: date
+ range: "(-1M)-(+1w)"
+ type: timestamp
+ format: "YYYY-MM-DD"
+
+ - field: room
+ range: 1
+
+ - field: minutes
+ range: ""
+
+ - field: minutedBy
+ range: ""
+
+ - field: minutedDate
+ range: ""
+
+ - field: objectType
+ range: story,task,issue,bug
+
+ - field: objectID
+ range: 0
+
+ - field: createdBy
+ range: admin
+
+ - field: createdDate
+ range: "(-1M)-(+1w)"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+
+ - field: editedBy
+ range: ""
+
+ - field: editedDate
+ range: ""
+
+ - field: deleted
+ range: 0
diff --git a/test/devdata/module.yaml b/test/devdata/module.yaml
new file mode 100644
index 0000000000..6dbb21392f
--- /dev/null
+++ b/test/devdata/module.yaml
@@ -0,0 +1,99 @@
+title: table zt_module
+desc: "模块"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: root
+ note: "根目录"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: branch
+ note: "分支"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "模块名称"
+ range: 1-10000
+ prefix: "这是一个模块"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父ID"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: path
+ note: "ID路径"
+ fields:
+ - field: path1
+ range: 1-1000
+ prefix: ","
+ postfix: ","
+ - field: path2
+ range: []
+ postfix: ""
+ - field: grade
+ note: "等级"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 10-100:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "对象类型"
+ range: doc,story,bug
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: owner
+ note: "所有者"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: collector
+ note: "收藏者"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: short
+ note: "模块简称"
+ range: 1-10000
+ prefix: "模块简称"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/morebug.yaml b/test/devdata/morebug.yaml
new file mode 100644
index 0000000000..61b58f2881
--- /dev/null
+++ b/test/devdata/morebug.yaml
@@ -0,0 +1,131 @@
+title: zt_bug
+desc: Bug表
+version: 1.0
+fields:
+ - field: id
+ range: 301-10000
+ - field: project
+ range: 11-20,0{5}
+ - field: product
+ range: 1-10,1{5}
+ - field: branch
+ range: 0
+ - field: module
+ range: 0
+ - field: execution
+ range: 101-110,0{5}
+ - field: plan
+ range: 0
+ - field: story
+ range: 2-40:4,0{5}
+ - field: storyVersion
+ range: 3{10},1{5}
+ - field: task
+ range: 0
+ - field: toTask
+ range: 0
+ - field: toStory
+ range: 0
+ - field: title
+ fields:
+ - field: title1
+ range: 测试单转Bug,SonarQube_Bug
+ - field: title2
+ range: 1-10000
+ - field: keywords
+ range: []
+ - field: severity
+ range: 1-4
+ - field: pri
+ range: 1-4
+ - field: type
+ range: codeerror
+ - field: os
+ range: ""
+ - field: browser
+ range: []
+ - field: hardware
+ range: []
+ - field: found
+ range: []
+ - field: steps
+ range: [【步骤】
【结果】
【期望】
,【步骤】进入成果展示
【结果】乱码
【期望】正常显示
]
+ - field: status
+ range: active
+ - field: subStatus
+ range: []
+ - field: color
+ range: [#3da7f5,#75c941,#2dbdb2,#797ec9,#ffaf38,#ff4e3e]
+ - field: confirmed
+ range: 0
+ - field: activatedCount
+ range: 0
+ - field: mailto
+ range: admin{100},[]{200}
+ - field: openedBy
+ range: admin
+ - field: openedDate
+ range: "(-1M)-(+1w):60"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: openedBuild
+ range: 11-20,11{6}
+ - field: assignedTo
+ range: admin,dev1,test1
+ - field: assignedDate
+ range: "(-1M)-(+1w):60"
+ type: timestamp
+ format: "YYYY-MM-DD"
+ - field: deadline
+ range: "(-1M)-(+1w):-1D"
+ type: timestamp
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: "YYYY-MM-DD"
+ - field: resolvedBy
+ range: ""
+ - field: resolution
+ range: ""
+ - field: resolvedBuild
+ range: ""
+ - field: resolvedDate
+ range: ""
+ prefix: ""
+ postfix: ""
+ - field: closedBy
+ range: ""
+ - field: closedDate
+ range: ""
+ - field: duplicateBug
+ range: 0
+ - field: linkBug
+ range:
+ - field: case
+ range: 2-40:4
+ - field: caseVersion
+ range: 1{10},0{5}
+ - field: result
+ range: 2-40:4
+ - field: repo
+ range: 0
+ - field: entry
+ range:
+ - field: lines
+ range:
+ - field: v1
+ range:
+ - field: v2
+ range:
+ - field: issueKey
+ range: []{10},[17]{5}
+ - field: repoType
+ range:
+ - field: testtask
+ range: 1-10,0{5}
+ - field: lastEditedBy
+ range:
+ - field: lastEditedDate
+ range:
+ - field: deleted
+ range: 0
diff --git a/test/devdata/moretask.yaml b/test/devdata/moretask.yaml
new file mode 100644
index 0000000000..264461b304
--- /dev/null
+++ b/test/devdata/moretask.yaml
@@ -0,0 +1,323 @@
+title: table zt_task
+desc: "任务"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "id"
+ range: 601-1000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父任务"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: project
+ note: "所属项目"
+ range: 11-100{3}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: execution
+ note: "所属执行"
+ range: 101-700{3}
+ - field: module
+ note: "所属模块"
+ range: 21-1820:3
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: story
+ note: "相关需求"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: design
+ note: "相关设计"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: storyVersion
+ note: "需求版本"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: designVersion
+ note: "设计版本"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: fromBug
+ note: "来源Bug"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "任务名称"
+ fields:
+ - field: name1
+ range: "更多任务"
+ - field: name2
+ range: 1-300
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "任务类型"
+ range: design,devel,test,study,discuss,ui,affair,misc
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: pri
+ note: "优先级"
+ range: 1-4
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: estimate
+ note: "最初预计"
+ range: 0-10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: consumed
+ note: "总计消耗"
+ range: 3-12
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: left
+ note: "预计剩余"
+ range: 0-10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deadline
+ note: "截止日期"
+ range: "(-1w)-(-1M):-1D"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ type: timestamp
+ format: "YY/MM/DD"
+ - field: status
+ note: "任务状态"
+ range: wait,doing,done,pause,cancel,closed
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: subStatus
+ note: "子状态"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: color
+ note: "标题颜色"
+ from: common.color.v1.yaml
+ use: color
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: mailto
+ note: "抄送给"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: desc
+ note: "任务描述"
+ range: 1-10000
+ prefix: "这里是任务描述"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: version
+ note: "版本号"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: openedBy
+ note: "由谁创建"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: openedDate
+ note: "创建日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: assignedTo
+ note: "指派给"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: assignedDate
+ note: "指派日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: estStarted
+ note: "预计开始"
+ range: "2022-01-27"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: realStarted
+ note: "实际开始"
+ from: common.date.v1.yaml
+ use: dateB
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: finishedBy
+ note: "由谁完成"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: finishedDate
+ note: "完成日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: finishedList
+ note: "完成者列表"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: canceledBy
+ note: "由谁取消"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: canceledDate
+ note: "取消日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedBy
+ note: "由谁关闭"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedDate
+ note: "关闭日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: realDuration
+ note: "实际持续时长"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: planDuration
+ note: "计划持续时长"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedReason
+ note: "关闭原因"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: lastEditedBy
+ note: "最后修改者"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: lastEditedDate
+ note: "最后修改时间"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: activatedDate
+ note: "重新激活日期"
+ from: common.date.v1.yaml
+ use: dateB
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/mr.yaml b/test/devdata/mr.yaml
new file mode 100644
index 0000000000..4f5c47a1d7
--- /dev/null
+++ b/test/devdata/mr.yaml
@@ -0,0 +1,38 @@
+title: zt_mr
+author: Yidong Wang
+version: "1.0"
+fields:
+ - field: id
+ range: 1
+ - field: hostID
+ range: 1
+ - field: sourceProject
+ range: 42
+ - field: sourceBranch
+ range: branch-08
+ - field: targetProject
+ range: 42
+ - field: targetBranch
+ range: master
+ - field: mriid
+ range: 19
+ - field: title
+ range: Test MR
+ - field: description
+ range: description
+ - field: status
+ range: opened
+ - field: mergeStatus
+ range: can_be_merged
+ - field: repoID
+ range: 1
+ - field: jobID
+ range: 0
+ - field: compileID
+ range: 0
+ - field: createdBy
+ range: admin
+ - field: assignee
+ range: admin
+ - field: deleted
+ range: 0
diff --git a/test/devdata/notify.yaml b/test/devdata/notify.yaml
new file mode 100644
index 0000000000..fca26c1104
--- /dev/null
+++ b/test/devdata/notify.yaml
@@ -0,0 +1,98 @@
+title: table zt_notify
+desc: "消息通知"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: objectType
+ note: "对象类型"
+ range: mail
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: objectID
+ note: "对象ID"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: action
+ note: "操作记录ID"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: toList
+ note: "指派用户"
+ range: admin,user10,test10,dev10,top10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: ccList
+ range: 0
+ note: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: subject
+ note: "主题"
+ range: 1-100
+ prefix: "主题"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: data
+ note: "记录数据"
+ range: 1-100
+ prefix: "用户创建了任务"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: createdBy
+ note: "创建者"
+ range: dev12,test12,admin
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: createdDate
+ note: "创建日期"
+ range: "(1M)-(1w)"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ - field: sendTime
+ note: "发送日期"
+ range: "(1M)-(1w)"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ - field: status
+ note: "状态"
+ range: wait,fail
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: failReason
+ note: "失败原因"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/oauth.yaml b/test/devdata/oauth.yaml
new file mode 100644
index 0000000000..cadcdfd2ac
--- /dev/null
+++ b/test/devdata/oauth.yaml
@@ -0,0 +1,17 @@
+title: table zt_oauth
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: account
+ fields:
+ - field: account1
+ range: user
+ - field: account2
+ range: 3-100
+ - field: openID
+ range: 1-98,root{2}
+ - field: providerType
+ range: gitlab{98},gitea,gogs
+ - field: providerID
+ range: 1
diff --git a/test/devdata/pipeline.yaml b/test/devdata/pipeline.yaml
new file mode 100644
index 0000000000..1e69ac16b3
--- /dev/null
+++ b/test/devdata/pipeline.yaml
@@ -0,0 +1,26 @@
+title: zt_pipeline
+author: Zeng gang
+version: "1.0"
+fields:
+ - field: id
+ range: 1-5
+ - field: type
+ range: gitlab,sonarqube,jenkins,gitea,gogs
+ - field: name
+ range: GitLab服务器,SonarQube服务器,Jenkins服务器,Gitea服务器,Gogs服务器
+ - field: url
+ range: [http://10.0.7.242:9980],[http://10.0.7.242:9990],[http://10.0.7.242:9580],[http://10.0.7.242:9020],[http://10.0.7.242:9021]
+ - field: account
+ range: [],[admin]{2},[]{2}
+ - field: password
+ range: [],[U2h3N0NldHlsc1ozYkVTVjBreXM=],[TThFbEJqcVZsNmJXcTdNSmJZN3U=],[]{2}
+ - field: token
+ range: x88fZokrp5hShia2jyBN,YWRtaW46U2h3N0NldHlsc1ozYkVTVjBreXM=,1196c85ba525a268570df9da627e3a7b2d,c6769e6761a7d719129b2421dcb3112d936e2b1f,9ff43f9d1a369465bcf0781a3785f46bcef782d1
+ - field: private
+ range: 08bcc98f75d7d40053dc80722bdc117b,228b25587479f2fc7570428e8bcbabdc,ec8e41481723685d9106c88be5967c41,a56af13f4c4a6a4ed77f24e59794cf39,4fabcbd31314365506ebc56c0c83c1ec
+ - field: createdBy
+ range: admin
+ - field: createdDate
+ range: [2022-08-01 09:09:37]
+ - field: deleted
+ range: 0
diff --git a/test/devdata/planstory.yaml b/test/devdata/planstory.yaml
new file mode 100644
index 0000000000..c2628a14bd
--- /dev/null
+++ b/test/devdata/planstory.yaml
@@ -0,0 +1,12 @@
+title: table zt_planstory
+desc: "需求计划关联表"
+author: sgm
+version: "1.0"
+fields:
+ - field: plan
+ range: 1-1000{10}
+ - field: story
+ range: 1-10000
+ - field: order
+ note: "排序"
+ range: 5-1000000:5
diff --git a/test/devdata/product.yaml b/test/devdata/product.yaml
new file mode 100644
index 0000000000..882dbbd85f
--- /dev/null
+++ b/test/devdata/product.yaml
@@ -0,0 +1,100 @@
+title: table zt_product
+desc: "产品"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ range: 1-1000
+ - field: program
+ note: "所属项目集"
+ range: 0-10
+ - field: name
+ note: "产品名称"
+ fields:
+ - field: name1
+ range: []{20},已关闭的{20},[]{20},已关闭的{20},[]{20},已关闭的{20},[]{10},已关闭的{10},[]{10},已关闭的{10},[]{10},已关闭的{10},[]{20}
+ - field: name2
+ range: 正常产品{40},多分支产品{40},多平台产品{40},独立测试项目{7},独立产品{53},[@#$%%&&*测试名称长度能有多长并且包含特殊字符的一个长长的字符串()!@#¥%……&*]{10},已删除产品{10}
+ - field: name3
+ range: 1-120,1-7,128-1000
+ - field: code
+ note: "产品代号"
+ fields:
+ - field: code1
+ range: code
+ - field: code2
+ range: 1-300
+ - field: line
+ note: "产品线"
+ range: 0-10
+ - field: type
+ note: "产品类型"
+ range: normal{40},branch{40},platform{40},normal{20},branch{20},platform{20},normal{20}
+ - field: status
+ note: "状态"
+ range: normal{20},closed{20},normal{20},closed{20},normal{20},closed{20},normal{10},closed{10},normal{10},closed{10},normal{10},closed{10},normal{20}
+ - field: subStatus
+ note: "子状态"
+ range: 0
+ - field: desc
+ note: "产品描述"
+ fields:
+ - field: desc1
+ range: []{30},产品描述{20}
+ - field: desc2
+ range:
+
一、禅道项目管理软件是做什么的?
+ 禅道由 青岛易软天创网络科技有限公司开发,国产开源项目管理软件。它集产品管理、项目管理、质量管理、文档管理、组织管理和事务管理于一体,是一款专业的研发项目管理软件,完整覆盖了研发项目管理的核心流程。禅道管理思想注重实效,功能完备丰富,操作简洁高效,界面美观大方,搜索功能强大,统计报表丰富多样,软件架构合理,扩展灵活,有完善的API可以调用。禅道,专注研发项目管理
+
+
我是数字符号23@#$%#^$
+
我是英文dashcuscbrewg
+
{30},
+ 1-20
+ - field: PO
+ note: "产品负责人"
+ fields:
+ - field: po1
+ range: po{120},[]{7}
+ - field: po2
+ range: 1-10{12!},[]{7}
+ - field: QD
+ note: "测试负责人"
+ fields:
+ - field: account1
+ range: test{120},[]{7}
+ - field: account2
+ range: 1-100,1-20,[]{7}
+ - field: RD
+ note: "发布负责人"
+ fields:
+ - field: dev1
+ range: dev{120},[]{7},dev{80}
+ - field: dev2
+ range: 1-120,[]{7},121-200
+ - field: acl
+ note: "访问控制"
+ range: open{10},private{10},open{10},private{10},open{10},private{10},open{10},private{10},open{10},private{10},open{10},private{10},open{5},private{5},open{5},private{5},open{5},private{5},open{5},private{5},open{5},private{5},open{5},private{5},open{20}
+ - field: whitelist
+ note: "分组白名单"
+ range: []{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{20}
+ - field: createdBy
+ note: "创建者"
+ fields:
+ - field: createdBy1
+ range: po
+ - field: createdBy2
+ range: 1-10
+ - field: createdDate
+ note: "创建日期"
+ range: "-:60"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: createdVersion
+ note: "创建版本"
+ range: 18.3
+ - field: order
+ note: "排序"
+ range: 5-10000:5
+ - field: deleted
+ note: "是否删除"
+ range: 0{190},1{10}
diff --git a/test/devdata/productalone.yaml b/test/devdata/productalone.yaml
new file mode 100644
index 0000000000..f6d0240779
--- /dev/null
+++ b/test/devdata/productalone.yaml
@@ -0,0 +1,95 @@
+title: table zt_product
+desc: "产品"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ range: 101-1000
+ - field: program
+ note: "所属项目集"
+ range: 0-10
+ - field: name
+ note: "产品名称"
+ range: 1-100
+ prefix: "产品"
+ - field: code
+ note: "产品代号"
+ fields:
+ - field: code1
+ range: code
+ - field: code2
+ range: 300-1000
+ - field: line
+ note: "产品线"
+ range: 0-10
+ - field: type
+ note: "产品类型"
+ range: normal{40}
+ - field: status
+ note: "状态"
+ range: normal{20}
+ - field: subStatus
+ note: "子状态"
+ range: 0
+ - field: desc
+ note: "产品描述"
+ fields:
+ - field: desc1
+ range: []{30},产品描述{20}
+ - field: desc2
+ range:
+
一、禅道项目管理软件是做什么的?
+ 禅道由 青岛易软天创网络科技有限公司开发,国产开源项目管理软件。它集产品管理、项目管理、质量管理、文档管理、组织管理和事务管理于一体,是一款专业的研发项目管理软件,完整覆盖了研发项目管理的核心流程。禅道管理思想注重实效,功能完备丰富,操作简洁高效,界面美观大方,搜索功能强大,统计报表丰富多样,软件架构合理,扩展灵活,有完善的API可以调用。禅道,专注研发项目管理
+
+
我是数字符号23@#$%#^$
+
我是英文dashcuscbrewg
+
{30},
+ 1-20
+ - field: PO
+ note: "产品负责人"
+ fields:
+ - field: po1
+ range: po{120},[]{7}
+ - field: po2
+ range: 1-10{12!},[]{7}
+ - field: QD
+ note: "测试负责人"
+ fields:
+ - field: account1
+ range: test{120},[]{7}
+ - field: account2
+ range: 1-100,1-20,[]{7}
+ - field: RD
+ note: "发布负责人"
+ fields:
+ - field: dev1
+ range: dev{120},[]{7},dev{80}
+ - field: dev2
+ range: 1-120,[]{7},121-200
+ - field: acl
+ note: "访问控制"
+ range: open{10},private{10},open{10},private{10},open{10},private{10},open{10},private{10},open{10},private{10},open{10},private{10},open{5},private{5},open{5},private{5},open{5},private{5},open{5},private{5},open{5},private{5},open{5},private{5},open{20}
+ - field: whitelist
+ note: "分组白名单"
+ range: []{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{20}
+ - field: createdBy
+ note: "创建者"
+ fields:
+ - field: createdBy1
+ range: po
+ - field: createdBy2
+ range: 1-10
+ - field: createdDate
+ note: "创建日期"
+ range: "-:60"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: createdVersion
+ note: "创建版本"
+ range: 15.6
+ - field: order
+ note: "排序"
+ range: 5-10000:5
+ - field: deleted
+ note: "是否删除"
+ range: 0
diff --git a/test/devdata/productline.yaml b/test/devdata/productline.yaml
new file mode 100644
index 0000000000..05e2c66866
--- /dev/null
+++ b/test/devdata/productline.yaml
@@ -0,0 +1,28 @@
+title: table zt_module
+desc: "产品线"
+author: zt
+version: "1.0"
+fields:
+ - field: root
+ note: "所属项目集"
+ range: 1-1000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "产品线名称"
+ range: 1-10000
+ prefix: "产品线"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ range: line
+ - field: short
+ note: "模块简称"
+ range: 1-10000
+ prefix: "产品线"
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/productplan.yaml b/test/devdata/productplan.yaml
new file mode 100644
index 0000000000..b97b37dfef
--- /dev/null
+++ b/test/devdata/productplan.yaml
@@ -0,0 +1,46 @@
+title: table zt_productplan
+desc: "产品计划"
+author: sgm
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ - field: product
+ note: "所属产品"
+ range: 1-10000
+ - field: branch
+ note: "所属分支"
+ range: 0
+ - field: parent
+ note: "父计划"
+ range: 0
+ - field: title
+ note: "名称"
+ prefix: "计划"
+ range: 1-10000
+ - field: desc
+ note: "描述"
+ range:
+
asdxxxfa阿萨德开机as家世界发卡机发设计费啥登记卡设计费卡加斯加附件阿峰
+
123a阿士大夫姐姐姐经历过反对派呸呸呸史蒂夫接收到付款纪委第三方乐山大佛量减少地方
+
IU风格就叫阿萨德奥斯丁哦IG是DAU发加速度快哦哦阿萨德几年内发,,,奥斯丁,,,切,,,请问加十多年你
+
IUIG是DAU发加速度快哦哦阿萨德几年内发,,,奥斯丁,,,切,,,请问加十多年你
+
IU风格就叫阿萨德奥斯丁哦IG是DAU,,,奥斯丁,,,切,,,请问加十多年你
+
+ - field: begin
+ note: "开始日期"
+ range: "(-10M)-(-7M):7D"
+ type: timestamp
+ format: "YYYY-MM-DD"
+ - field: end
+ note: "结束日期"
+ range: "(-6M)-(+6M):7D"
+ type: timestamp
+ format: "YYYY-MM-DD"
+ - field: order
+ note: "排序"
+ value: "$id * 5"
+ - field: deleted
+ note: "是否删除"
+ range: 0
diff --git a/test/devdata/productsonplan.yaml b/test/devdata/productsonplan.yaml
new file mode 100644
index 0000000000..152e269bed
--- /dev/null
+++ b/test/devdata/productsonplan.yaml
@@ -0,0 +1,48 @@
+title: table zt_productplan
+desc: "产品子计划"
+author: sgm
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 100-10000
+ - field: product
+ note: "所属产品"
+ range: 1-10{3}
+ - field: branch
+ note: "所属分支"
+ range: 41-50
+ - field: parent
+ note: "父计划"
+ range: 1-10
+ - field: title
+ note: "名称"
+ range: [1.0,1.1,长名称好长好长好长好长好长好长好长好长好长好长好长好好长好长好长好长好长好好长好长好长好长好长好好长好长好长好长好长好的名字啊!@ase!!@#%@^!]
+ - field: status
+ note: "状态"
+ range: wait,doing,closed,done
+ - field: desc
+ note: "描述"
+ range:
+
asdxxxfa阿萨德开机as家世界发卡机发设计费啥登记卡设计费卡加斯加附件阿峰
+
123a阿士大夫姐姐姐经历过反对派呸呸呸史蒂夫接收到付款纪委第三方乐山大佛量减少地方
+
IU风格就叫阿萨德奥斯丁哦IG是DAU发加速度快哦哦阿萨德几年内发,,,奥斯丁,,,切,,,请问加十多年你
+
IUIG是DAU发加速度快哦哦阿萨德几年内发,,,奥斯丁,,,切,,,请问加十多年你
+
IU风格就叫阿萨德奥斯丁哦IG是DAU,,,奥斯丁,,,切,,,请问加十多年你
+
+ - field: begin
+ note: "开始日期"
+ range: "(-10M)-(-7M):7D"
+ type: timestamp
+ format: "YYYY-MM-DD"
+ - field: end
+ note: "结束日期"
+ range: "(-6M)-(+6M):7D"
+ type: timestamp
+ format: "YYYY-MM-DD"
+ - field: order
+ note: "排序"
+ value: "$id * 5"
+ - field: deleted
+ note: "是否删除"
+ range: 0{359},1
diff --git a/test/devdata/program.yaml b/test/devdata/program.yaml
new file mode 100644
index 0000000000..ef4fdc2c17
--- /dev/null
+++ b/test/devdata/program.yaml
@@ -0,0 +1,96 @@
+title: program
+author: Zhu Jinyong
+version: "1.0"
+fields:
+ - field: id
+ range: 1-1000
+ - field: project
+ range: 0
+ - field: model
+ range: []
+ - field: name
+ note: "名称"
+ fields:
+ - field: name1
+ range: "项目集"
+ - field: name2
+ range: 1-10000
+ - field: type
+ range: program
+ - field: budget
+ range: 1000000-1:100
+ - field: status
+ range: wait
+ - field: parent
+ range: 0
+ - field: path
+ fields:
+ - field: path1
+ prefix: ","
+ range: 1-1000
+ - field: path2
+ range: []
+ postfix: ","
+ - field: path3
+ range: []
+ postfix: ","
+ - field: grade
+ range: 1
+ - field: code
+ range: 1-10000
+ prefix: "program"
+ - field: begin
+ range: "(-5M)-(+M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: end
+ range: "(+10w)-(+2M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: realBegan
+ range: "(-5M)-(+M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: realEnd
+ range: "(+10w)-(+2M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: desc
+ range: 1-10000
+ prefix: "项目集描述"
+ - field: acl
+ range: open{4},private{4}
+ - field: PO
+ range: 1-10
+ prefix: "po"
+ - field: PM
+ range: 1-10
+ prefix: "pm"
+ - field: QD
+ range: 1-10
+ prefix: "test"
+ - field: RD
+ range: 1-10
+ prefix: "dev"
+ - field: openedVersion
+ range: "18.3"
+ - field: whitelist
+ froms:
+ - from: common.user.v1.yaml
+ use: empty{8}
+ - from: common.user.v1.yaml
+ use: empty{8}
+ prefix: ","
+ - from: common.user.v1.yaml
+ use: one{8}
+ prefix: ","
+ - from: common.user.v1.yaml
+ use: two{8}
+ prefix: ","
+ - from: common.user.v1.yaml
+ use: three{8}
+ prefix: ","
diff --git a/test/devdata/project.yaml b/test/devdata/project.yaml
new file mode 100644
index 0000000000..972d6557c2
--- /dev/null
+++ b/test/devdata/project.yaml
@@ -0,0 +1,95 @@
+title: table zt_project
+author: Zhu Jinyong
+version: "1.0"
+fields:
+ - field: id
+ range: 1001-20000
+ - field: project
+ range: 1-1000
+ - field: model
+ range: scrum{9000},waterfall{5000},kanban{5000}
+ - field: name
+ note: "名称"
+ fields:
+ - field: name1
+ range: '项目'
+ - field: name2
+ range: 1-25000
+ - field: type
+ range: project
+ - field: status
+ range: wait{2},doing{4},suspended,closed
+ - field: lifetime
+ range:
+ - field: budget
+ range: 900000-1:100
+ - field: budgetUnit
+ range: CNY,USD
+ - field: attribute
+ note: "Only stage has attribute"
+ range:
+ - field: percent
+ range: 1-100:R
+ - field: milestone
+ note: "Is it milestone"
+ range: 0
+ - field: output
+ note: "Output document"
+ range:
+ - field: auth
+ note: "Only project has auth"
+ range: "extend"
+ - field: parent
+ range: 1-1000
+ - field: path
+ fields:
+ - field: path1
+ prefix: ","
+ range: 1-1000
+ - field: path2
+ prefix: ","
+ range: 1001-20000
+ postfix: ","
+ - field: grade
+ range: "2"
+ - field: code
+ range: 1-25000
+ prefix: "project"
+ - field: begin
+ range: "(-3M)-(+M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: end
+ range: "(+5w)-(+2M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: realBegan
+ range: "(-3M)-(+M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: realEnd
+ range: "(+5w)-(+2M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: PO
+ range:
+ - field: PM
+ range:
+ - field: QD
+ range:
+ - field: RD
+ range:
+ - field: team
+ range:
+ - field: acl
+ range: open,private,program
+ - field: order
+ range: 5-100000:5
+ - field: openedVersion
+ range: "18.3"
+ - field: deleted
+ range: 0
diff --git a/test/devdata/projectalone.yaml b/test/devdata/projectalone.yaml
new file mode 100644
index 0000000000..840af33daa
--- /dev/null
+++ b/test/devdata/projectalone.yaml
@@ -0,0 +1,87 @@
+title: table zt_project
+author: Zhu Jinyong
+version: "1.0"
+fields:
+ - field: id
+ range: 731-750
+ - field: project
+ range: 0
+ - field: model
+ range: scrum
+ - field: name
+ note: "名称"
+ fields:
+ - field: name1
+ range: '独立项目'
+ - field: name2
+ range: 1-10000
+ - field: type
+ range: project
+ - field: status
+ range: wait
+ - field: lifetime
+ range:
+ - field: budget
+ range: 0
+ - field: budgetUnit
+ range: CNY,USD
+ - field: attribute
+ note: "Only stage has attribute"
+ range:
+ - field: percent
+ range: 1-100
+ - field: milestone
+ note: "Is it milestone"
+ range: 0
+ - field: output
+ note: "Output document"
+ range:
+ - field: auth
+ note: "Only project has auth"
+ range: "extend"
+ - field: parent
+ range: 0
+ - field: path
+ fields:
+ - field: path1
+ prefix: ","
+ range: 731-750
+ - field: path2
+ range: []
+ postfix: ","
+ - field: path3
+ range: []
+ postfix: ","
+ - field: grade
+ range: "1"
+ - field: code
+ range: 101-1000
+ prefix: "project"
+ - field: begin
+ range: "(-2M)-(+M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: end
+ range: "(+1w)-(+2M):1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ postfix: "\t"
+ - field: PO
+ range:
+ - field: PM
+ range:
+ - field: QD
+ range:
+ - field: RD
+ range:
+ - field: team
+ range:
+ - field: acl
+ range: open,private,program
+ - field: order
+ range: 5-10000:5
+ - field: openedVersion
+ range: "16.5"
+ - field: deleted
+ range: 0
diff --git a/test/devdata/projectcase.yaml b/test/devdata/projectcase.yaml
new file mode 100644
index 0000000000..8ca7c5b808
--- /dev/null
+++ b/test/devdata/projectcase.yaml
@@ -0,0 +1,17 @@
+title: table zt_projectcase
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: project
+ range: 1001-19000{4}
+ - field: product
+ range: 1-1000{4}
+ - field: case
+ range: 1-4000
+ - field: count
+ range: 1
+ - field: version
+ range: 1
+ - field: order
+ range: 1
diff --git a/test/devdata/projectproduct.yaml b/test/devdata/projectproduct.yaml
new file mode 100644
index 0000000000..207e310a04
--- /dev/null
+++ b/test/devdata/projectproduct.yaml
@@ -0,0 +1,12 @@
+title: zt_projectproduct
+desc: 项目关联产品表
+version: 1.0
+fields:
+ - field: project
+ range: 1001-20000
+ - field: product
+ range: 1-1000{19}
+ - field: branch
+ range: 0
+ - field: plan
+ range: 1-1000{19}
diff --git a/test/devdata/projectproductalone.yaml b/test/devdata/projectproductalone.yaml
new file mode 100644
index 0000000000..d83a50d517
--- /dev/null
+++ b/test/devdata/projectproductalone.yaml
@@ -0,0 +1,12 @@
+title: zt_projectproduct
+desc: 项目关联产品表
+version: 1.0
+fields:
+ - field: project
+ range: 731-732{5},733-750
+ - field: product
+ range: 101-110,111-112{5},113-120
+ - field: branch
+ range: 0
+ - field: plan
+ range: 0
diff --git a/test/devdata/projectstory.yaml b/test/devdata/projectstory.yaml
new file mode 100644
index 0000000000..7a96955ea8
--- /dev/null
+++ b/test/devdata/projectstory.yaml
@@ -0,0 +1,40 @@
+title: table zt_projectstory
+desc: "项目需求关系"
+author: automated export
+version: "1.0"
+fields:
+ - field: project
+ note: "项目ID"
+ range: 1001-20000{2},1001-13000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: product
+ note: "产品ID"
+ range: 1-10000{5}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: story
+ note: "需求ID"
+ range: 1-50000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: version
+ note: "版本"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 10-100000:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/relation.yaml b/test/devdata/relation.yaml
new file mode 100644
index 0000000000..711dea338c
--- /dev/null
+++ b/test/devdata/relation.yaml
@@ -0,0 +1,82 @@
+title: table zt_relation
+desc: "需求关系"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: product
+ note: "所属产品"
+ range: 7{4},8{4},9{4}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: project
+ note: "所属阶段"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: AType
+ note: "需求类型"
+ range: requirement,story
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: AID
+ note: "自身ID"
+ range: 25-36
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: AVersion
+ note: "自身版本"
+ range: 2
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: relation
+ note: "关联关系"
+ range: subdivideinto,subdividedfrom
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: BType
+ note: "被关联需求类型"
+ range: story,requirement
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: BID
+ note: "被关联需求ID"
+ range: 26,25,28,27,30,29,32,31,34,33,36,35
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: BVersion
+ note: "被关联版本"
+ range: 2
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: extra
+ note: ""
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/release.yaml b/test/devdata/release.yaml
new file mode 100644
index 0000000000..253d646608
--- /dev/null
+++ b/test/devdata/release.yaml
@@ -0,0 +1,59 @@
+title: table zt_release
+desc: ""
+version: "1.0"
+fields:
+ - field: id
+ range: 1-1000
+
+ - field: project
+ range: 1001-20000
+
+ - field: product
+ range: 1-1000
+
+ - field: branch
+ range: 0
+
+ - field: build
+ range: 1-1000
+
+ - field: name
+ fields:
+ - field: name.1
+ range: 发布
+
+ - field: name.2
+ range: 1-1000
+
+ - field: marker
+ range: 0,1
+
+ - field: date
+ range: "(-1M)-(+1w):60"
+ type: timestamp
+ format: "YYYY-MM-DD"
+
+ - field: stories
+ range: ''
+
+ - field: bugs
+ range: ' '
+
+ - field: leftBugs
+ range: ' '
+
+ - field: desc
+ range: 代金券哦放假啊理发店啦发啦打扫房间群殴OAf
sSL卡洛斯等放假啦水电费来看四方达Kjl;阿斯顿发顺丰啊aksdjl
jlaksdfj la阿里肯定是放假啦水电费看来时代峰峻拉水电费拉打扫房间阿拉丁佛爷发
+
+ - field: status
+ range: [normal,terminate]
+
+ - field: subStatus
+ range: ' '
+
+ - field: notify
+ range: PO,PD
+ postfix: ","
+
+ - field: deleted
+ range: 0
diff --git a/test/devdata/repo.yaml b/test/devdata/repo.yaml
new file mode 100644
index 0000000000..4cc989c667
--- /dev/null
+++ b/test/devdata/repo.yaml
@@ -0,0 +1,32 @@
+title: zt_repo
+author: Yidong Wang
+version: "1.0"
+fields:
+ - field: id
+ range: 1
+ - field: product
+ range: 1
+ - field: name
+ range: 723test
+ - field: path
+ range: 42
+ - field: SCM
+ range: Gitlab
+ - field: client
+ range: 1
+ - field: serviceHost
+ range: 1
+ - field: serviceProject
+ range: 42
+ - field: acl
+ range: open
+ - field: desc
+ range: desc
+ - field: extra
+ range: 42
+ - field: preMerge
+ range: 1
+ - field: job
+ range: 1
+ - field: deleted
+ range: 0
diff --git a/test/devdata/score.yaml b/test/devdata/score.yaml
new file mode 100644
index 0000000000..c302df088c
--- /dev/null
+++ b/test/devdata/score.yaml
@@ -0,0 +1,67 @@
+title: table zt_score
+desc: "积分"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: account
+ note: "用户账号"
+ range: admin,test10,dev10,top10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: module
+ note: "模块"
+ range: execution{2},task{3},story{2},bug{2},doc{1}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: method
+ note: "动作"
+ range: create,close,create,close,finish,create,close,create,resolve,create
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: desc
+ note: "描述"
+ range: 1-10000
+ prefix: "这里是分值描述"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: before
+ note: "之前"
+ range: 1-10000:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: score
+ note: "分值"
+ range: 10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: after
+ note: "之后"
+ range: 11-10000:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: time
+ note: "时间"
+ range: "(-1M)-(+1w):60"
+ type: timestamp
+ format: "YYYY-MM-DD"
+ loop: 0
diff --git a/test/devdata/sql/001_company.sql b/test/devdata/sql/001_company.sql
new file mode 100755
index 0000000000..f68b974b90
--- /dev/null
+++ b/test/devdata/sql/001_company.sql
@@ -0,0 +1,3 @@
+INSERT INTO zt_company(`id`, `name`, `admins`, `phone`, `zipcode`, `website`, `guest`, `deleted`)
+ VALUES ('1', '易软天创网络科技有限公司', ',admin,', '15666933065', '100000', 'www.zentao.net', '0', '0'),
+ ('2', '外部公司', ',admin,', '15666933065', '100000', 'www.zentao.net', '0', '0');
diff --git a/test/devdata/sql/002_user.sql b/test/devdata/sql/002_user.sql
new file mode 100755
index 0000000000..8568bec87d
--- /dev/null
+++ b/test/devdata/sql/002_user.sql
@@ -0,0 +1,11 @@
+INSERT INTO zt_user(`id`, `type`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `mobile`, `phone`, `weixin`, `dingding`, `slack`, `whatsapp`, `address`, `zipcode`, `join`, `visits`, `visions`, `ip`, `last`, `fails`, `locked`, `company`, `ranzhi`, `score`, `scoreLevel`, `deleted`)
+ VALUES ('1', 'inside', '1', 'admin', 'a0933c1218a4e745bacdcf572b10eba7', '', 'admin', '', '', '/home/z/tmp/1.png', '1993-05-04', 'f', '10001000@qq.com', 'Skype', '127113918', '', '15887892879', '', '', 'slack', 'whatsApp', '', '', '23/05/04', '1674', 'rnd,lite', '', '1680594087', '1', '0', '1', '', '1645', '', '0'),
+ ('2', 'inside', '1', 'user1', 'a0933c1218a4e745bacdcf572b10eba7', 'dev', '用户1', '', '', '/home/z/user/2.png', '1993-07-03', 'm', '10021002@163.com', 'Skype', '568695851', '', '17944294191', '', '', 'slack', 'whatsApp', '', '', '23/05/04', '2379', 'rnd,lite', '', '1680597687', '2', '0', '1', '', '4933', '', '0'),
+ ('3', 'inside', '1', 'user2', 'a0933c1218a4e745bacdcf572b10eba7', 'dev', '用户2', '', '', '/home/z/tmp/3.png', '1993-09-01', 'f', '10041004@gmail.com', 'Skype', '103846142', '', '17671535000', '', '', 'slack', 'whatsApp', '', '', '23/05/04', '9542', 'rnd,lite', '', '1680601287', '3', '0', '1', '', '2444', '', '0'),
+ ('4', 'inside', '1', 'user3', 'a0933c1218a4e745bacdcf572b10eba7', 'dev', '用户3', '', '', '/home/z/user/4.png', '1993-10-31', 'm', '10061006@qq.com', 'Skype', '432960229', '', '17253676589', '', '', 'slack', 'whatsApp', '', '', '23/05/04', '5277', 'rnd,lite', '', '1680604887', '4', '0', '1', '', '6691', '', '0'),
+ ('5', 'inside', '1', 'user4', 'a0933c1218a4e745bacdcf572b10eba7', 'dev', '用户4', '', '', '/home/z/tmp/5.png', '1993-12-30', 'f', '10081008@163.com', 'Skype', '404555290', '', '193646814', '', '', 'slack', 'whatsApp', '', '', '23/05/04', '5837', 'rnd,lite', '', '1680608487', '5', '0', '1', '', '846', '', '0'),
+ ('6', 'inside', '1', 'user5', 'a0933c1218a4e745bacdcf572b10eba7', 'dev', '用户5', '', '', '/home/z/user/6.png', '1994-02-28', 'm', '10101010@gmail.com', 'Skype', '271502285', '', '19991854512', '', '', 'slack', 'whatsApp', '', '', '23/05/04', '8006', 'rnd,lite', '', '1680612087', '6', '0', '1', '', '6257', '', '0'),
+ ('7', 'inside', '1', 'user6', 'a0933c1218a4e745bacdcf572b10eba7', 'dev', '用户6', '', '', '/home/z/tmp/7.png', '1994-04-29', 'f', '10121012@qq.com', 'Skype', '219255447', '', '19490023087', '', '', 'slack', 'whatsApp', '', '', '23/05/04', '8527', 'rnd,lite', '', '1680615687', '7', '0', '1', '', '2969', '', '0'),
+ ('8', 'inside', '1', 'user7', 'a0933c1218a4e745bacdcf572b10eba7', 'dev', '用户7', '', '', '/home/z/user/8.png', '1994-06-28', 'm', '10141014@163.com', 'Skype', '436606919', '', '17265914399', '', '', 'slack', 'whatsApp', '', '', '23/05/04', '7146', 'rnd,lite', '', '1680619287', '8', '0', '1', '', '5618', '', '0'),
+ ('9', 'inside', '1', 'user8', 'a0933c1218a4e745bacdcf572b10eba7', 'dev', '用户8', '', '', '/home/z/tmp/9.png', '1994-08-27', 'f', '10161016@gmail.com', 'Skype', '940567728', '', '167744731', '', '', 'slack', 'whatsApp', '', '', '23/05/04', '5070', 'rnd,lite', '', '1680622887', '9', '0', '1', '', '5118', '', '0'),
+ ('10', 'inside', '1', 'user9', 'a0933c1218a4e745bacdcf572b10eba7', 'dev', '用户9', '', '', '/home/z/user/10.png', '1994-10-26', 'm', '10181018@qq.com', 'Skype', '483727793', '', '1477016615', '', '', 'slack', 'whatsApp', '', '', '23/05/04', '1547', 'rnd,lite', '', '1680626487', '10', '0', '1', '', '2803', '', '0');
diff --git a/test/devdata/stage.yaml b/test/devdata/stage.yaml
new file mode 100644
index 0000000000..a5caa9bf28
--- /dev/null
+++ b/test/devdata/stage.yaml
@@ -0,0 +1,26 @@
+title: table zt_stage
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ range: 1-6
+ - field: name
+ range: 需求,设计,开发,测试,发布,总结评审
+ - field: percent
+ range: 10{2},50,15,10,5
+ - field: type
+ range: request,design,dev,qa,release,review
+ - field: createdBy
+ range: admin
+ - field: createdDate
+ range: ""
+ prefix: "2018-02-12 12:00:00"
+ postfix: ""
+ - field: editedBy
+ range: admin
+ - field: editedDate
+ range: ""
+ prefix: "2020-02-12 13:50:27"
+ - field: deleted
+ range: "0"
diff --git a/test/devdata/stakeholder.yaml b/test/devdata/stakeholder.yaml
new file mode 100644
index 0000000000..3c524b169b
--- /dev/null
+++ b/test/devdata/stakeholder.yaml
@@ -0,0 +1,12 @@
+title: zt_stakeholder
+desc: 干系人表
+version: 1.0
+fields:
+ - field: objectID
+ range: 11-100
+ - field: objectType
+ range: project
+ - field: key
+ range: 1
+ - field: user
+ range: admin
diff --git a/test/devdata/story.yaml b/test/devdata/story.yaml
new file mode 100644
index 0000000000..ebeb001b25
--- /dev/null
+++ b/test/devdata/story.yaml
@@ -0,0 +1,292 @@
+title: table zt_story
+desc: "需求"
+author: automated export
+version: "1.0"
+fields:
+ - field: parent
+ note: "父需求ID"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: product
+ note: "所属产品"
+ range: 1-1000{50}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: branch
+ note: "分支/平台"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: module
+ note: "所属模块"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: plan
+ note: "所属计划"
+ range: 1-1000{50}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: source
+ note: "需求来源"
+ range: customer,user,po,market,service,operation,support,competitor,partner,dev,tester,bug,forum,other
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: sourceNote
+ note: "来源备注"
+ range: 1-100000
+ prefix: "这里是需求来源备注"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: fromBug
+ note: "来源Bug"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: title
+ note: "需求名称"
+ fields:
+ - field: field1
+ range: 软件需求
+ - field: field2
+ range: 1-1000000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: keywords
+ note: "关键词"
+ range: 1-100000
+ prefix: "关键词"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "需求类型"
+ range: story
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: pri
+ note: "优先级"
+ range: 1-4
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: estimate
+ note: "预计工时"
+ range: 0-20:R
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: status
+ note: "当前状态"
+ range: active
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: subStatus
+ note: "子状态"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: color
+ note: "标题颜色"
+ from: common.color.v1.yaml
+ use: color
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: stage
+ note: "所处阶段"
+ range: [],wait,[],planned,[],projected,[],developing,[],developed,[],testing,[],tested,[],verified,[],released,[],closed
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: stagedBy
+ note: "设置阶段者"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: mailto
+ note: "抄送给"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: openedBy
+ note: "由谁创建"
+ fields:
+ - field: openedBy1
+ range: admin,user,test,dev
+ - field: openedBy2
+ range: [],2-4
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: openedDate
+ note: "创建日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: assignedTo
+ note: "指派给"
+ fields:
+ - field: openedBy1
+ range: admin,user,test,dev
+ - field: openedBy2
+ range: [],2-4
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: assignedDate
+ note: "指派日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: lastEditedBy
+ note: "最后修改者"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: lastEditedDate
+ note: "最后修改日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: reviewedBy
+ note: "评审者"
+ fields:
+ - field: reviewedBy1
+ range: user,test,dev,admin
+ - field: reviewedBy2
+ range: 5-7,[]{10}
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: reviewedDate
+ note: "评审日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedBy
+ note: "关闭者"
+ fields:
+ - field: closedBy1
+ range: test,dev
+ - field: closedBy2
+ range: 1-10,1-10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedDate
+ note: "关闭日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedReason
+ note: "关闭原因"
+ range: done,subdivided,duplicate,postponed,willnotdo,cancel,bydesign
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: toBug
+ note: "转Bug"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: childStories
+ note: "细分需求"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: linkStories
+ note: "相关需求"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: duplicateStory
+ note: "重复需求ID"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: version
+ note: "版本号"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: URChanged
+ note: "用户需求变更"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/storyestimate.yaml b/test/devdata/storyestimate.yaml
new file mode 100644
index 0000000000..1356358350
--- /dev/null
+++ b/test/devdata/storyestimate.yaml
@@ -0,0 +1,44 @@
+title: table zt_storyestimate
+desc: "需求描述"
+author: automated export
+version: "1.0"
+fields:
+ - field: story
+ note: "需求ID"
+ range: 2-1000:2
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: round
+ note: "轮次"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: estimate
+ note: "估计"
+ range: 92-100
+ prefix: "user"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: average
+ note: "平均值"
+ range: 1.5
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: openedBy
+ note: "验收标准"
+ range: admin
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: openedDate
+ range: "(M)-(w)"
+ type: timestamp
+ format: "YYYY-MM-DD"
diff --git a/test/devdata/storymodule.yaml b/test/devdata/storymodule.yaml
new file mode 100644
index 0000000000..8a285289d5
--- /dev/null
+++ b/test/devdata/storymodule.yaml
@@ -0,0 +1,79 @@
+title: table zt_module
+desc: "模块"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1821-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: root
+ note: "根目录"
+ range: 1-100{4}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: branch
+ note: "分支"
+ range: 0{161},1,2,0{2},3,4,0{10000}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "模块名称"
+ range: 1-10000
+ prefix: "产品模块"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父ID"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: path
+ note: "ID路径"
+ fields:
+ - field: path1
+ range: 1821-2620
+ prefix: ","
+ postfix: ","
+ - field: path2
+ range: []
+ postfix: ""
+ format: ""
+ - field: grade
+ note: "等级"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 10-100:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "对象类型"
+ range: story
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/storymoduleson.yaml b/test/devdata/storymoduleson.yaml
new file mode 100644
index 0000000000..a17c8fb846
--- /dev/null
+++ b/test/devdata/storymoduleson.yaml
@@ -0,0 +1,78 @@
+title: table zt_module
+desc: "模块"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 2621-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: root
+ note: "根目录"
+ range: 1-100{2}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: branch
+ note: "分支"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "模块名称"
+ range: 1-10000
+ prefix: "产品子模块"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父ID"
+ range: 1821-2620:4{2}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: path
+ note: "ID路径"
+ fields:
+ - field: path1
+ range: 1821-2620:4{2}
+ prefix: ","
+ postfix: ","
+ - field: path2
+ range: 2621-10000
+ postfix: ","
+ - field: grade
+ note: "等级"
+ range: 2
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 10-100:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "对象类型"
+ range: story
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/storyreview.yaml b/test/devdata/storyreview.yaml
new file mode 100644
index 0000000000..4c600544b1
--- /dev/null
+++ b/test/devdata/storyreview.yaml
@@ -0,0 +1,18 @@
+title: table zt_storyreview
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: story
+ range: 3001-4000
+ - field: version
+ range: "1"
+ - field: reviewer
+ range: admin{50},dev3{50}
+ - field: result
+ range: ""
+ - field: reviewDate
+ range: "(M)-(w)"
+ type: timestamp
+ postfix: ""
+ format: "YY/MM/DD"
diff --git a/test/devdata/storyspec.yaml b/test/devdata/storyspec.yaml
new file mode 100644
index 0000000000..f32f3b8be4
--- /dev/null
+++ b/test/devdata/storyspec.yaml
@@ -0,0 +1,44 @@
+title: table zt_storyspec
+desc: "需求描述"
+author: automated export
+version: "1.0"
+fields:
+ - field: story
+ note: "需求ID"
+ range: 1-450,1-100,1-20
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: version
+ note: "版本"
+ range: 1{450},2{100},3{20}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: title
+ note: "需求标题"
+ fields:
+ - field: field1
+ range: 用户需求版本一{10},软件需求版本一{10},用户需求版本二{10},软件需求版本二{10},用户需求版本三{10},软件需求版本三{10}
+ - field: field2
+ range: 1-100000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: spec
+ note: "需求描述"
+ range: 1-10000
+ prefix: "这是一个软件需求描述"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: verify
+ note: "验收标准"
+ range: 1-10000
+ prefix: "这是一个需求验收"
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/storystage.yaml b/test/devdata/storystage.yaml
new file mode 100644
index 0000000000..9a52e59f62
--- /dev/null
+++ b/test/devdata/storystage.yaml
@@ -0,0 +1,32 @@
+title: table zt_storystage
+desc: "需求阶段"
+author: automated export
+version: "1.0"
+fields:
+ - field: story
+ note: "需求ID"
+ range: 1-50000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: branch
+ note: "分支"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: stage
+ note: "所处阶段"
+ range: wait,planned,projected,developing,developed,testing,tested,verified,released,closed
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: stagedBy
+ note: "设置阶段者"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/suitecase.yaml b/test/devdata/suitecase.yaml
new file mode 100644
index 0000000000..3a471ad5e8
--- /dev/null
+++ b/test/devdata/suitecase.yaml
@@ -0,0 +1,33 @@
+title: table zt_suitecase
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: suite
+ note: ""
+ range: 1-200{2}
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: product
+ note: ""
+ range: 1-100{4}
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: case
+ note: ""
+ range: 1-400
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: version
+ note: ""
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
diff --git a/test/devdata/task.yaml b/test/devdata/task.yaml
new file mode 100644
index 0000000000..12a6abfd3c
--- /dev/null
+++ b/test/devdata/task.yaml
@@ -0,0 +1,330 @@
+title: table zt_task
+desc: "任务"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-500000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父任务"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: project
+ note: "所属项目"
+ range: 1001-20000{20},1001-13000{10}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: execution
+ note: "所属执行"
+ range: 20001-50000{10},20001-40000{10}
+ - field: module
+ note: "所属模块"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: story
+ note: "相关需求"
+ range: 1-50000{10}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: design
+ note: "相关设计"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: storyVersion
+ note: "需求版本"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: designVersion
+ note: "设计版本"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: fromBug
+ note: "来源Bug"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "任务名称"
+ fields:
+ - field: name1
+ range: "开发任务"
+ - field: name2
+ range: 1-1000000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "任务类型"
+ range: design,devel,test,study,discuss,ui,affair,misc
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: pri
+ note: "优先级"
+ range: 1-4
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: estimate
+ note: "最初预计"
+ range: 0-10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: consumed
+ note: "总计消耗"
+ range: 3-12
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: left
+ note: "预计剩余"
+ range: 0-10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deadline
+ note: "截止日期"
+ range: "(+1w)-(-1M):-1D"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ type: timestamp
+ format: "YY/MM/DD"
+ - field: status
+ note: "任务状态"
+ range: wait,doing,done,pause,cancel,closed
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: subStatus
+ note: "子状态"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: color
+ note: "标题颜色"
+ from: common.color.v1.yaml
+ use: color
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: mailto
+ note: "抄送给"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: desc
+ note: "任务描述"
+ range: 1-10000
+ prefix: "这里是任务描述"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: version
+ note: "版本号"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: openedBy
+ note: "由谁创建"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: openedDate
+ note: "创建日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: assignedTo
+ note: "指派给"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: assignedDate
+ note: "指派日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: estStarted
+ note: "预计开始"
+ range: "2022-01-27"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ type: timestamp
+ format: "YY/MM/DD"
+ - field: realStarted
+ note: "实际开始"
+ from: common.date.v1.yaml
+ use: dateB
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: "YY/MM/DD"
+ type: timestamp
+ - field: finishedBy
+ note: "由谁完成"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: finishedDate
+ note: "完成日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: "YY/MM/DD"
+ type: timestamp
+ - field: finishedList
+ note: "完成者列表"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: canceledBy
+ note: "由谁取消"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: canceledDate
+ note: "取消日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: "YY/MM/DD"
+ type: timestamp
+ - field: closedBy
+ note: "由谁关闭"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedDate
+ note: "关闭日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: "YY/MM/DD"
+ type: timestamp
+ - field: realDuration
+ note: "实际持续时长"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: planDuration
+ note: "计划持续时长"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedReason
+ note: "关闭原因"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: lastEditedBy
+ note: "最后修改者"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: lastEditedDate
+ note: "最后修改时间"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: "YY/MM/DD"
+ type: timestamp
+ - field: activatedDate
+ note: "重新激活日期"
+ from: common.date.v1.yaml
+ use: dateB
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: "YY/MM/DD"
+ type: timestamp
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/taskestimate.yaml b/test/devdata/taskestimate.yaml
new file mode 100644
index 0000000000..47dfbf77b5
--- /dev/null
+++ b/test/devdata/taskestimate.yaml
@@ -0,0 +1,48 @@
+title: table zt_taskestimate
+desc: "预计工时"
+author: automated export
+version: "1.0"
+fields:
+ - field: task
+ note: "任务ID"
+ range: 1-100000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: date
+ note: "更新日期"
+ range: "(-1M)-(+1w):60s"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ - field: left
+ note: "总计消耗"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: consumed
+ note: "预计剩余"
+ range: 3-11
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: account
+ note: "操作账号"
+ fields:
+ - field: account1
+ range: admin,user{999},test{1000},dev{1000},pm{1000},po{1000},td{1000},pd{1000},qd{1000},top{1000},others{999},outside
+ - field: account2
+ range: [],1-999,1-1000,1-1000,1-1000,1-1000,1-1000,1-1000,1-1000,1-1000,1-999,[]
+ - field: work
+ note: "工作备注"
+ range: 1-10000
+ prefix: "这里是工作内容"
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/taskmodule.yaml b/test/devdata/taskmodule.yaml
new file mode 100644
index 0000000000..10f8f183a2
--- /dev/null
+++ b/test/devdata/taskmodule.yaml
@@ -0,0 +1,78 @@
+title: table zt_module
+desc: "模块"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 21-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: root
+ note: "根目录"
+ range: 101-700{3}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: branch
+ note: "分支"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "模块名称"
+ range: 1-10000
+ prefix: "模块"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父ID"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: path
+ note: "ID路径"
+ fields:
+ - field: path1
+ range: 21-1820
+ prefix: ","
+ postfix: ","
+ - field: path2
+ range: []
+ postfix: ""
+ - field: grade
+ note: "等级"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 10-100:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "对象类型"
+ range: task
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/taskmoduleson.yaml b/test/devdata/taskmoduleson.yaml
new file mode 100644
index 0000000000..da3d4b7d20
--- /dev/null
+++ b/test/devdata/taskmoduleson.yaml
@@ -0,0 +1,78 @@
+title: table zt_module
+desc: "模块"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 3021-3620
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: root
+ note: "根目录"
+ range: 101-700{1}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: branch
+ note: "分支"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "模块名称"
+ range: 1-10000
+ prefix: "执行子模块"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父ID"
+ range: 21-1820:2
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: path
+ note: "ID路径"
+ fields:
+ - field: path1
+ range: 21-1820:2
+ prefix: ","
+ postfix: ","
+ - field: path2
+ range: 3021-3620
+ postfix: ""
+ - field: grade
+ note: "等级"
+ range: 2
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 10-100:10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "对象类型"
+ range: task
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/taskson.yaml b/test/devdata/taskson.yaml
new file mode 100644
index 0000000000..3b7c794305
--- /dev/null
+++ b/test/devdata/taskson.yaml
@@ -0,0 +1,325 @@
+title: table zt_task
+desc: "任务"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "id"
+ range: 901-910
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: parent
+ note: "父任务"
+ range: 601-603
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: project
+ note: "所属项目"
+ range: 11
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: execution
+ note: "所属执行"
+ range: 101
+ - field: module
+ note: "所属模块"
+ range: 21
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: story
+ note: "相关需求"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: design
+ note: "相关设计"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: storyVersion
+ note: "需求版本"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: designVersion
+ note: "设计版本"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: fromBug
+ note: "来源Bug"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "任务名称"
+ fields:
+ - field: name1
+ range: "子任务"
+ - field: name2
+ range: 1-10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "任务类型"
+ range: design,devel,test,study,discuss,ui,affair,misc
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: pri
+ note: "优先级"
+ range: 1-4
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: estimate
+ note: "最初预计"
+ range: 0-10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: consumed
+ note: "总计消耗"
+ range: 3-12
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: left
+ note: "预计剩余"
+ range: 0-10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deadline
+ note: "截止日期"
+ range: "(-1w)-(-1M):-1D"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ type: timestamp
+ format: "YY/MM/DD"
+ - field: status
+ note: "任务状态"
+ range: wait,doing,done,pause,cancel,closed
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: subStatus
+ note: "子状态"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: color
+ note: "标题颜色"
+ from: common.color.v1.yaml
+ use: color
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: mailto
+ note: "抄送给"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: desc
+ note: "任务描述"
+ range: 1-10000
+ prefix: "这里是任务描述"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: version
+ note: "版本号"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: openedBy
+ note: "由谁创建"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: openedDate
+ note: "创建日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: assignedTo
+ note: "指派给"
+ range: po82,user92
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: assignedDate
+ note: "指派日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: estStarted
+ note: "预计开始"
+ range: "2022-01-27"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: "YY/MM/DD"
+ type: timestamp
+ - field: realStarted
+ note: "实际开始"
+ from: common.date.v1.yaml
+ use: dateB
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: "YY/MM/DD"
+ type: timestamp
+ - field: finishedBy
+ note: "由谁完成"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: finishedDate
+ note: "完成日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: finishedList
+ note: "完成者列表"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: canceledBy
+ note: "由谁取消"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: canceledDate
+ note: "取消日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedBy
+ note: "由谁关闭"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedDate
+ note: "关闭日期"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: realDuration
+ note: "实际持续时长"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: planDuration
+ note: "计划持续时长"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedReason
+ note: "关闭原因"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: lastEditedBy
+ note: "最后修改者"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: lastEditedDate
+ note: "最后修改时间"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: activatedDate
+ note: "重新激活日期"
+ from: common.date.v1.yaml
+ use: dateB
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/taskspec.yaml b/test/devdata/taskspec.yaml
new file mode 100644
index 0000000000..78f28a1bd7
--- /dev/null
+++ b/test/devdata/taskspec.yaml
@@ -0,0 +1,40 @@
+title: table zt_taskspec
+desc: "任务版本"
+author: automated export
+version: "1.0"
+fields:
+ - field: task
+ note: "任务ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: version
+ note: "任务版本"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "任务名称"
+ fields:
+ - field: name1
+ range: 开发任务
+ - field: name2
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: estStarted
+ note: "预计开始"
+ range: "(-1M)-(+1w):-1D"
+ type: timestamp
+ format: "YY/MM/DD"
+ - field: deadline
+ note: "截止时间"
+ range: "(M)-(+2w):-1D"
+ type: timestamp
+ format: "YY/MM/DD"
diff --git a/test/devdata/team.yaml b/test/devdata/team.yaml
new file mode 100644
index 0000000000..d1665ff5eb
--- /dev/null
+++ b/test/devdata/team.yaml
@@ -0,0 +1,101 @@
+title: table zt_team
+desc: "团队"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ fields:
+ range: 1-100000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: root
+ note: "项目/执行ID"
+ range: 1001-50000{5}
+ #range: 4{100},5{100}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "项目类型"
+ range: project{90},execution{200}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: account
+ note: "用户账号"
+ fields:
+ - field: account1
+ range: admin,user{1000},test{1000},pm{1000},po{1000},dev{1000}
+ - field: account2
+ range: [],1-1000,1-1000,1-1000,1-1000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: role
+ note: "角色"
+ range: 研发{1000},测试{1000},项目经理{1000},产品经理{1000}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: limited
+ note: "受限用户"
+ range: yes,no
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: join
+ note: "加盟日"
+ range: Y-m-d
+ prefix: ""
+ type: timestamp
+ format: "YYYY-MM-DD"
+ - field: days
+ note: "可用工作日"
+ range: 1-50
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: hours
+ note: "可用工时/天"
+ range: 1-8
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: estimate
+ note: ""
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: consumed
+ note: ""
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: left
+ note: ""
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/teamtask.yaml b/test/devdata/teamtask.yaml
new file mode 100644
index 0000000000..d22bba8e50
--- /dev/null
+++ b/test/devdata/teamtask.yaml
@@ -0,0 +1,99 @@
+title: table zt_team
+desc: "团队"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 911-1000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: root
+ note: "任务ID"
+ range: 1,901-909
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "项目类型"
+ range: 'task'
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: account
+ note: "用户账号"
+ fields:
+ - field: account1
+ range: po,user,user,po
+ - field: account2
+ range: 82,92,92,82
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: role
+ note: "角色"
+ range: 研发{99},测试{100},项目经理{100},产品经理{5}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: limited
+ note: "受限用户"
+ range: no
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: join
+ note: "加盟日"
+ range: Y-m-d
+ prefix: ""
+ type: timestamp
+ format: "YYYY-MM-DD"
+ - field: days
+ note: "可用工作日"
+ range: 1-50:R
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: hours
+ note: "可用工时/天"
+ range: 1-8:R
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: estimate
+ note: ""
+ range: 1-3
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: consumed
+ note: ""
+ range: 1-3
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: left
+ note: ""
+ range: 1-3
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: order
+ note: "排序"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/testreport.yaml b/test/devdata/testreport.yaml
new file mode 100644
index 0000000000..5e0b3acf77
--- /dev/null
+++ b/test/devdata/testreport.yaml
@@ -0,0 +1,161 @@
+title: table zt_testreport
+desc: "测试报告"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: execution
+ note: "所属执行"
+ range: 20001-21000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: product
+ note: "所属产品"
+ range: 1-1000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: project
+ note: "所属项目"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: tasks
+ note: "测试版本"
+ range: 1-10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: builds
+ note: "版本信息"
+ range: 1-1000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: title
+ note: "标题"
+ fields:
+ - field: title1
+ range: "(M)-(w)"
+ type: timestamp
+ format: "YYYY-MM-DD"
+ - field: title2
+ range: 101-110
+ prefix: "EXECUTION#"
+ - field: title3
+ range: 1-10000
+ prefix: " 迭代"
+ postfix: " 测试报告"
+ - field: begin
+ note: "开始时间"
+ range: "(M)-(w):1D"
+ type: timestamp
+ prefix: ""
+ postfix: "\t"
+ format: "YYYY-MM-DD"
+ - field: end
+ note: "结束时间"
+ range: "(+1w)-(M)"
+ type: timestamp
+ prefix: ""
+ postfix: "\t"
+ format: "YY/MM/DD"
+ - field: owner
+ note: "负责人"
+ range: 1-1000
+ prefix: "test"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: members
+ note: "参与人员"
+ fields:
+ - field: members1
+ range: admin
+ postfix: ","
+ - field: members2
+ range: 1-1000
+ prefix: "dev"
+ - field: stories
+ note: "测试的需求"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: bugs
+ note: "测试的Bug"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: cases
+ note: "用例"
+ fields:
+ - field: cases1
+ range: 1-100:4
+ postfix: ","
+ - field: cases2
+ range: 2-100:4
+ postfix: ","
+ - field: cases3
+ range: 3-100:4
+ postfix: ","
+ - field: cases4
+ range: 4-100:4
+ - field: report
+ note: "总结"
+ range: 1-10000
+ prefix: "这里是报告总结"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: objectType
+ note: "对象类型"
+ range: execution
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: objectID
+ note: "对象ID"
+ range: 20001-21000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: createdBy
+ note: "由谁创建"
+ range: 1-1000
+ prefix: "test"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: createdDate
+ note: "创建日期"
+ range: "(M)-(w):60"
+ type: timestamp
+ prefix: ""
+ postfix: ""
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/testresult.yaml b/test/devdata/testresult.yaml
new file mode 100644
index 0000000000..1489206cc9
--- /dev/null
+++ b/test/devdata/testresult.yaml
@@ -0,0 +1,97 @@
+title: table zt_testresult
+desc: "测试结果"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-70
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: run
+ note: "运行"
+ range: 1-70
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: case
+ note: "用例ID"
+ range: 1-40,411-440
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: version
+ note: "用例版本"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: job
+ note: "工作"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: compile
+ note: "编译"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: caseResult
+ note: "测试结果"
+ range: [pass,fail]{20!},[pass,pass,fail]{15!}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: stepResults
+ note: "步骤结果"
+ range: "php处理"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: lastRunner
+ note: "最后执行人"
+ range: admin
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: date
+ note: "测试时间"
+ range: "(M)-(w):60"
+ type: timestamp
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: duration
+ note: "持续时间"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: xml
+ note: "XMl格式"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deploy
+ note: "部署"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/testrun.yaml b/test/devdata/testrun.yaml
new file mode 100644
index 0000000000..569ea35234
--- /dev/null
+++ b/test/devdata/testrun.yaml
@@ -0,0 +1,73 @@
+title: table zt_testrun
+desc: "测试执行"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: task
+ note: "测试单任务ID"
+ range: 1-10{4},51-60{3}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: case
+ note: "用例ID"
+ range: 1-40,411-440
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: version
+ note: "版本"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: assignedTo
+ note: "指派给"
+ fields:
+ - field: openedBy1
+ range: admin,user,test,dev
+ - field: openedBy2
+ range: [],2-4
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: lastRunner
+ note: "最后执行人"
+ range: []{40},admin{30}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: lastRunDate
+ note: "最后执行时间"
+ range: "(M)-(w):60"
+ type: timestamp
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: "YYYY-MM-DD"
+ - field: lastRunResult
+ note: "最后执行结果"
+ range: [pass,fail]{20!},[pass,pass,fail]{15!}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: status
+ note: "状态"
+ range: normal{40},done{30}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/testsuite.yaml b/test/devdata/testsuite.yaml
new file mode 100644
index 0000000000..2c0f244fd1
--- /dev/null
+++ b/test/devdata/testsuite.yaml
@@ -0,0 +1,76 @@
+title: table zt_testsuite
+desc: "测试套件"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: product
+ note: "所属产品"
+ range: 1-100{2},0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "名称"
+ range: 1-10000
+ prefix: "这是测试套件名称"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: desc
+ note: "描述"
+ range: 1-10000
+ prefix: "这是测试套件的描述"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "类型"
+ range: [public,private]{100},library
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: addedBy
+ note: "由谁创建"
+ fields:
+ - field: addedBy1
+ range: dev{100},user{100},admin
+ - field: addedBy2
+ range: 1-100,1-100,[]
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: addedDate
+ note: "创建日期"
+ range: "(M)-(w)"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: lastEditedBy
+ note: "最后编辑者"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: lastEditedDate
+ note: "最后编辑日期"
+ range: "(M)-(w)"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/testtask.yaml b/test/devdata/testtask.yaml
new file mode 100644
index 0000000000..4bdac43aec
--- /dev/null
+++ b/test/devdata/testtask.yaml
@@ -0,0 +1,130 @@
+title: table zt_testtask
+desc: "测试版本"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-1000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "测试单名称"
+ fields:
+ - field: name1
+ range: 测试单
+ - field: name2
+ range: 1-1000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: product
+ note: "所属产品"
+ range: 1-1000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: project
+ note: "所属项目"
+ range: 1001-2000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: execution
+ note: "所属执行"
+ range: 20001-21000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: build
+ range: 1-1000
+ note: "版本"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: owner
+ note: "负责人"
+ range: 1-1000
+ prefix: "user"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: pri
+ note: "优先级"
+ range: 1-4
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: begin
+ note: "开始日期"
+ range: "(M)-(w):60"
+ type: timestamp
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: "YYYY-MM-DD"
+ - field: end
+ note: "结束日期"
+ range: "(+1w)-(M)"
+ type: timestamp
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: "YYYY-MM-DD"
+ - field: mailto
+ note: "抄送给"
+ range: ""
+ prefix: ","
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: desc
+ note: "描述"
+ range: 1-1000
+ prefix: "这是测试单描述"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: report
+ note: "报告"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: status
+ note: "状态"
+ range: wait,doing,done,blocked
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: auto
+ note: "自动"
+ range: no
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: subStatus
+ note: "子状态"
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/todo.yaml b/test/devdata/todo.yaml
new file mode 100644
index 0000000000..a59a19f943
--- /dev/null
+++ b/test/devdata/todo.yaml
@@ -0,0 +1,156 @@
+title: table zt_todo
+desc: "待办"
+author: ly
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: account
+ note: "用户名"
+ fields:
+ - field: account1
+ range: admin,user{99},test{100},dev{100},pm{100},po{100},td{100},pd{100},qd{100},top{100},others{100}
+ - field: account2
+ range: [],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: date
+ note: "日期"
+ range: "(-1M)-(+1w):-1D"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ type: timestamp
+ format: "YY/MM/DD"
+ - field: begin
+ note: "开始"
+ range: "1000-1059:2"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: end
+ note: "结束"
+ range: "1400-1459:2"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "类型"
+ range: custom,bug,task,story,testtask
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: objectID
+ note: "关联编号"
+ range: 0,1-20,1-20,1-20,1-20
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: pri
+ note: "优先级"
+ range: 1-4
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "待办名称"
+ fields:
+ - field: name1
+ range: 自定义,BUG,任务,需求,测试单
+ - field: name2
+ range: 1-200,1-200,1-200,1-200.1-200
+ prefix: ""
+ postfix: "的待办"
+ loop: 0
+ format: ""
+ - field: desc
+ note: "描述"
+ range: 1-10000
+ prefix: "这是一个待办的描述"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: status
+ note: "状态"
+ range: wait,doing,done,closed
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: private
+ note: "私人事务"
+ range: 1{10},0{10}
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: config
+ note: "配置"
+ range: ""
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: assignedTo
+ note: "指派给"
+ fields:
+ - field: ass1
+ range: admin,user{99},test{100},dev{100},pm{100},po{100},td{100},pd{100},qd{100},top{100},others{100}
+ - field: ass2
+ range: [],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: assignedBy
+ note: "由谁指派"
+ fields:
+ - field: ass1
+ range: admin,user{99},test{100},dev{100},pm{100},po{100},td{100},pd{100},qd{100},top{100},others{100}
+ - field: ass2
+ range: [],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: assignedDate
+ note: "指派日期"
+ range: "(M)-(w):60m"
+ type: timestamp
+ prefix: ""
+ postfix: ""
+ format: "YY-MM-DD hh:mm:ss"
+ - field: finishedBy
+ note: "由谁完成"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: finishedDate
+ range: "20230101"
+ type: timestamp
+ format: "YY/MM/DD"
+ - field: closedBy
+ note: "由谁关闭"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedDate
+ note: "关闭时间"
+ range: "20230101"
+ type: timestamp
+ format: "YY/MM/DD"
diff --git a/test/devdata/todocycle.yaml b/test/devdata/todocycle.yaml
new file mode 100644
index 0000000000..7265f5900c
--- /dev/null
+++ b/test/devdata/todocycle.yaml
@@ -0,0 +1,149 @@
+title: table zt_todo
+desc: "待办"
+author: ly
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 2001-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: account
+ note: "用户名"
+ range: admin
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: date
+ note: "日期"
+ range: "(M)-(w)"
+ type: timestamp
+ prefix: ""
+ postfix: ""
+ format: "YY-MM-DD"
+ - field: begin
+ note: "开始"
+ range: "1000-1059:2"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: end
+ note: "结束"
+ range: "1400-1459:2"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "类型"
+ range: cycle
+ prefix: ""
+ postfix: ""
+ - field: cycle
+ note: "周期"
+ range: 1
+ prefix: ""
+ postfix: ""
+ - field: idvalue
+ note: "关联编号"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: pri
+ note: "优先级"
+ range: 3
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: name
+ note: "待办名称"
+ range: 天周期{2},周周期{2},月周期
+ prefix: ""
+ postfix: "待办"
+ loop: 0
+ format: ""
+ - field: desc
+ note: "描述"
+ range: 1-10000
+ prefix: "这是一个待办的描述"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: status
+ note: "状态"
+ range: wait
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: private
+ note: "私人事务"
+ range: 0
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: config
+ note: "配置"
+ range: ""
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: assignedTo
+ note: "指派给"
+ range: admin
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: assignedBy
+ note: "由谁指派"
+ range: admin
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: assignedDate
+ note: "指派日期"
+ range: "(M)-(w):60m"
+ type: timestamp
+ prefix: ""
+ postfix: ""
+ format: "YY/MM/DD hh:mm:ss"
+ - field: finishedBy
+ note: "由谁完成"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: finishedDate
+ note: "完成时间"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedBy
+ note: "由谁关闭"
+ from: common.user.v1.yaml
+ use: user
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: closedDate
+ note: "关闭时间"
+ from: common.date.v1.yaml
+ use: dateA
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/unitcase.yaml b/test/devdata/unitcase.yaml
new file mode 100644
index 0000000000..92ba59a6ee
--- /dev/null
+++ b/test/devdata/unitcase.yaml
@@ -0,0 +1,141 @@
+title: table zt_case
+desc: "测试用例"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 411-10000
+ - field: product
+ note: "产品ID"
+ range: 1-50{3}
+ - field: branch
+ note: "分支ID"
+ range: 0
+ - field: execution
+ note: "执行ID"
+ range: 0
+ - field: lib
+ note: "所属库"
+ range: 0
+ - field: module
+ note: "所属模块"
+ range: 0
+ - field: path
+ note: ""
+ range: "0"
+ - field: story
+ note: "相关需求"
+ range: "0"
+ - field: storyVersion
+ note: "需求版本"
+ range: "1"
+ - field: title
+ note: "用例标题"
+ range: 登录成功,密码错误,账号过期
+ prefix: "com.ngtesting.autotest.test.TestLogin"
+ - field: precondition
+ note: "前置条件"
+ range: []
+ prefix: ""
+ - field: keywords
+ note: "关键词"
+ range: []
+ prefix: ""
+ - field: pri
+ note: "优先级"
+ range: 1-4
+ - field: type
+ note: "用例类型"
+ range: unit
+ - field: auto
+ note: "是否是自动化测试用例"
+ range: "unit"
+ - field: frame
+ note: "自动化测试框架"
+ range: "junit"
+ - field: stage
+ note: "适用阶段"
+ range: unittest
+ - field: howRun
+ note: "测试方式"
+ range: ""
+ - field: scriptedBy
+ note: "脚本由谁创建"
+ range: ""
+ - field: scriptedDate
+ note: "脚本创建日期"
+ from: common.date.v1.yaml
+ use: dateB
+ - field: scriptStatus
+ note: "脚本状态"
+ range: ""
+ - field: scriptLocation
+ note: "脚本地址"
+ range: ""
+ - field: status
+ note: "用例状态"
+ range: normal
+ - field: subStatus
+ note: "子状态"
+ range: ""
+ - field: color
+ note: "标题颜色"
+ range: ""
+ - field: frequency
+ note: "使用频率"
+ range: 1
+ - field: order
+ note: "排序"
+ range: 0
+ - field: openedBy
+ note: "由谁创建"
+ range: admin
+ prefix: ""
+ - field: openedDate
+ note: "创建日期"
+ range: "-:600"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: reviewedBy
+ note: "由谁评审"
+ range: ""
+ - field: reviewedDate
+ note: "评审时间"
+ range: ""
+ - field: lastEditedBy
+ note: "最后修改者"
+ range: ""
+ - field: lastEditedDate
+ note: "修改日期"
+ range: ""
+ - field: version
+ note: "用例版本"
+ range: "1"
+ - field: linkCase
+ note: "相关用例"
+ range: ""
+ - field: fromBug
+ note: "来源Bug"
+ range: 0
+ - field: fromCaseID
+ note: ""
+ range: 0
+ - field: fromCaseVersion
+ note: ""
+ range: 1
+ - field: deleted
+ note: "是否删除"
+ range: 0
+ - field: lastRunner
+ note: "执行人"
+ range: admin
+ prefix: ""
+ - field: lastRunDate
+ note: "执行时间"
+ range: "-:500"
+ type: timestamp
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: lastRunResult
+ note: "结果"
+ range: pass,pass,fail
diff --git a/test/devdata/user.yaml b/test/devdata/user.yaml
new file mode 100644
index 0000000000..de0a6d47bc
--- /dev/null
+++ b/test/devdata/user.yaml
@@ -0,0 +1,172 @@
+title: table zt_user
+desc: "用户信息"
+author: sgm
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-100000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "内外部人员"
+ range: inside{9999},outside
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: dept
+ note: "所属部门"
+ range: 1-100{10}
+ - field: account
+ note: "用户名"
+ fields:
+ - field: account1
+ range: admin,user{999},test{1000},dev{1000},pm{1000},po{1000},td{1000},pd{1000},qd{1000},top{1000},others{999},outside
+ - field: account2
+ range: [],1-999,1-1000,1-1000,1-1000,1-1000,1-1000,1-1000,1-1000,1-1000,1-999,[]
+ - field: password
+ note: "密码"
+ range: 123Qwe!@#
+ format: md5
+ - field: role
+ note: "职位"
+ range: [],dev{999},qa{1000},dev{1000},pm{1000},po{1000},td{1000},pd{1000},qd{1000},others{1999},outside
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: realname
+ note: "真实姓名"
+ fields:
+ - field: realname1
+ range: admin,用户{999},测试{1000},开发{1000},项目经理{1000},产品经理{1000},研发主管{1000},产品主管{1000},测试主管{1000},高层管理{1000},外用户{999},其他
+ - field: realname2
+ range: [],1-999,1-1000,1-1000,1-1000,1-1000,1-1000,1-1000,1-1000,1-1000,1-999,[]
+ - field: nickname
+ note: "昵称"
+ - field: commiter
+ note: "源代码帐号"
+ range: []
+ - field: avatar
+ note: ""
+ fields:
+ - field: avatar1
+ range: /home/z/tmp/,/home/z/user/
+ - field: avatar2
+ range: 1-10,10-20
+ prefix: ""
+ postfix: ".png"
+ format: ""
+ - field: birthday
+ note: "生日"
+ range: "(-30Y)-(-20Y):60D"
+ type: timestamp
+ format: "YYYY-MM-DD"
+ - field: gender
+ note: "性别"
+ range: f,m
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: email
+ note: "邮箱"
+ fields:
+ - field: email1
+ range: 1000-99999:2
+ - field: email2
+ range: 1000-99999:2
+ - field: email3
+ range: [@qq.com,@163.com,@gmail.com]
+ - field: skype
+ note: "Skype"
+ range: Skype
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: qq
+ note: "QQ"
+ range: QQ
+ fields:
+ - field: qq1
+ range: 100-999:R
+ - field: qq2
+ range: 100-999:R
+ - field: qq3
+ range: 100-999:R
+ - field: mobile
+ note: "手机"
+ - field: phone
+ note: "电话"
+ fields:
+ - field: phone1
+ range: 130-199:R
+ - field: phone2
+ range: 0000-9999:R
+ - field: phone3
+ range: 0000-9999:R
+ - field: weixin
+ note: "微信"
+ - field: dingding
+ note: "钉钉"
+ - field: slack
+ note: "Slack"
+ range: slack
+ - field: whatsapp
+ note: "WhatsApp"
+ range: whatsApp
+ - field: address
+ note: "通讯地址"
+ - field: zipcode
+ note: "邮编"
+ - field: join
+ note: "入职日期"
+ range: "(M)-(w)"
+ type: timestamp
+ postfix: ""
+ format: "YY/MM/DD"
+ - field: visits
+ note: "访问次数"
+ range: 0-10000:R
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: visions
+ note: "版本"
+ range: rnd
+ prefix: ""
+ postfix: ",lite"
+ loop: 0
+ format: ""
+ - field: ip
+ note: "最后IP"
+ format: ""
+ - field: last
+ note: "最后登录"
+ range: "(-1M)-(+1w):60m"
+ type: timestamp
+ - field: fails
+ note: "失败次数"
+ range: 1-10000
+ - field: locked
+ note: "锁定时间"
+ range: 0
+ - field: company
+ note: "公司"
+ range: 1
+ - field: ranzhi
+ note: "ZDOO账号"
+ range: []
+ - field: score
+ note: "积分"
+ range: 1-10000:R
+ - field: scoreLevel
+ note: "积分等级"
+ - field: deleted
+ note: "是否删除"
+ range: 0
diff --git a/test/devdata/usercontact.yaml b/test/devdata/usercontact.yaml
new file mode 100644
index 0000000000..737ab3898e
--- /dev/null
+++ b/test/devdata/usercontact.yaml
@@ -0,0 +1,41 @@
+title: table zt_usercontact
+desc: "用户联系人"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: account
+ note: "用户名"
+ fields:
+ - field: account1
+ range: user,dev,test,admin
+ - field: account2
+ range: 1-20,1-20,1-20,""
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: listName
+ note: "列表名称"
+ range: 1-10000
+ prefix: "联系人列表"
+ postfix: ""
+ format: ""
+ - field: userList
+ note: "用户列表"
+ fields:
+ - field: userList1
+ range: user,dev,test
+ - field: userList2
+ range: 20-30,20-30,20-30
+ postfix: ","
+ - field: userList3
+ range: user,dev,test
+ - field: userList4
+ range: 40-50,40-5040-50
+ format: ""
diff --git a/test/devdata/usergroup.yaml b/test/devdata/usergroup.yaml
new file mode 100644
index 0000000000..044cc6b46a
--- /dev/null
+++ b/test/devdata/usergroup.yaml
@@ -0,0 +1,18 @@
+title: table zt_usergroup
+desc: "用户分组"
+author: Li yuchun
+version: "1.0"
+fields:
+ - field: account
+ note: "用户名"
+ fields:
+ - field: account1
+ range: test{99},dev{100},pm,po{54},td{100},pd{47},qd{7},top{100},others{92}
+ - field: account2
+ range: 2-100,1-100,1,48-100,1-100,1-47,94-100,1-100,2-93
+ - field: group
+ note: "分组名称"
+ range: 1-16
+ - field: project
+ note: "项目ID"
+ range:
diff --git a/test/devdata/userquery.yaml b/test/devdata/userquery.yaml
new file mode 100644
index 0000000000..6610ed69dc
--- /dev/null
+++ b/test/devdata/userquery.yaml
@@ -0,0 +1,52 @@
+title: table zt_userquery
+desc: "用户查询"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: account
+ note: "用户名"
+ range: admin
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: module
+ note: "模块"
+ range: task
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: title
+ note: "名称"
+ range: 1-1000
+ prefix: "这是搜索条件名称"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: form
+ note: "表单字段"
+ range: 'a:60:{s:9:\"fieldname\";s:0:\"\";s:11:\"fieldstatus\";s:0:\"\";s:9:\"fielddesc\";s:0:\"\";s:15:\"fieldassignedTo\";s:0:\"\";s:8:\"fieldpri\";s:1:\"0\";s:14:\"fieldexecution\";s:0:\"\";s:11:\"fieldmodule\";s:4:\"ZERO\";s:13:\"fieldestimate\";s:0:\"\";s:9:\"fieldleft\";s:0:\"\";s:13:\"fieldconsumed\";s:0:\"\";s:9:\"fieldtype\";s:0:\"\";s:12:\"fieldfromBug\";s:0:\"\";s:17:\"fieldclosedReason\";s:0:\"\";s:13:\"fieldopenedBy\";s:0:\"\";s:15:\"fieldfinishedBy\";s:0:\"\";s:13:\"fieldclosedBy\";s:0:\"\";s:13:\"fieldcancelBy\";s:1:\"0\";s:17:\"fieldlastEditedBy\";s:0:\"\";s:11:\"fieldmailto\";s:0:\"\";s:17:\"fieldfinishedList\";s:0:\"\";s:15:\"fieldopenedDate\";s:0:\"\";s:13:\"fielddeadline\";s:0:\"\";s:15:\"fieldestStarted\";s:0:\"\";s:16:\"fieldrealStarted\";s:0:\"\";s:17:\"fieldassignedDate\";s:0:\"\";s:17:\"fieldfinishedDate\";s:0:\"\";s:15:\"fieldclosedDate\";s:0:\"\";s:17:\"fieldcanceledDate\";s:0:\"\";s:19:\"fieldlastEditedDate\";s:0:\"\";s:7:\"fieldid\";s:0:\"\";s:15:\"fieldcanceledBy\";s:0:\"\";s:6:\"andOr1\";s:3:\"AND\";s:6:\"field1\";s:4:\"name\";s:9:\"operator1\";s:7:\"include\";s:6:\"value1\";s:2:\"aa\";s:6:\"andOr2\";s:3:\"and\";s:6:\"field2\";s:2:\"id\";s:9:\"operator2\";s:1:\"=\";s:6:\"value2\";s:0:\"\";s:6:\"andOr3\";s:3:\"and\";s:6:\"field3\";s:6:\"status\";s:9:\"operator3\";s:1:\"=\";s:6:\"value3\";s:0:\"\";s:10:\"groupAndOr\";s:3:\"and\";s:6:\"andOr4\";s:3:\"AND\";s:6:\"field4\";s:4:\"desc\";s:9:\"operator4\";s:7:\"include\";s:6:\"value4\";s:0:\"\";s:6:\"andOr5\";s:3:\"and\";s:6:\"field5\";s:10:\"assignedTo\";s:9:\"operator5\";s:1:\"=\";s:6:\"value5\";s:0:\"\";s:6:\"andOr6\";s:3:\"and\";s:6:\"field6\";s:3:\"pri\";s:9:\"operator6\";s:1:\"=\";s:6:\"value6\";s:1:\"0\";s:6:\"module\";s:4:\"task\";s:9:\"actionURL\";s:77:\"/index.php?m=execution&f=task&executionID=101&status=bySearch¶m=myQueryID\";s:10:\"groupItems\";s:1:\"3\";s:8:\"formType\";s:4:\"lite\";}'
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: sql
+ note: "SQL条件"
+ range: "(( 1 AND `name` LIKE '%aa%' ) AND ( 1 )) AND deleted = '0'"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: shortcut
+ note: "显示在菜单栏"
+ range: 0,1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/usertpl.yaml b/test/devdata/usertpl.yaml
new file mode 100644
index 0000000000..015c97b661
--- /dev/null
+++ b/test/devdata/usertpl.yaml
@@ -0,0 +1,47 @@
+title: table zt_usertpl
+desc: "用户模块"
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: "ID"
+ range: 1-10000
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: account
+ range: admin,dev10,top10,test10,po10
+ note: "用户名"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: type
+ note: "类型"
+ range: exporttask,story,exportbug,exportstory
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: title
+ note: "模板名"
+ range: 1-10000
+ prefix: "模板名称"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: content
+ note: "内容"
+ range: 1-10000
+ prefix: "模块内容"
+ postfix: ""
+ loop: 0
+ format: ""
+ - field: public
+ note: "是否公开"
+ range: 0,1
+ prefix: ""
+ postfix: ""
+ loop: 0
+ format: ""
diff --git a/test/devdata/userview.yaml b/test/devdata/userview.yaml
new file mode 100644
index 0000000000..c134b48504
--- /dev/null
+++ b/test/devdata/userview.yaml
@@ -0,0 +1,36 @@
+title: table zt_userview
+desc: "可访问权限"
+author: automated export
+version: "1.0"
+fields:
+ - field: account
+ note: "用户名"
+ fields:
+ - field: account1
+ range: test{1000},dev{1000},td{1000},top{1000}
+ - field: account2
+ range: 1-1000,1-1000,1-1000,1-1000
+ - field: programs
+ note: "项目集"
+ range: 1-1000
+ prefix: ","
+ postfix: ""
+ format: ""
+ - field: products
+ note: "产品"
+ range: 1-1000
+ prefix: ","
+ postfix: ""
+ format: ""
+ - field: projects
+ note: "项目"
+ range: 1001-20000
+ prefix: ","
+ postfix: ""
+ format: ""
+ - field: sprints
+ note: "迭代"
+ range: 20001-50000
+ prefix: ","
+ postfix: ""
+ format: ""
diff --git a/test/devdata/vm.yaml b/test/devdata/vm.yaml
new file mode 100644
index 0000000000..6e7d1284eb
--- /dev/null
+++ b/test/devdata/vm.yaml
@@ -0,0 +1,36 @@
+title: zt_vm
+author: Zeng gang
+version: "1.0"
+fields:
+ - field: id
+ range: 1
+ - field: hostID
+ range: 1
+ - field: name
+ range: vm1
+ - field: osCategory
+ range: windows
+ - field: osType
+ range: winServer
+ - field: osLang
+ range: zh_cn
+ - field: osCpu
+ range: 1
+ - field: osMemory
+ range: 512
+ - field: osDisk
+ range: 10240
+ - field: status
+ range: running
+ - field: macAddress
+ range: [1C:1C:1C:56:34:84]
+ - field: templateID
+ range: 1
+ - field: vncPort
+ range: 5910
+ - field: createdBy
+ range: admin
+ - field: createdDate
+ range: [2022-03-09 09:29:53]
+ - field: deleted
+ range: 0
diff --git a/test/devdata/vmtemplate.yaml b/test/devdata/vmtemplate.yaml
new file mode 100644
index 0000000000..e7b97516d5
--- /dev/null
+++ b/test/devdata/vmtemplate.yaml
@@ -0,0 +1,26 @@
+title: zt_vmtemplate
+author: Zeng gang
+version: "1.0"
+fields:
+ - field: id
+ range: 1
+ - field: name
+ range: 模板1
+ - field: hostID
+ range: 1
+ - field: templateName
+ range: [tmpl-win10-pro-x64-zh_cn-desktop]
+ - field: osType
+ range: winServer
+ - field: osCategory
+ range: windows
+ - field: osVersion
+ range: 2008
+ - field: osLang
+ range: zh_cn
+ - field: cpuCoreNum
+ range: 1
+ - field: memorySize
+ range: 512
+ - field: diskSize
+ range: 10240
diff --git a/test/devdata/webhook.yaml b/test/devdata/webhook.yaml
new file mode 100644
index 0000000000..fffe29d6c5
--- /dev/null
+++ b/test/devdata/webhook.yaml
@@ -0,0 +1,134 @@
+title: table zt_webhook
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ note: ""
+ range: 1-100
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: type
+ note: ""
+ range: dinggroup,dinguser,wechatgroup,wechatuser,feishugroup,feishuuser,default
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: name
+ note: ""
+ range: 钉钉群机器人,钉钉工作消息,企业微信机器人,企业微信应用,飞书群机器人,飞书工作消息,其他
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: url
+ note: ""
+ range: [https://oapi.dinggroup.com/, https://oapi.dingtalk.com/,https://qyapi.weixin.qq.com/cgi-bin/,https://qyapi.weixin.qq.com/cgi-bin/,https://open.feishu.cn/open-apis/, https://open.feishu.cn/open-apis/,http://qita.com/]
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: domain
+ note: ""
+ range: "http://127.0.0.1"
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: secret
+ note: ""
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: contentType
+ note: ""
+ range: "application/json"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: sendType
+ note: ""
+ range: "sync"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: products
+ note: ""
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: executions
+ note: ""
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: params
+ note: ""
+ range: "text"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: actions
+ note: ""
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: desc
+ note: ""
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: createdBy
+ note: ""
+ range: "admin"
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: createdDate
+ note: ""
+ range: "(M)-(w):60"
+ type: timestamp
+ prefix: ""
+ postfix: ""
+ format: "YYYY-MM-DD hh:mm:ss"
+ - field: editedBy
+ note: ""
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: editedDate
+ note: ""
+ range: ""
+ prefix: ""
+ postfix: ""
+ format: ""
+ - field: deleted
+ note: ""
+ range: "0"
+ prefix: ""
+ postfix: ""
+ format: ""
diff --git a/test/devdata/weeklyreport.yaml b/test/devdata/weeklyreport.yaml
new file mode 100644
index 0000000000..b7693c1b6b
--- /dev/null
+++ b/test/devdata/weeklyreport.yaml
@@ -0,0 +1,89 @@
+title: table zt_weeklyreport
+desc: ""
+author: automated export
+version: "1.0"
+fields:
+ - field: id
+ range: 1-10000
+ note: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: project
+ range: 41-50
+ note: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: weekStart
+ note: ""
+ range: ""
+ prefix: "2022-05-02"
+ postfix: ""
+ - field: pv
+ range: 1-10
+ note: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: ev
+ note: ""
+ range: 1-10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: ac
+ note: ""
+ range: 2-10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: sv
+ note: ""
+ range: 3-10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: cv
+ note: ""
+ range: 4-10
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: staff
+ note: ""
+ range: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: progress
+ note: ""
+ range: 1-10
+ prefix: "测试"
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
+ - field: workload
+ note: ""
+ prefix: ""
+ postfix: ""
+ loop: 0
+ loopfix: ""
+ format: ""
diff --git a/test/devdata/zentao/blockdefault.yaml b/test/devdata/zentao/blockdefault.yaml
new file mode 100644
index 0000000000..0ed01e6f1b
--- /dev/null
+++ b/test/devdata/zentao/blockdefault.yaml
@@ -0,0 +1,12 @@
+title: blockDefault
+author: Tian shujie
+version: "1.0"
+fields:
+ - field: id
+ range: 1-10000
+ - field: account
+ fields:
+ - field: account1
+ range: admin{30},test{30},pm{30},pd{30},qd{30}
+ - field: account2
+ range: []{30},1{120}
diff --git a/test/devdata/zentao/blockrandom.yaml b/test/devdata/zentao/blockrandom.yaml
new file mode 100644
index 0000000000..ee76b36121
--- /dev/null
+++ b/test/devdata/zentao/blockrandom.yaml
@@ -0,0 +1,12 @@
+title: blockRandom
+author: Tian shujie
+version: "1.0"
+fields:
+ - field: id
+ range: 151-10000
+ - field: account
+ fields:
+ - field: account1
+ range: test{30},dev{30},pm{30},po{30}
+ - field: account2
+ range: 2{5},3{5},4{5},5{5},6{5},9{5}
diff --git a/test/devdata/zentao/config.php b/test/devdata/zentao/config.php
new file mode 100644
index 0000000000..d5c73196d3
--- /dev/null
+++ b/test/devdata/zentao/config.php
@@ -0,0 +1,102 @@
+company = array('rows' => 2, 'extends' => array('company'));
+$builder->user = array('rows' => 10000, 'extends' => array('user'));
+$builder->dept = array('rows' => 100, 'extends' => array('dept'));
+$builder->product = array('rows' => 1000, 'extends' => array('product'));
+$builder->productplan = array('rows' => 1000, 'extends' => array('productplan'));
+$builder->story = array('rows' => 50000, 'extends' => array('story'));
+$builder->program = array('rows' => 1000, 'extends' => array('project', 'program'));
+$builder->project = array('rows' => 19000, 'extends' => array('project'));
+$builder->projectproduct = array('rows' => 19000, 'extends' => array('projectproduct'));
+$builder->projectstory = array('rows' => 50000, 'extends' => array('projectstory'));
+$builder->sprint = array('rows' => 30000, 'extends' => array('project', 'execution'));
+$builder->task = array('rows' => 500000, 'extends' => array('task'));
+$builder->bug = array('rows' => 500000, 'extends' => array('bug'));
+$builder->todo = array('rows' => 2000, 'extends' => array('todo'));
+$builder->effort = array('rows' => 100, 'extends' => array('effort'));
+$builder->usergroup = array('rows' => 600, 'extends' => array('usergroup'));
+$builder->usercontact = array('rows' => 61, 'extends' => array('usercontact'));
+$builder->userview = array('rows' => 4000, 'extends' => array('userview'));
+$builder->action = array('rows' => 654000, 'extends' => array('action'));
+$builder->history = array('rows' => 500000, 'extends' => array('history'));
+$builder->file = array('rows' => 100, 'extends' => array('file'));
+$builder->score = array('rows' => 100, 'extends' => array('score'));
+$builder->extension = array('rows' => 10, 'extends' => array('extension'));
+
+$builder->pipeline = array('rows' => 5, 'extends' => array('pipeline'));
+$builder->repo = array('rows' => 1, 'extends' => array('repo'));
+$builder->job = array('rows' => 2, 'extends' => array('job'));
+$builder->mr = array('rows' => 1, 'extends' => array('mr'));
+
+$builder->storyreview = array('rows' => 1000, 'extends' => array('storyreview'));
+$builder->storymodule = array('rows' => 800, 'extends' => array('module','storymodule'));
+$builder->storymoduleson = array('rows' => 400, 'extends' => array('module','storymoduleson'));
+$builder->storyplan = array('rows' => 10000, 'extends' => array('planstory'));
+$builder->storystage = array('rows' => 50000, 'extends' => array('storystage'));
+$builder->storyspec = array('rows' => 570, 'extends' => array('storyspec'));
+$builder->storyestimate = array('rows' => 6, 'extends' => array('storyestimate'));
+$builder->relation = array('rows' => 12, 'extends' => array('relation'));
+$builder->taskspec = array('rows' => 600, 'extends' => array('taskspec'));
+$builder->taskmodule = array('rows' => 1800, 'extends' => array('module','taskmodule'));
+$builder->taskmoduleson = array('rows' => 600, 'extends' => array('module','taskmoduleson'));
+$builder->taskestimate = array('rows' => 100000, 'extends' => array('taskestimate'));
+$builder->case = array('rows' => 100000, 'extends' => array('case'));
+$builder->casestep = array('rows' => 400, 'extends' => array('casestep'));
+$builder->casemodule = array('rows' => 100, 'extends' => array('module', 'casemodule'));
+$builder->casemoduleson = array('rows' => 200, 'extends' => array('module', 'casemoduleson'));
+$builder->bugmodule = array('rows' => 100, 'extends' => array('module','bugmodule'));
+$builder->bugmoduleson = array('rows' => 200, 'extends' => array('module','bugmoduleson'));
+$builder->feedback = array('rows' => 100, 'extends' => array('feedback'));
+$builder->feedbackmodule = array('rows' => 100, 'extends' => array('module','feedbackmodule'));
+$builder->feedbackmoduleson = array('rows' => 200, 'extends' => array('module','feedbackmoduleson'));
+
+$builder->testtask = array('rows' => 1000, 'extends' => array('testtask'));
+$builder->testresult = array('rows' => 70, 'extends' => array('testresult'));
+$builder->testrun = array('rows' => 70, 'extends' => array('testrun'));
+$builder->testreport = array('rows' => 1000, 'extends' => array('testreport'));
+$builder->testsuite = array('rows' => 201, 'extends' => array('testsuite'));
+$builder->suitecase = array('rows' => 400, 'extends' => array('suitecase'));
+//
+$builder->productline = array('rows' => 20, 'extends' => array('module', 'productline'));
+$builder->branch = array('rows' => 240, 'extends' => array('branch'));
+$builder->projectcase = array('rows' => 4000, 'extends' => array('projectcase'));
+$builder->executionstory = array('rows' => 50000, 'extends' => array('projectstory','executionstory'));
+//
+$builder->kanbanspace = array('rows' => 50, 'extends' => array('kanbanspace'));
+$builder->kanban = array('rows' => 100, 'extends' => array('kanban'));
+$builder->kanbanregion = array('rows' => 100, 'extends' => array('kanbanregion','kanbanregion'));
+$builder->kanbangroup = array('rows' => 100, 'extends' => array('kanbangroup','kanbangroup'));
+$builder->kanbanlane = array('rows' => 100, 'extends' => array('kanbanlane','kanbanlane'));
+$builder->kanbancolumn = array('rows' => 400, 'extends' => array('kanbancolumn','kanbancolumn'));
+$builder->kanbancard = array('rows' => 1000, 'extends' => array('kanbancard','kanbancard'));
+$builder->kanbancell = array('rows' => 400, 'extends' => array('kanbancell','kanbancell'));
+
+$builder->team = array('rows' => 100000, 'extends' => array('team'));
+$builder->expect = array('rows' => 270, 'extends' => array('expect'));
+
+$builder->doclib = array('rows' => 910, 'extends' => array('doclib'));
+$builder->doc = array('rows' => 900, 'extends' => array('doc'));
+$builder->doccontent = array('rows' => 910, 'extends' => array('doccontent'));
+$builder->docmodule = array('rows' => 100, 'extends' => array('module','docmodule'));
+$builder->docmoduleon = array('rows' => 200, 'extends' => array('module','docmoduleson'));
+
+$builder->build = array('rows' => 1000, 'extends' => array('build'));
+$builder->release = array('rows' => 1000, 'extends' => array('release'));
+$builder->webhook = array('rows' => 7, 'extends' => array('webhook'));
+$builder->entry = array('rows' => 1, 'extends' => array('entry'));
+$builder->log = array('rows' => 10, 'extends' => array('log'));
+$builder->weeklyreport = array('rows' => 10, 'extends' => array('weeklyreport'));
+$builder->metting = array('rows' => 10, 'extends' => array('meeting'));
+$builder->usertpl = array('rows' => 10, 'extends' => array('usertpl'));
+//
+$builder->holiday = array('rows' => 100, 'extends' => array('holiday'));
+$builder->oauth = array('rows' => 100, 'extends' => array('oauth'));
+$builder->notify = array('rows' => 10, 'extends' => array('notify'));
+//
+//$builder->kanbanregionproject = array('rows' => 180, 'extends' => array('kanbanregion','kanbanregionproject'));
+//$builder->kanbangroupproject = array('rows' => 540, 'extends' => array('kanbangroup','kanbangroupproject'));
+//$builder->kanbanlaneproject = array('rows' => 540, 'extends' => array('kanbanlane','kanbanlaneproject'));
+//$builder->kanbancolumnproject = array('rows' => 4860, 'extends' => array('kanbancolumn','kanbancolumnproject'));
+//$builder->kanbancellproject = array('rows' => 4860, 'extends' => array('kanbancell','kanbancellproject'));
diff --git a/test/devdata/zentao/processor.php b/test/devdata/zentao/processor.php
new file mode 100644
index 0000000000..3527bc78f8
--- /dev/null
+++ b/test/devdata/zentao/processor.php
@@ -0,0 +1,462 @@
+dao = $dao;
+ }
+
+ /**
+ * Init data.
+ *
+ * @access public
+ * @return void
+ */
+ public function init()
+ {
+ $this->dao->begin();
+
+ //$this->initBassicSql();
+ $this->initDept();
+ //$this->initUser();
+ //$this->initProgram();
+ //$this->initProduct();
+ //$this->initPlan();
+ //$this->initProject();
+ //$this->initBuild();
+ //$this->initTask();
+ //$this->initExecution();
+ //$this->initRelease();
+ //$this->initStakeholder();
+ //$this->initUserquery();
+ //$this->initMessage();
+ //$this->initUpdateKanban();
+ //$this->initStory();
+ //$this->initBug();
+ //$this->initTest();
+ //$this->initTodo();
+ //$this->initSonPlan();
+
+ $this->dao->commit();
+ }
+
+ /**
+ * Init department.
+ *
+ * @access public
+ * @return void
+ */
+ private function initDept()
+ {
+ $data = array('parent' => 2, 'path' => ",2,5,", 'grade' => 2);
+ $this->dao->update(TABLE_DEPT)->data($data)->where('id')->eq(5)->exec();
+
+ $data = array('parent' => 2, 'path' => ",2,6,", 'grade' => 2);
+ $this->dao->update(TABLE_DEPT)->data($data)->where('id')->eq(6)->exec();
+
+ for($id = 18; $id <= 27; $id++)
+ {
+ $parent = $id - 10;
+ $child = $id + 10;
+
+ $data = array('parent' => $parent, 'path' => ",$parent,$id,", 'grade' => 2);
+ $this->dao->update(TABLE_DEPT)->data($data)->where('id')->eq($id)->exec();
+
+ $data = array('parent' => $id, 'path' => ",$parent,$id,$child,", 'grade' => 3);
+ $this->dao->update(TABLE_DEPT)->data($data)->where('id')->eq($child)->exec();
+ }
+ }
+
+ /**
+ * Init user.
+ *
+ * @access public
+ * @return void
+ */
+ private function initUser()
+ {
+ $users = array();
+ $users['user1'] = array('account' => 'program1whitelist', 'realname' => '项目集1白名单用户');
+ $users['user2'] = array('account' => 'noprogram1', 'realname' => '不在项目集1用户');
+
+ foreach($users as $account => $user) $this->dao->update(TABLE_USER)->data($user)->where('account')->eq($account)->exec();
+
+ $this->dao->update(TABLE_USERCONTACT)->set('account')->eq('admin')->where('account')->like('admin%')->exec();
+
+ $productIDList = $this->dao->select('id')->from(TABLE_PRODUCT)->fetchAll();
+ $projectIDList = $this->dao->select('id')->from(TABLE_PROJECT)->where('type')->eq('project')->fetchAll();
+ $sprintIDList = $this->dao->select('id')->from(TABLE_EXECUTION)->where('type')->in('sprint,stage,kanban')->fetchAll();
+
+ $product = array();
+ $project = array();
+ $sprint = array();
+ foreach($productIDList as $productID) $product[] = $productID->id;
+ foreach($projectIDList as $projectID) $project[] = $projectID->id;
+ foreach($sprintIDList as $sprintID) $sprint[] = $sprintID->id;
+
+ $products = ",".join(",",$product);
+ $projects = ",".join(",",$project);
+ $sprints = ",".join(",",$sprint);
+
+ $userViews = new stdclass();
+ $userViews->account = 'admin';
+ $userViews->programs = ',1,2,3,4,5,6,7,8,9,10';
+ $userViews->products = $products;
+ $userViews->projects = $projects;
+ $userViews->sprints = $sprints;
+ $this->dao->insert(TABLE_USERVIEW)->data($userViews)->exec();
+
+ $guestViews = new stdclass();
+ $guestViews->account = 'guest';
+ $guestViews->programs = '';
+ $guestViews->products = '';
+ $guestViews->projects = '';
+ $guestViews->sprints = '';
+ $this->dao->insert(TABLE_USERVIEW)->data($guestViews)->exec();
+ }
+
+ /**
+ * Init program.
+ *
+ * @access public
+ * @return void
+ */
+ private function initProgram()
+ {
+ }
+
+ /**
+ * Init product.
+ *
+ * @access public
+ * @return void
+ */
+ private function initProduct()
+ {
+ }
+
+ /**
+ * Init Story.
+ *
+ * @access private
+ * @return void
+ */
+ private function initStory()
+ {
+ $this->dao->update(TABLE_STORY)->set('`status`')->eq('active')->where('id')->le('20')->exec();
+ $this->dao->update(TABLE_STORY)->set('`status`')->eq('draft')->where('id')->ge('300')->andwhere('id')->le('400')->exec();
+ $this->dao->update(TABLE_STORY)->set('`closedBy`')->eq('')->set('`closedReason`')->eq('')->where('status')->ne('closed')->exec();
+ $this->dao->update(TABLE_STORY)->set('`plan`')->eq('0')->where('id')->gt('300')->andwhere('id')->lt('321')->exec();
+
+ $accounts = array('user92' => 'po82', 'user93' => 'po83', 'user94' => 'po84', 'user95' => 'po85', 'user96' => 'po86', 'user97' => 'po82');
+ foreach($accounts as $key => $value)
+ {
+ $this->dao->update(TABLE_STORYESTIMATE)->set('`estimate`')->eq("{\"$value\":{\"account\":\"$value\",\"estimate\":1},\"$key\":{\"account\":\"$key\",\"estimate\":2}")->where('estimate')->eq($key)->exec();
+ }
+
+ }
+
+ /**
+ * Init Test.
+ *
+ * @access private
+ * @return void
+ */
+ private function initBug()
+ {
+ $this->dao->update(TABLE_BUG)->set('`issueKey`')->eq('2:AX-W7K3_L7H_36P3H4le')->where('issueKey')->eq('17')->exec();
+ }
+
+ private function initTest()
+ {
+ $testResults = $this->dao->select('*')->from(TABLE_TESTRESULT)->fetchAll();
+
+ foreach($testResults as $testResult)
+ {
+ if($testResult->caseResult == 'fail')
+ {
+ $this->dao->update(TABLE_TESTRESULT)->set('`stepResults`')->eq('a:1:{i:'.$testResult->run.';a:2:{s:6:\"result\";s:4:\"fail\";s:4:\"real\";s:0:\"\";}}')->where('id')->eq($testResult->id)->exec();
+ }
+ else
+ {
+ $this->dao->update(TABLE_TESTRESULT)->set('`stepResults`')->eq('a:1:{i:'.$testResult->run.';a:2:{s:6:\"result\";s:4:\"pass\";s:4:\"real\";s:0:\"\";}}')->where('id')->eq($testResult->id)->exec();
+ }
+ }
+ }
+
+ /**
+ * Init product plan.
+ *
+ * @access public
+ * @return void
+ */
+ private function initPlan()
+ {
+ }
+
+ /**
+ * Init project.
+ *
+ * @access public
+ * @return void
+ */
+ private function initProject()
+ {
+ }
+
+ /**
+ * Init build.
+ *
+ * @access public
+ * @return void
+ */
+ private function initBuild()
+ {
+ }
+
+ /**
+ * Init task.
+ *
+ * @access public
+ * @return void
+ */
+ private function initTask()
+ {
+ $parentList = $this->dao->select('parent')->from(TABLE_TASK)->where('parent')->gt(0)->fetchAll('parent');
+ $parentIDList = array_keys($parentList);
+ $parentID = implode(',', $parentIDList);
+
+ $this->dao->update(TABLE_TASK)->set('parent')->eq(-1)->where('id')->in($parentID)->andWhere('deleted')->eq(0)->exec();
+ $this->dao->update(TABLE_TASK)->set('assignedTo')->eq('po82')->set('mailto')->eq('user1,user2,user3')->set('frombug')->eq('1')->where('id')->eq(1)->andWhere('deleted')->eq(0)->exec();
+ }
+
+ /**
+ * Init execution.
+ *
+ * @access public
+ * @return void
+ */
+ private function initExecution()
+ {
+ /* Add relationship of projectproduct. */
+ $projectProducts = $this->dao->select('*')->from(TABLE_PROJECTPRODUCT)->fetchAll();
+ $productsInProject = array();
+ foreach($projectProducts as $relation)
+ {
+ if(!isset($productsInProject[$relation->project])) $productsInProject[$relation->project] = array();
+ $productsInProject[$relation->project][] = $relation->product;
+ }
+
+ $executions = $this->dao->select('*')->from(TABLE_PROJECT)->where('type')->in('sprint,kanban,stage')->fetchAll();
+ foreach($executions as $execution)
+ {
+ $products = $productsInProject[$execution->project];
+ foreach($products as $product)
+ {
+ $data = new stdclass();
+ $data->project = $execution->id;
+ $data->product = $product;
+ $this->dao->insert(TABLE_PROJECTPRODUCT)->data($data)->exec();
+ }
+ }
+ }
+
+ /**
+ * Init release.
+ *
+ * @access public
+ * @return void
+ */
+ private function initRelease()
+ {
+ }
+
+ /**
+ * init BassicSql.
+ *
+ * @access private
+ * @return void
+ */
+ private function initBassicSql()
+ {
+ global $app;
+ $sqlRoot = $app->getAppRoot();
+ $this->dao->exec(file_get_contents($sqlRoot . '/data/zt_block.sql'));
+ $this->dao->exec(file_get_contents($sqlRoot . '/data/zt_lang.sql'));
+ $this->dao->exec(file_get_contents($sqlRoot . '/data/zt_cron.sql'));
+ }
+
+ /**
+ * Init Stakeholder.
+ *
+ * @access public
+ * @return void
+ */
+ private function initStakeholder()
+ {
+ /* Add stakeholder of project. */
+ $projectProgramPairs = $this->dao->select('id,type')->from(TABLE_PROJECT)->where('type')->in('project,program')->andwhere('id')->lt('730')->fetchPairs();
+ $accounts = $this->dao->select('id,account')->from(TABLE_USER)->fetchPairs();
+
+ foreach($projectProgramPairs as $id => $type)
+ {
+ $users = array($accounts[$id*10] ,$accounts[$id*10-1] ,$accounts[$id*10-2]);
+ $data = new stdclass();
+ foreach($users as $userID => $userAccount)
+ {
+ $data->objectID = $id;
+ $data->objectType = $type;
+ $data->user = $userAccount;
+ $this->dao->insert(TABLE_STAKEHOLDER)->data($data)->exec();
+ }
+ }
+ $this->dao->update(TABLE_STAKEHOLDER)->set('`type`')->eq('inside')->where('id')->le('300')->exec();
+ $this->dao->update(TABLE_STAKEHOLDER)->set('`type`')->eq('outside')->set('`user`')->eq('outside1')->where('id')->eq('301')->exec();
+ }
+
+ /**
+ * Init userquery.
+ *
+ * @access public
+ * @return void
+ */
+ private function initUserquery()
+ {
+ $this->dao->query("DELETE FROM `zt_userquery`;");
+ $this->dao->query("INSERT INTO `zt_userquery` (`id`, `account`, `module`, `title`, `form`, `sql`, `shortcut`) VALUES (1, 'admin', 'task', '任务查询测试条件', 'a:60:{s:9:\"fieldname\";s:0:\"\";s:11:\"fieldstatus\";s:0:\"\";s:9:\"fielddesc\";s:0:\"\";s:15:\"fieldassignedTo\";s:0:\"\";s:8:\"fieldpri\";s:1:\"0\";s:14:\"fieldexecution\";s:0:\"\";s:11:\"fieldmodule\";s:4:\"ZERO\";s:13:\"fieldestimate\";s:0:\"\";s:9:\"fieldleft\";s:0:\"\";s:13:\"fieldconsumed\";s:0:\"\";s:9:\"fieldtype\";s:0:\"\";s:12:\"fieldfromBug\";s:0:\"\";s:17:\"fieldclosedReason\";s:0:\"\";s:13:\"fieldopenedBy\";s:0:\"\";s:15:\"fieldfinishedBy\";s:0:\"\";s:13:\"fieldclosedBy\";s:0:\"\";s:13:\"fieldcancelBy\";s:1:\"0\";s:17:\"fieldlastEditedBy\";s:0:\"\";s:11:\"fieldmailto\";s:0:\"\";s:17:\"fieldfinishedList\";s:0:\"\";s:15:\"fieldopenedDate\";s:0:\"\";s:13:\"fielddeadline\";s:0:\"\";s:15:\"fieldestStarted\";s:0:\"\";s:16:\"fieldrealStarted\";s:0:\"\";s:17:\"fieldassignedDate\";s:0:\"\";s:17:\"fieldfinishedDate\";s:0:\"\";s:15:\"fieldclosedDate\";s:0:\"\";s:17:\"fieldcanceledDate\";s:0:\"\";s:19:\"fieldlastEditedDate\";s:0:\"\";s:7:\"fieldid\";s:0:\"\";s:15:\"fieldcanceledBy\";s:0:\"\";s:6:\"andOr1\";s:3:\"AND\";s:6:\"field1\";s:4:\"name\";s:9:\"operator1\";s:7:\"include\";s:6:\"value1\";s:2:\"aa\";s:6:\"andOr2\";s:3:\"and\";s:6:\"field2\";s:2:\"id\";s:9:\"operator2\";s:1:\"=\";s:6:\"value2\";s:0:\"\";s:6:\"andOr3\";s:3:\"and\";s:6:\"field3\";s:6:\"status\";s:9:\"operator3\";s:1:\"=\";s:6:\"value3\";s:0:\"\";s:10:\"groupAndOr\";s:3:\"and\";s:6:\"andOr4\";s:3:\"AND\";s:6:\"field4\";s:4:\"desc\";s:9:\"operator4\";s:7:\"include\";s:6:\"value4\";s:0:\"\";s:6:\"andOr5\";s:3:\"and\";s:6:\"field5\";s:10:\"assignedTo\";s:9:\"operator5\";s:1:\"=\";s:6:\"value5\";s:0:\"\";s:6:\"andOr6\";s:3:\"and\";s:6:\"field6\";s:3:\"pri\";s:9:\"operator6\";s:1:\"=\";s:6:\"value6\";s:1:\"0\";s:6:\"module\";s:4:\"task\";s:9:\"actionURL\";s:77:\"/index.php?m=execution&f=task&executionID=101&status=bySearch¶m=myQueryID\";s:10:\"groupItems\";s:1:\"3\";s:8:\"formType\";s:4:\"lite\";}', '(( 1 AND `name` LIKE \'%11%\' ) AND ( 1 )) AND deleted = \'0\'', '0');");
+ $this->dao->query("INSERT INTO `zt_userquery` (`id`, `account`, `module`, `title`, `form`, `sql`, `shortcut`) VALUES (2, 'admin', 'executionStory', '需求查找条件', 'a:56:{s:10:\"fieldtitle\";s:0:\"\";s:13:\"fieldkeywords\";s:0:\"\";s:11:\"fieldstatus\";s:0:\"\";s:10:\"fieldstage\";s:0:\"\";s:8:\"fieldpri\";s:1:\"0\";s:12:\"fieldproduct\";s:1:\"0\";s:11:\"fieldbranch\";s:0:\"\";s:11:\"fieldmodule\";s:4:\"ZERO\";s:9:\"fieldplan\";s:0:\"\";s:13:\"fieldestimate\";s:0:\"\";s:11:\"fieldsource\";s:0:\"\";s:15:\"fieldsourceNote\";s:0:\"\";s:12:\"fieldfromBug\";s:0:\"\";s:13:\"fieldopenedBy\";s:0:\"\";s:15:\"fieldreviewedBy\";s:0:\"\";s:15:\"fieldassignedTo\";s:0:\"\";s:13:\"fieldclosedBy\";s:0:\"\";s:17:\"fieldlastEditedBy\";s:0:\"\";s:11:\"fieldmailto\";s:0:\"\";s:17:\"fieldclosedReason\";s:0:\"\";s:12:\"fieldversion\";s:0:\"\";s:15:\"fieldopenedDate\";s:0:\"\";s:17:\"fieldreviewedDate\";s:0:\"\";s:17:\"fieldassignedDate\";s:0:\"\";s:15:\"fieldclosedDate\";s:0:\"\";s:19:\"fieldlastEditedDate\";s:0:\"\";s:7:\"fieldid\";s:0:\"\";s:6:\"andOr1\";s:3:\"AND\";s:6:\"field1\";s:5:\"title\";s:9:\"operator1\";s:7:\"include\";s:6:\"value1\";s:3:\"362\";s:6:\"andOr2\";s:3:\"and\";s:6:\"field2\";s:2:\"id\";s:9:\"operator2\";s:1:\"=\";s:6:\"value2\";s:0:\"\";s:6:\"andOr3\";s:3:\"and\";s:6:\"field3\";s:8:\"keywords\";s:9:\"operator3\";s:7:\"include\";s:6:\"value3\";s:0:\"\";s:10:\"groupAndOr\";s:3:\"and\";s:6:\"andOr4\";s:3:\"AND\";s:6:\"field4\";s:5:\"stage\";s:9:\"operator4\";s:1:\"=\";s:6:\"value4\";s:0:\"\";s:6:\"andOr5\";s:3:\"and\";s:6:\"field5\";s:6:\"status\";s:9:\"operator5\";s:1:\"=\";s:6:\"value5\";s:0:\"\";s:6:\"andOr6\";s:3:\"and\";s:6:\"field6\";s:3:\"pri\";s:9:\"operator6\";s:1:\"=\";s:6:\"value6\";s:1:\"0\";s:6:\"module\";s:14:\"executionStory\";s:9:\"actionURL\";s:95:\"/index.php?m=execution&f=story&executionID=101&orderBy=pri_desc&type=bySearch&queryID=myQueryID\";s:10:\"groupItems\";s:1:\"3\";s:8:\"formType\";s:4:\"lite\";}', '(( 1 AND `title` LIKE \'%362%\' ) AND ( 1 ))', '0');");
+ $this->dao->query("INSERT INTO `zt_userquery` (`id`, `account`, `module`, `title`, `form`, `sql`, `shortcut`) VALUES (3, 'admin', 'user', '用户测试条件', 'a:48:{s:13:\"fieldrealname\";s:0:\"\";s:10:\"fieldemail\";s:0:\"\";s:9:\"fielddept\";s:0:\"\";s:12:\"fieldaccount\";s:0:\"\";s:9:\"fieldrole\";s:0:\"\";s:10:\"fieldphone\";s:0:\"\";s:9:\"fieldjoin\";s:0:\"\";s:12:\"fieldvisions\";s:3:\"rnd\";s:7:\"fieldid\";s:0:\"\";s:13:\"fieldcommiter\";s:1:\"0\";s:11:\"fieldgender\";s:1:\"m\";s:7:\"fieldqq\";s:0:\"\";s:10:\"fieldskype\";s:0:\"\";s:13:\"fielddingding\";s:0:\"\";s:11:\"fieldweixin\";s:0:\"\";s:10:\"fieldslack\";s:0:\"\";s:13:\"fieldwhatsapp\";s:0:\"\";s:12:\"fieldaddress\";s:0:\"\";s:12:\"fieldzipcode\";s:0:\"\";s:6:\"andOr1\";s:3:\"AND\";s:6:\"field1\";s:8:\"realname\";s:9:\"operator1\";s:7:\"include\";s:6:\"value1\";s:9:\"白名单\";s:6:\"andOr2\";s:3:\"and\";s:6:\"field2\";s:5:\"email\";s:9:\"operator2\";s:7:\"include\";s:6:\"value2\";s:0:\"\";s:6:\"andOr3\";s:3:\"and\";s:6:\"field3\";s:4:\"dept\";s:9:\"operator3\";s:6:\"belong\";s:6:\"value3\";s:0:\"\";s:10:\"groupAndOr\";s:3:\"and\";s:6:\"andOr4\";s:3:\"AND\";s:6:\"field4\";s:7:\"account\";s:9:\"operator4\";s:7:\"include\";s:6:\"value4\";s:0:\"\";s:6:\"andOr5\";s:3:\"and\";s:6:\"field5\";s:4:\"role\";s:9:\"operator5\";s:1:\"=\";s:6:\"value5\";s:0:\"\";s:6:\"andOr6\";s:3:\"and\";s:6:\"field6\";s:5:\"phone\";s:9:\"operator6\";s:7:\"include\";s:6:\"value6\";s:0:\"\";s:6:\"module\";s:4:\"user\";s:9:\"actionURL\";s:74:\"/index.php?m=company&f=browse&browseType=all¶m=myQueryID&type=bysearch\";s:10:\"groupItems\";s:1:\"3\";s:8:\"formType\";s:4:\"lite\";}', '(( 1 AND `realname` LIKE \'%白名单%\' ) AND ( 1 ))', '0');");
+ $this->dao->query("INSERT INTO `zt_userquery` (`id`, `account`, `module`, `title`, `form`, `sql`, `shortcut`) VALUES (4, 'admin', 'projectBuild', '项目版本搜索', 'a:38:{s:9:\"fieldname\";s:0:\"\";s:12:\"fieldproduct\";s:0:\"\";s:12:\"fieldscmPath\";s:0:\"\";s:13:\"fieldfilePath\";s:0:\"\";s:9:\"fielddate\";s:0:\"\";s:12:\"fieldbuilder\";s:0:\"\";s:9:\"fielddesc\";s:0:\"\";s:14:\"fieldexecution\";s:0:\"\";s:7:\"fieldid\";s:0:\"\";s:6:\"andOr1\";s:3:\"AND\";s:6:\"field1\";s:4:\"name\";s:9:\"operator1\";s:7:\"include\";s:6:\"value1\";s:8:\"版本7\";s:6:\"andOr2\";s:3:\"and\";s:6:\"field2\";s:2:\"id\";s:9:\"operator2\";s:1:\"=\";s:6:\"value2\";s:0:\"\";s:6:\"andOr3\";s:3:\"and\";s:6:\"field3\";s:7:\"product\";s:9:\"operator3\";s:1:\"=\";s:6:\"value3\";s:0:\"\";s:10:\"groupAndOr\";s:3:\"and\";s:6:\"andOr4\";s:3:\"AND\";s:6:\"field4\";s:7:\"scmPath\";s:9:\"operator4\";s:7:\"include\";s:6:\"value4\";s:0:\"\";s:6:\"andOr5\";s:3:\"and\";s:6:\"field5\";s:8:\"filePath\";s:9:\"operator5\";s:7:\"include\";s:6:\"value5\";s:0:\"\";s:6:\"andOr6\";s:3:\"and\";s:6:\"field6\";s:4:\"date\";s:9:\"operator6\";s:1:\"=\";s:6:\"value6\";s:0:\"\";s:6:\"module\";s:12:\"projectBuild\";s:9:\"actionURL\";s:73:\"/index.php?m=project&f=build&projectID=13&type=bysearch&queryID=myQueryID\";s:10:\"groupItems\";s:1:\"3\";s:8:\"formType\";s:4:\"more\";}', '(( 1 AND `name` LIKE \'%版本7%\' ) AND ( 1 ))', '0');");
+ $this->dao->query("INSERT INTO `zt_userquery` (`id`, `account`, `module`, `title`, `form`, `sql`, `shortcut`) VALUES (5, 'admin', 'executionBuild', '执行版本搜索', 'a:37:{s:9:\"fieldname\";s:0:\"\";s:12:\"fieldproduct\";s:0:\"\";s:12:\"fieldscmPath\";s:0:\"\";s:13:\"fieldfilePath\";s:0:\"\";s:9:\"fielddate\";s:0:\"\";s:12:\"fieldbuilder\";s:0:\"\";s:9:\"fielddesc\";s:0:\"\";s:7:\"fieldid\";s:0:\"\";s:6:\"andOr1\";s:3:\"AND\";s:6:\"field1\";s:4:\"name\";s:9:\"operator1\";s:7:\"include\";s:6:\"value1\";s:8:\"版本17\";s:6:\"andOr2\";s:3:\"and\";s:6:\"field2\";s:2:\"id\";s:9:\"operator2\";s:1:\"=\";s:6:\"value2\";s:0:\"\";s:6:\"andOr3\";s:3:\"and\";s:6:\"field3\";s:7:\"product\";s:9:\"operator3\";s:1:\"=\";s:6:\"value3\";s:0:\"\";s:10:\"groupAndOr\";s:3:\"and\";s:6:\"andOr4\";s:3:\"AND\";s:6:\"field4\";s:7:\"scmPath\";s:9:\"operator4\";s:7:\"include\";s:6:\"value4\";s:0:\"\";s:6:\"andOr5\";s:3:\"and\";s:6:\"field5\";s:8:\"filePath\";s:9:\"operator5\";s:7:\"include\";s:6:\"value5\";s:0:\"\";s:6:\"andOr6\";s:3:\"and\";s:6:\"field6\";s:4:\"date\";s:9:\"operator6\";s:1:\"=\";s:6:\"value6\";s:0:\"\";s:6:\"module\";s:14:\"executionBuild\";s:9:\"actionURL\";s:78:\"/index.php?m=execution&f=build&executionID=101&type=bysearch&queryID=myQueryID\";s:10:\"groupItems\";s:1:\"3\";s:8:\"formType\";s:4:\"more\";}', '(( 1 AND `name` LIKE \'%版本17%\' ) AND ( 1 ))', '0');");
+ $this->dao->query("INSERT INTO `zt_userquery` (`id`, `account`, `module`, `title`, `form`, `sql`, `shortcut`) VALUES (6, 'admin', 'design', '设计搜索', 'a:37:{s:9:\"fieldtype\";s:0:\"\";s:9:\"fieldname\";s:0:\"\";s:11:\"fieldcommit\";s:0:\"\";s:14:\"fieldcreatedBy\";s:0:\"\";s:16:\"fieldcreatedDate\";s:0:\"\";s:15:\"fieldassignedTo\";s:0:\"\";s:10:\"fieldstory\";s:1:\"0\";s:7:\"fieldid\";s:0:\"\";s:6:\"andOr1\";s:3:\"AND\";s:6:\"field1\";s:2:\"id\";s:9:\"operator1\";s:1:\"=\";s:6:\"value1\";s:0:\"\";s:6:\"andOr2\";s:3:\"and\";s:6:\"field2\";s:4:\"type\";s:9:\"operator2\";s:1:\"=\";s:6:\"value2\";s:0:\"\";s:6:\"andOr3\";s:3:\"and\";s:6:\"field3\";s:4:\"name\";s:9:\"operator3\";s:7:\"include\";s:6:\"value3\";s:19:\"这是一个设计1\";s:10:\"groupAndOr\";s:3:\"and\";s:6:\"andOr4\";s:3:\"AND\";s:6:\"field4\";s:6:\"commit\";s:9:\"operator4\";s:7:\"include\";s:6:\"value4\";s:0:\"\";s:6:\"andOr5\";s:3:\"and\";s:6:\"field5\";s:9:\"createdBy\";s:9:\"operator5\";s:1:\"=\";s:6:\"value5\";s:0:\"\";s:6:\"andOr6\";s:3:\"and\";s:6:\"field6\";s:11:\"createdDate\";s:9:\"operator6\";s:1:\"=\";s:6:\"value6\";s:0:\"\";s:6:\"module\";s:6:\"design\";s:9:\"actionURL\";s:86:\"/index.php?m=design&f=browse&projectID=41&productID=31&type=bySearch&queryID=myQueryID\";s:10:\"groupItems\";s:1:\"3\";s:8:\"formType\";s:4:\"more\";}', '(( 1 AND `name` LIKE \'%这是一个设计1%\' ) AND ( 1 ))', '0');");
+ }
+
+ private function initMessage()
+ {
+ $this->dao->query("DELETE FROM `zt_config` where `key` = 'setting';");
+ $this->dao->query("INSERT INTO `zt_config` (`vision`, `owner`, `module`, `section`, `key`, `value`) VALUES
+ ('rnd', 'system', 'message', '', 'setting', '{\"mail\":{\"setting\":{\"story\":[\"opened\",\"edited\",\"commented\",\"frombug\",\"changed\",\"reviewed\",\"closed\",\"activated\",\"assigned\"],\"task\":[\"opened\",\"edited\",\"commented\",\"assigned\",\"confirmed\",\"started\",\"finished\",\"paused\",\"canceled\",\"restarted\",\"closed\",\"activated\"],\"testtask\":[\"opened\",\"edited\",\"closed\"],\"doc\":[\"created\",\"edited\"]}},\"message\":{\"setting\":{\"story\":[\"opened\",\"edited\",\"commented\",\"frombug\",\"changed\",\"reviewed\",\"closed\",\"activated\",\"assigned\"],\"task\":[\"opened\",\"edited\",\"commented\",\"assigned\",\"confirmed\",\"started\",\"finished\",\"paused\",\"canceled\",\"restarted\",\"closed\",\"activated\"],\"testtask\":[\"opened\",\"edited\",\"started\",\"blocked\",\"closed\",\"activated\"],\"todo\":[\"opened\",\"edited\"],\"doc\":[\"created\",\"edited\"]}}}');");
+ }
+ private function initTodo()
+ {
+ $toDay = date('y-m-d');
+ $addDay = date('Y-m-d',strtotime("+1 day"));
+
+ $str = '{"day":"1","specify":{"month":"0","day":"1"},"type":"day","beforeDays":11,"end":"","begin":"'.$toDay.'"}';
+ $str2 = '{"specify":{"month":"0","day":"1"},"week":"1,3","type":"week","beforeDays":31,"end":"","begin":"'.$toDay.'"}';
+ $str3 = '{"specify":{"month":"0","day":"1"},"month":"5,17,29","type":"month","beforeDays":301,"end":"","begin":"'.$toDay.'"}';
+
+ $this->dao->update(TABLE_TODO)->SET('config')->eq($str)->where('id')->eq('2001')->exec();
+ $this->dao->update(TABLE_TODO)->SET('date')->eq($addDay)->where('id')->eq('2002')->exec();
+ $this->dao->update(TABLE_TODO)->SET('config')->eq($str2)->where('id')->eq('2003')->exec();
+ $this->dao->update(TABLE_TODO)->SET('config')->eq($str3)->where('id')->eq('2005')->exec();
+
+ }
+
+ /**
+ * Init initUpdateKanban.
+ *
+ * @access public
+ * @return void
+ */
+ private function initUpdateKanban()
+ {
+ $this->dao->query("update zt_kanbancolumn set `limit` = '-1' where id >= 1 and id <= 400");
+ $this->dao->query("update zt_kanbanspace set `whitelist` = '' where type in ('cooperation','public')");
+ $this->dao->query("update zt_kanbanspace set `team` = '' where type = 'private'");
+
+ $kanban = $this->dao->select('id,type,region,name,color,`limit`,`order`')->from(TABLE_KANBANCOLUMN)->where('id')->gt('400')->fetchAll();
+ $group = 101;
+ foreach($kanban as $key => $value)
+ {
+ $id = $value->id;
+
+ $value->limit = '-1';
+ if(!isset($value->parent)) $value->parent = 0;
+
+ if(in_array($value->type, ['develop', 'test', 'resolving']))
+ {
+ $value->parent = '-1';
+ $kanban[$key+1]->parent = $value->id;
+ $kanban[$key+2]->parent = $value->id;
+ }
+
+ $value->group = $group;
+ if($value->type == 'closed')
+ {
+ $group++;
+ }
+ unset($value->id);
+ $this->dao->update(TABLE_KANBANCOLUMN)->data($value)->where('id')->eq($id)->exec();
+ }
+
+ $kanbancell = $this->dao->select('id,type')->from(TABLE_KANBANCELL)->where('id')->gt('400')->fetchAll();
+ $kanbanlane = 101;
+ foreach($kanbancell as $key => $value)
+ {
+ $id = $value->id;
+
+ $value->lane = $kanbanlane;
+
+ if($value->type == 'story' && isset($kanbancell[$key+1]) && $kanbancell[$key+1]->type == 'bug')
+ {
+ $kanbanlane++;
+ }
+
+ if($value->type == 'bug' && isset($kanbancell[$key+1]) && $kanbancell[$key+1]->type == 'task')
+ {
+ $kanbanlane++;
+ }
+ if($value->type == 'task' && isset($kanbancell[$key+1]) && $kanbancell[$key+1]->type == 'story')
+ {
+ $kanbanlane++;
+ }
+ unset($value->id);
+ $this->dao->update(TABLE_KANBANCELL)->data($value)->where('id')->eq($id)->exec();
+ }
+ $this->dao->query("update zt_kanbancell set `cards` = '' where id > 400");
+ $this->dao->query("update zt_kanbancell set `cards` = ',244,' where id = 401");
+ $this->dao->query("update zt_kanbancell set `cards` = ',181,182,183,' where id = 412");
+ $this->dao->query("update zt_kanbancell set `cards` = ',61,' where id = 421");
+ $this->dao->query("update zt_kanbancell set `cards` = ',246,' where id = 428");
+ $this->dao->query("update zt_kanbancell set `cards` = ',184,185,186,' where id = 439");
+ $this->dao->query("update zt_kanbancell set `cards` = ',62,' where id = 448");
+ $this->dao->query("update zt_kanbancell set `cards` = ',247,' where id = 458");
+ $this->dao->query("update zt_kanbancell set `cards` = ',187,188,189,' where id = 469");
+ $this->dao->query("update zt_kanbancell set `cards` = ',63,' where id = 477");
+ $this->dao->query("update zt_kanbancell set `cards` = ',248,' where id = 485");
+ $this->dao->query("update zt_kanbancell set `cards` = ',190,191,192,' where id = 496");
+ $this->dao->query("update zt_kanbancell set `cards` = ',64,' where id = 504");
+ $this->dao->query("update zt_kanbancolumn set `parent` = '-1' where id = 202");
+ $this->dao->query("update zt_kanbancolumn set `parent` = '202' where id in ('203','204')");
+ $this->dao->query("update zt_kanbancolumn set `parent` = '-1' where id = 206");
+ $this->dao->query("update zt_kanbancolumn set `parent` = '206' where id in ('207','208')");
+ }
+
+ /**
+ * Init son plan
+ *
+ * @access public
+ * @return void
+ */
+ public function initSonPlan()
+ {
+ $this->dao->query("update zt_productplan set `parent` = '-1' where id < 10 and id > 0");
+ }
+}
diff --git a/test/lib/init.php b/test/lib/init.php
index e3ad2b4625..387ef1f449 100644
--- a/test/lib/init.php
+++ b/test/lib/init.php
@@ -102,9 +102,6 @@ function p($keys = '', $delimiter = ',')
{
global $_result;
- $_keys = $keys;
- $_delimiter = $delimiter;
-
if(empty($_result)) return print(implode("\n", array_fill(0, substr_count($keys, $delimiter) + 1, 0)) . "\n");
if(is_array($_result) and isset($_result['code']) and $_result['code'] == 'fail') return print((string) $_result['message'] . "\n");
@@ -117,6 +114,8 @@ function p($keys = '', $delimiter = ',')
foreach($parts as $part)
{
$values = getValues($_result, $part, $delimiter);
+ if(!is_array($values)) continue;
+
foreach($values as $value) echo $value . "\n";
}
@@ -273,7 +272,7 @@ function genModuleAndMethod($rParams)
{
$param = trim($param, "'");
if($param[0] != '$') $param = trim(strchr($param, '$'), ')');
-
+
$objArrowCount = substr_count($param, '->');
$rParamsStructureList = explode('->', $param);
@@ -475,7 +474,9 @@ function zdImport($table, $yaml, $count = 10)
function su($account)
{
$userModel = new userModel();
- $user = $userModel->identify($account, '123Qwe!@#');
+ $user = $userModel->getByID($account);
if($user) return $userModel->login($user);
+
+ $user = $userModel->identify($account, $user->password);
return false;
}
diff --git a/test/lib/utils.php b/test/lib/utils.php
index fd32f1bc0c..7663e181c2 100755
--- a/test/lib/utils.php
+++ b/test/lib/utils.php
@@ -115,22 +115,20 @@ function getCaseModelDir()
* @access public
* @return void
*/
-function zdRun($dataVersion = '', $dbFile = '')
+function zdRun($isDev = false)
{
- global $config, $dao, $db;
+ global $config, $dao;
$frameworkRoot = dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'framework' . DIRECTORY_SEPARATOR;
include LIB_ROOT . 'spyc.php';
- if($dataVersion && $dbFile)
+ $zdRoot = dirname(dirname(__FILE__)) . '/data/';
+ if($isDev === true)
{
- $db->replaceDBConfig($dbFile);
- $zdRoot = dirname(dirname(__FILE__)) . "/data/{$dataVersion}/";
- }
- else
- {
- $zdRoot = dirname(dirname(__FILE__)) . '/data/';
+ if(isset($config->db->devDbName)) $dao->exec("use {$config->db->devDbName};");
+ $zdRoot = dirname(dirname(__FILE__)) . "/devdata/";
}
+
$zdPath = RUNTIME_ROOT . 'zd';
set_time_limit(0);
diff --git a/test/lib/yaml.class.php b/test/lib/yaml.class.php
index 87bd834641..56cd39a8fd 100644
--- a/test/lib/yaml.class.php
+++ b/test/lib/yaml.class.php
@@ -341,21 +341,6 @@ class yaml
$this->insertDB($yamlFile, $this->tableName, $rows, $isClear);
}
- /**
- * 打印zendata生成的sql和导入数据库产生的错误.
- * Print sql and error.
- *
- * @param int $rows
- * @param bool $isClear Truncate table if set isClear to true.
- * @param bool $debug Print sql and error if set isClear to true.
- * @access public
- * @return void
- */
- public function debug($rows, $isClear = true)
- {
- $yamlFile = $this->mergeYaml();
- $this->insertDB($yamlFile, $this->tableName, $rows, $isClear, true);
- }
/**
* Insert the data into database.
*
@@ -363,11 +348,10 @@ class yaml
* @param string $tableName
* @param int $rows
* @param bool $isClear Truncate table if set isClear to true.
- * @param bool $debug
* @access public
* @return string
*/
- function insertDB($yamlFile, $tableName, $rows, $isClear = true, $debug = false)
+ function insertDB($yamlFile, $tableName, $rows, $isClear = true)
{
$tableSqlDir = "{$_SERVER['PWD']}/data/sql";
@@ -385,32 +369,51 @@ class yaml
$dbUser = $this->config->db->user;
$dbPWD = $this->config->db->password;
- $command = "$zdPath -c %s -d %s -n %d -t %s -dns mysql://%s:%s@%s:%s/%s#utf8";
+ $command = "mysql -u%s -p%s -h%s -P%s -D%s < %s";
$genSQL = "$zdPath -c %s -d %s -n %d -t %s -o %s";
if($isClear === true)
{
/* Truncate table to reset auto increment number. */
system(sprintf("mysql -u%s -p%s -h%s -P%s %s -e 'truncate %s' 2>/dev/null", $dbUser, $dbPWD, $dbHost, $dbPort, $dbName, $tableName));
- $command .= ' --clear';
}
$sqlPath = "{$tableSqlDir}/{$tableName}_zd.sql";
- $execYaml = sprintf($command, $configYaml, $yamlFile, $rows, $tableName, $dbUser, $dbPWD, $dbHost, $dbPort, $dbName);
+ $execYaml = sprintf($command, $dbUser, $dbPWD, $dbHost, $dbPort, $dbName, $sqlPath);
$execDump = sprintf($dumpCommand, $dbUser, $dbPWD, $dbHost, $dbPort, $dbName, $tableName);
$execGenSQL = sprintf($genSQL, $configYaml, $yamlFile, $rows, $tableName, $sqlPath);
system($execGenSQL);
- if($debug)
- {
- echo "\n" . file_get_contents($sqlPath) . "\n";
-
- $tmpl = "mysql -u%s -p%s -h%s -P%s -D%s < %s";
- system(sprintf($tmpl, $dbUser, $dbPWD, $dbHost, $dbPort, $dbName, $sqlPath));
- return;
- }
-
system($execDump);
- system($execYaml);
+ $stderr = '';
+ $this->exec_with_stderr($execYaml, $stderr);
+
+ if(empty($stderr)) return;
+
+ $errors = explode(PHP_EOL, $stderr);
+ $errors = array_filter($errors, function($error)
+ {
+ return !empty($error) && !strpos($error, 'Using a password on the command line interface can be insecure');
+ });
+
+ if(!empty($errors)) echo implode(PHP_EOL, $errors) . PHP_EOL;
+ }
+
+ /**
+ * 执行系统命令,并捕捉stderror
+ * exec command and catch stderror.
+ *
+ * @param string $cmd
+ * @param string $stderr
+ * @access private
+ * @return string
+ */
+ private function exec_with_stderr($cmd, &$stderr=null)
+ {
+ $proc = proc_open($cmd, array(2 => array('pipe', 'w')), $pipes);
+ $stderr = stream_get_contents($pipes[2]);
+
+ fclose($pipes[2]);
+ proc_close($proc);
}
/**
diff --git a/test/ztest b/test/ztest
index 3eed4e26e7..0afbeb0b5c 100755
--- a/test/ztest
+++ b/test/ztest
@@ -25,6 +25,9 @@ else
case 'init':
zdRun();
break;
+ case 'devdata':
+ zdRun(true);
+ break;
case 'copyDB':
copyDB();
break;
diff --git a/zin/core/h.class.php b/zin/core/h.class.php
index 1b57303928..967a6a0db2 100644
--- a/zin/core/h.class.php
+++ b/zin/core/h.class.php
@@ -100,6 +100,13 @@ class h extends wg
return new h(prop('tagName', $tagName), $args);
}
+ public static function a()
+ {
+ $a = static::create('a', func_get_args());
+ if($a->prop('target') === '_blank' && !$a->hasProp('rel')) $a->prop('rel', 'noopener noreferrer');
+ return $a;
+ }
+
public static function button()
{
return static::create('button', prop('type', 'button'), func_get_args());
diff --git a/zin/wg/select/v1.php b/zin/wg/select/v1.php
index c86f98fd39..27edc3fe96 100644
--- a/zin/wg/select/v1.php
+++ b/zin/wg/select/v1.php
@@ -35,13 +35,7 @@ class select extends wg
public function isMultiple()
{
- $multiple = $this->prop('multiple');
- if($multiple === NULL)
- {
- $name = $this->prop('name');
- $multiple = str_contains($name, '[');
- }
- return $multiple;
+ return $this->prop('multiple');
}
public function getValueList()