Merge branch release/21.7.2 of zentao/zentaopms (#9729)
This commit is contained in:
@@ -64,7 +64,7 @@ spec:
|
||||
content: |-
|
||||
代码库: {{ .GITFOX_REPO_NAME }}
|
||||
|
||||
新版本: {{ .GITFOX_TAG }}
|
||||
新版本: {{ .GITFOX_TAG }}
|
||||
|
||||
旧版本: {{ .PREVIOUS_TAG }}
|
||||
|
||||
@@ -76,4 +76,4 @@ spec:
|
||||
# "0": "qishiyao"
|
||||
groups:
|
||||
"0": "38a4e39b-df5d-4606-a988-e22673bdc358"
|
||||
name: gitfox-xuanim-plugin
|
||||
name: gitfox-xuanim-plugin
|
||||
|
||||
@@ -91,6 +91,7 @@ zentaoxx:
|
||||
cp -r xuan/xxb/module/client zentaoxx/extension/xuan/
|
||||
cp -r xuan/xxb/module/conference zentaoxx/extension/xuan/
|
||||
cp -r xuan/xxb/module/watermark zentaoxx/extension/xuan/
|
||||
cp -r xuan/xxb/module/log zentaoxx/extension/xuan/
|
||||
cp -r xuan/xxb/module/integration zentaoxx/extension/xuan/
|
||||
mkdir -p zentaoxx/extension/xuan/common/view
|
||||
cp -r xuan/xxb/module/common/view/header.modal.html.php zentaoxx/extension/xuan/common/view
|
||||
|
||||
@@ -79,6 +79,7 @@ $filter->projectplan = new stdclass();
|
||||
$filter->kanban = new stdclass();
|
||||
$filter->group = new stdclass();
|
||||
$filter->convert = new stdclass();
|
||||
$filter->admin = new stdclass();
|
||||
|
||||
$filter->index->index = new stdclass();
|
||||
$filter->block->default = new stdclass();
|
||||
@@ -205,6 +206,9 @@ $filter->caselib->default = new stdclass();
|
||||
$filter->requirement->batchchangeparent = new stdclass();
|
||||
$filter->requirement->export = new stdclass();
|
||||
$filter->convert->mapjira2zentao = new stdclass();
|
||||
$filter->admin->register = new stdclass();
|
||||
$filter->admin->getcaptcha = new stdclass();
|
||||
$filter->admin->sendcode = new stdclass();
|
||||
|
||||
$filter->index->index->get['open'] = 'reg::base64';
|
||||
|
||||
@@ -538,3 +542,7 @@ $filter->bug->ajaxgetproductbugs->get['limit'] = 'int';
|
||||
|
||||
$filter->convert->mapjira2zentao->cookie['stepStatus'] = 'reg::any';
|
||||
$filter->convert->mapjira2zentao->cookie['jiraRelation'] = 'reg::any';
|
||||
|
||||
$filter->admin->register->cookie['zentaosid'] = 'reg::any';
|
||||
$filter->admin->getcaptcha->cookie['zentaosid'] = 'reg::any';
|
||||
$filter->admin->sendcode->cookie['zentaosid'] = 'reg::any';
|
||||
@@ -223,6 +223,10 @@ $config->openMethods[] = 'user.login';
|
||||
$config->openMethods[] = 'user.refreshrandom';
|
||||
$config->openMethods[] = 'user.reset';
|
||||
$config->openMethods[] = 'user.resetpassword';
|
||||
$config->openMethods[] = 'admin.register';
|
||||
$config->openMethods[] = 'admin.getcaptcha';
|
||||
$config->openMethods[] = 'admin.sendcode';
|
||||
$config->openMethods[] = 'admin.planmodal';
|
||||
|
||||
/* 登录用户可以使用的方法。The methods that can be used by the logged users. */
|
||||
$config->logonMethods = array();
|
||||
@@ -669,6 +673,7 @@ $config->objectTables['api'] = TABLE_API;
|
||||
$config->objectTables['doc'] = TABLE_DOC;
|
||||
$config->objectTables['doclib'] = TABLE_DOCLIB;
|
||||
$config->objectTables['docspace'] = TABLE_DOCLIB;
|
||||
$config->objectTables['doctemplate'] = TABLE_DOC;
|
||||
$config->objectTables['demand'] = TABLE_DEMAND;
|
||||
$config->objectTables['demandpool'] = TABLE_DEMANDPOOL;
|
||||
$config->objectTables['demandspec'] = TABLE_DEMANDSPEC;
|
||||
|
||||
+6
-1
@@ -13,6 +13,11 @@ UPDATE `zt_workflowgroup` SET `name` = '瀑布式项目研发' WHERE `code` = 'w
|
||||
UPDATE `zt_workflowgroup` SET `name` = '敏捷式产品研发' WHERE `code` = 'scrumproduct';
|
||||
UPDATE `zt_workflowgroup` SET `name` = '敏捷式项目研发' WHERE `code` = 'scrumproject';
|
||||
|
||||
|
||||
CREATE OR REPLACE VIEW `ztv_projectnotpl` AS SELECT * FROM `zt_project` WHERE `deleted` = '0' AND `isTpl` = 0;
|
||||
CREATE OR REPLACE VIEW `ztv_tasknotpl` AS SELECT * FROM `zt_task` WHERE `deleted` = '0' AND `isTpl` = 0;
|
||||
|
||||
ALTER TABLE `zt_compile` ADD `branch` varchar(255) NOT NULL DEFAULT '' AFTER `status`;
|
||||
|
||||
ALTER TABLE `zt_doc`
|
||||
ADD `templateDesc` text NULL AFTER `templateType`,
|
||||
ADD `builtIn` enum('0','1') NOT NULL DEFAULT '0' AFTER `version`;
|
||||
|
||||
+17
-13
@@ -636,6 +636,7 @@ CREATE TABLE IF NOT EXISTS `zt_compile` (
|
||||
`job` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`queue` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`status` varchar(100) NOT NULL DEFAULT '',
|
||||
`branch` varchar(255) NOT NULL DEFAULT '',
|
||||
`logs` longtext NULL,
|
||||
`atTime` varchar(10) NOT NULL DEFAULT '',
|
||||
`testtask` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
@@ -797,6 +798,7 @@ CREATE TABLE IF NOT EXISTS `zt_doc` (
|
||||
`lib` varchar(30) NOT NULL DEFAULT '',
|
||||
`template` varchar(30) NOT NULL DEFAULT '',
|
||||
`templateType` varchar(30) NOT NULL DEFAULT '',
|
||||
`templateDesc` text NULL,
|
||||
`chapterType` varchar(30) NOT NULL DEFAULT '',
|
||||
`module` varchar(30) NOT NULL DEFAULT '',
|
||||
`title` varchar(255) NOT NULL DEFAULT '',
|
||||
@@ -830,6 +832,7 @@ CREATE TABLE IF NOT EXISTS `zt_doc` (
|
||||
`readGroups` varchar(255) NOT NULL DEFAULT '',
|
||||
`readUsers` text NULL,
|
||||
`version` smallint(6) unsigned NOT NULL DEFAULT '1',
|
||||
`builtIn` enum('0','1') NOT NULL DEFAULT '0',
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
@@ -1291,7 +1294,7 @@ CREATE TABLE IF NOT EXISTS `zt_module` (
|
||||
`from` mediumint(8) unsigned NOT NULL default '0',
|
||||
`owner` varchar(30) NOT NULL DEFAULT '',
|
||||
`collector` text NULL,
|
||||
`short` varchar(30) NOT NULL DEFAULT '',
|
||||
`short` varchar(60) NOT NULL DEFAULT '',
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
@@ -13668,7 +13671,7 @@ CREATE VIEW `view_datasource_12` AS select `id`,`title` from `zt_productplan` wh
|
||||
CREATE VIEW `view_datasource_41` AS select `id`,`title` from `zt_case` where `deleted` = '0';
|
||||
CREATE VIEW `view_datasource_54` AS select `id`,`name` from `zt_task` where `deleted` = '0' and vision = 'lite';
|
||||
CREATE VIEW `view_datasource_55` AS select `id`,`title` from `zt_feedback` where `deleted` = '0';
|
||||
CREATE VIEW `ztv_projectnotpl` AS select * from `zt_project` where `deleted` = '0' and `isTpl` = 0;
|
||||
CREATE VIEW `ztv_projectnotpl` AS select * from `zt_project` where `deleted` = '0' and `isTpl` = 0;
|
||||
CREATE VIEW `ztv_tasknotpl` AS select * from `zt_task` where `deleted` = '0' and `isTpl` = 0;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_durationestimation`;
|
||||
@@ -16177,17 +16180,16 @@ CREATE TABLE IF NOT EXISTS `zt_metric` (
|
||||
-- DROP TABLE IF EXISTS `zt_metriclib`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_metriclib` (
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||
`metricID` mediumint NOT NULL DEFAULT 0,
|
||||
`metricCode` varchar(100) NOT NULL DEFAULT '',
|
||||
`system` char(30) NOT NULL DEFAULT '0',
|
||||
`program` char(30) NOT NULL DEFAULT '',
|
||||
`project` char(30) NOT NULL DEFAULT '',
|
||||
`product` char(30) NOT NULL DEFAULT '',
|
||||
`execution` char(30) NOT NULL DEFAULT '',
|
||||
`system` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`program` int(11) NOT NULL DEFAULT '0',
|
||||
`project` int(11) NOT NULL DEFAULT '0',
|
||||
`product` int(11) NOT NULL DEFAULT '0',
|
||||
`execution` int(11) NOT NULL DEFAULT '0',
|
||||
`code` char(30) NOT NULL DEFAULT '',
|
||||
`pipeline` char(30) NOT NULL DEFAULT '',
|
||||
`repo` char(30) NOT NULL DEFAULT '',
|
||||
`user` text,
|
||||
`user` varchar(30) NOT NULL DEFAULT '',
|
||||
`dept` char(30) NOT NULL DEFAULT '',
|
||||
`year` char(4) NOT NULL DEFAULT '0',
|
||||
`month` char(2) NOT NULL DEFAULT '0',
|
||||
@@ -16200,10 +16202,12 @@ CREATE TABLE IF NOT EXISTS `zt_metriclib` (
|
||||
`deleted` ENUM('0', '1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
CREATE INDEX `metricID` ON `zt_metriclib`(`metricID`);
|
||||
CREATE INDEX `metricCode` ON `zt_metriclib`(`metricCode`);
|
||||
CREATE INDEX `date` ON zt_metriclib (date);
|
||||
CREATE INDEX `deleted` ON `zt_metriclib` (`deleted`);
|
||||
CREATE INDEX `metricCode_system_date` ON `zt_metriclib`(`metricCode`, `system`, `date`);
|
||||
CREATE INDEX `metricCode_program_date` ON `zt_metriclib`(`metricCode`, `program`, `date`);
|
||||
CREATE INDEX `metricCode_project_date` ON `zt_metriclib`(`metricCode`, `project`, `date`);
|
||||
CREATE INDEX `metricCode_product_date` ON `zt_metriclib`(`metricCode`, `product`, `date`);
|
||||
CREATE INDEX `metricCode_execution_date` ON `zt_metriclib`(`metricCode`, `execution`, `date`);
|
||||
CREATE INDEX `metricCode_user_date` ON `zt_metriclib`(`metricCode`, `user`, `date`);
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_duckdbqueue`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_duckdbqueue` (
|
||||
|
||||
@@ -146,6 +146,13 @@ $lang->doc->menuOrder[15] = 'my';
|
||||
$lang->doc->menuOrder[20] = 'custom';
|
||||
$lang->doc->menuOrder[25] = 'project';
|
||||
|
||||
if(strpos(',max,ipd,', $config->edition) !== false)
|
||||
{
|
||||
$lang->doc->menu->template = array('link' => "模板广场|doc|browseTemplate|", 'alias' => 'browsetemplate');
|
||||
$lang->doc->menuOrder[30] = 'template';
|
||||
$lang->doc->dividerMenu .= ',template,';
|
||||
}
|
||||
|
||||
/* Admin menu. */
|
||||
$lang->admin->menu = new stdclass();
|
||||
|
||||
|
||||
@@ -570,31 +570,41 @@ $lang->task->methodOrder[125] = 'import';
|
||||
|
||||
/* Doc. */
|
||||
$lang->resource->doc = new stdclass();
|
||||
$lang->resource->doc->index = 'index';
|
||||
$lang->resource->doc->mySpace = 'mySpace';
|
||||
$lang->resource->doc->quick = 'quick';
|
||||
$lang->resource->doc->createSpace = 'createSpace';
|
||||
$lang->resource->doc->createLib = 'createLibAction';
|
||||
$lang->resource->doc->editLib = 'editLibAction';
|
||||
$lang->resource->doc->deleteLib = 'deleteLibAction';
|
||||
$lang->resource->doc->moveLib = 'moveLibAction';
|
||||
$lang->resource->doc->moveDoc = 'moveDocAction';
|
||||
$lang->resource->doc->create = 'create';
|
||||
$lang->resource->doc->view = 'view';
|
||||
$lang->resource->doc->edit = 'edit';
|
||||
$lang->resource->doc->delete = 'delete';
|
||||
$lang->resource->doc->deleteFile = 'deleteFile';
|
||||
$lang->resource->doc->collect = 'collectAction';
|
||||
$lang->resource->doc->projectSpace = 'projectSpace';
|
||||
$lang->resource->doc->teamSpace = 'teamSpace';
|
||||
$lang->resource->doc->showFiles = 'showFiles';
|
||||
$lang->resource->doc->addCatalog = 'addCatalog';
|
||||
$lang->resource->doc->editCatalog = 'editCatalog';
|
||||
$lang->resource->doc->sortDoclib = 'sortDoclib';
|
||||
$lang->resource->doc->sortCatalog = 'sortCatalog';
|
||||
$lang->resource->doc->sortDoc = 'sortDoc';
|
||||
$lang->resource->doc->deleteCatalog = 'deleteCatalog';
|
||||
// $lang->resource->doc->displaySetting = 'displaySetting';
|
||||
$lang->resource->doc->index = 'index';
|
||||
$lang->resource->doc->mySpace = 'mySpace';
|
||||
$lang->resource->doc->quick = 'quick';
|
||||
$lang->resource->doc->createSpace = 'createSpace';
|
||||
$lang->resource->doc->createLib = 'createLibAction';
|
||||
$lang->resource->doc->editLib = 'editLibAction';
|
||||
$lang->resource->doc->deleteLib = 'deleteLibAction';
|
||||
$lang->resource->doc->moveLib = 'moveLibAction';
|
||||
$lang->resource->doc->moveDoc = 'moveDocAction';
|
||||
$lang->resource->doc->create = 'create';
|
||||
$lang->resource->doc->view = 'view';
|
||||
$lang->resource->doc->edit = 'edit';
|
||||
$lang->resource->doc->delete = 'delete';
|
||||
$lang->resource->doc->deleteFile = 'deleteFile';
|
||||
$lang->resource->doc->collect = 'collectAction';
|
||||
$lang->resource->doc->projectSpace = 'projectSpace';
|
||||
$lang->resource->doc->teamSpace = 'teamSpace';
|
||||
$lang->resource->doc->showFiles = 'showFiles';
|
||||
$lang->resource->doc->addCatalog = 'addCatalog';
|
||||
$lang->resource->doc->editCatalog = 'editCatalog';
|
||||
$lang->resource->doc->sortDoclib = 'sortDoclib';
|
||||
$lang->resource->doc->sortCatalog = 'sortCatalog';
|
||||
$lang->resource->doc->sortDoc = 'sortDoc';
|
||||
$lang->resource->doc->deleteCatalog = 'deleteCatalog';
|
||||
$lang->resource->doc->browseTemplate = 'browseTemplate';
|
||||
$lang->resource->doc->createTemplate = 'createTemplate';
|
||||
$lang->resource->doc->editTemplate = 'editTemplate';
|
||||
$lang->resource->doc->moveTemplate = 'moveTemplate';
|
||||
$lang->resource->doc->sortTemplate = 'sortTemplate';
|
||||
$lang->resource->doc->deleteTemplate = 'deleteTemplate';
|
||||
$lang->resource->doc->viewTemplate = 'viewTemplate';
|
||||
$lang->resource->doc->addTemplateType = 'addTemplateType';
|
||||
$lang->resource->doc->editTemplateType = 'editTemplateType';
|
||||
$lang->resource->doc->deleteTemplateType = 'deleteTemplateType';
|
||||
$lang->resource->doc->manageScope = 'manageScope';
|
||||
|
||||
$lang->doc->methodOrder[5] = 'index';
|
||||
$lang->doc->methodOrder[10] = 'mySpace';
|
||||
|
||||
@@ -38,6 +38,7 @@ if(count($teams2Import) > 1)
|
||||
set::value($copyProjectID),
|
||||
set::items($teams2Import),
|
||||
set('data-placeholder', $lang->project->copyTeamTitle),
|
||||
set::width('200px'),
|
||||
on::change('choseTeam2Copy')
|
||||
)
|
||||
);
|
||||
@@ -61,6 +62,7 @@ featureBar
|
||||
set::name('dept'),
|
||||
set::value($dept),
|
||||
set::items($depts),
|
||||
set::width('200px'),
|
||||
set('data-placeholder', $lang->execution->selectDeptTitle),
|
||||
on::change('setDeptUsers')
|
||||
),
|
||||
|
||||
@@ -996,7 +996,7 @@ class baseDAO
|
||||
* @access public
|
||||
* @return string the sql string.
|
||||
*/
|
||||
static public function processKeywords($sql)
|
||||
public static function processKeywords($sql)
|
||||
{
|
||||
return str_replace(array(DAO::WHERE, DAO::GROUPBY, DAO::HAVING, DAO::ORDERBY, DAO::LIMIT), array('WHERE', 'GROUP BY', 'HAVING', 'ORDER BY', 'LIMIT'), $sql);
|
||||
}
|
||||
|
||||
@@ -212,11 +212,13 @@ class dao extends baseDAO
|
||||
/**
|
||||
* Check workFlow field rule.
|
||||
*
|
||||
* @param bool $skip true|false
|
||||
* @access public
|
||||
* @return object the dao object self.
|
||||
*/
|
||||
public function checkFlow()
|
||||
public function checkFlow($skip = false)
|
||||
{
|
||||
if($skip) return $this;
|
||||
if(!isset($this->config->bizVersion)) return $this;
|
||||
|
||||
$module = $this->app->getModuleName();
|
||||
|
||||
@@ -570,7 +570,7 @@ class sqlparser
|
||||
$tables = array();
|
||||
$tables[] = $this->parseTable($from, 'from');
|
||||
|
||||
foreach($joins as $join) $tables[] = $this->parseTable($join->expr, 'join');
|
||||
if(!empty($joins)) foreach($joins as $join) $tables[] = $this->parseTable($join->expr, 'join');
|
||||
|
||||
return $tables;
|
||||
}
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* ubb2html support for php
|
||||
* @requires xhEditor
|
||||
*
|
||||
* @author Yanis.Wang<yanis.wang@gmail.com>
|
||||
* @site http://xheditor.com/
|
||||
* @licence LGPL(http://www.opensource.org/licenses/lgpl-license.php)
|
||||
*
|
||||
* @Version: 0.9.8 (build 100505)
|
||||
*/
|
||||
class ubb
|
||||
{
|
||||
public static function parseUBB($sUBB)
|
||||
{
|
||||
$sHtml=$sUBB;
|
||||
|
||||
global $emotPath,$cnum,$arrcode,$bUbb2htmlFunctionInit;$cnum=0;$arrcode=array();
|
||||
$emotPath='../xheditor_emot/';
|
||||
|
||||
if(!$bUbb2htmlFunctionInit)
|
||||
{
|
||||
function saveCodeArea($match)
|
||||
{
|
||||
global $cnum,$arrcode;
|
||||
$cnum++;$arrcode[$cnum]=$match[0];
|
||||
return "[\tubbcodeplace_".$cnum."\t]";
|
||||
}
|
||||
}
|
||||
|
||||
$sHtml=preg_replace_callback('/\[code\s*(?:=\s*((?:(?!")[\s\S])+?)(?:"[\s\S]*?)?)?\]([\s\S]*?)\[\/code\]/i','saveCodeArea',$sHtml);
|
||||
|
||||
//$sHtml=preg_replace("/&/",'&',$sHtml);
|
||||
//$sHtml=preg_replace("/</",'<',$sHtml);
|
||||
//$sHtml=preg_replace("/>/",'>',$sHtml);
|
||||
$sHtml=preg_replace("/\r?\n/",'<br />',$sHtml);
|
||||
|
||||
$sHtml=preg_replace("/\[(\/?)(b|u|i|s|sup|sub)\]/i",'<$1$2>',$sHtml);
|
||||
$sHtml=preg_replace('/\[color\s*=\s*([^\]"]+?)(?:"[^\]]*?)?\s*\]/i','<span style="color:$1;">',$sHtml);
|
||||
if(!$bUbb2htmlFunctionInit)
|
||||
{
|
||||
function getSizeName($match)
|
||||
{
|
||||
$arrSize=array('8pt','10pt','12pt','14pt','18pt','24pt','36pt');
|
||||
return '<span style="font-size:'.$arrSize[$match[1]-1].';">';
|
||||
}
|
||||
}
|
||||
$sHtml=preg_replace_callback("/\[size\s*=\s*(\d+?)\s*\]/i",'getSizeName',$sHtml);
|
||||
$sHtml=preg_replace('/\[font\s*=\s*([^\]"]+?)(?:"[^\]]*?)?\s*\]/i','<span style="font-family:$1;">',$sHtml);
|
||||
$sHtml=preg_replace('/\[back\s*=\s*([^\]"]+?)(?:"[^\]]*?)?\s*\]/i','<span style="background-color:$1;">',$sHtml);
|
||||
$sHtml=preg_replace("/\[\/(color|size|font|back)\]/i",'</span>',$sHtml);
|
||||
|
||||
for($i=0;$i<3;$i++)$sHtml=preg_replace('/\[align\s*=\s*([^\]"]+?)(?:"[^\]]*?)?\s*\](((?!\[align(?:\s+[^\]]+)?\])[\s\S])*?)\[\/align\]/','<p align="$1">$2</p>',$sHtml);
|
||||
$sHtml=preg_replace('/\[img\]\s*(((?!")[\s\S])+?)(?:"[\s\S]*?)?\s*\[\/img\]/i','<img src="$1" alt="" />',$sHtml);
|
||||
if(!$bUbb2htmlFunctionInit)
|
||||
{
|
||||
function getImg($match)
|
||||
{
|
||||
$alt=$match[1];$p1=$match[2];$p2=$match[3];$p3=$match[4];$src=$match[5];
|
||||
$a=$p3?$p3:(!is_numeric($p1)?$p1:'');
|
||||
return '<img src="'.$src.'" alt="'.$alt.'"'.(is_numeric($p1)?' width="'.$p1.'"':'').(is_numeric($p2)?' height="'.$p2.'"':'').($a?' align="'.$a.'"':'').' />';
|
||||
}
|
||||
}
|
||||
|
||||
$sHtml=preg_replace_callback('/\[img\s*=([^,\]]*)(?:\s*,\s*(\d*%?)\s*,\s*(\d*%?)\s*)?(?:,?\s*(\w+))?\s*\]\s*(((?!")[\s\S])+?)(?:"[\s\S]*)?\s*\[\/img\]/i','getImg',$sHtml);
|
||||
if(!$bUbb2htmlFunctionInit)
|
||||
{
|
||||
function getEmot($match)
|
||||
{
|
||||
global $emotPath;
|
||||
$arr=preg_split('/,/',$match[1]);
|
||||
if(!isset($arr[1])){$arr[1]=$arr[0];$arr[0]='default';}
|
||||
$path=$emotPath.$arr[0].'/'.$arr[1].'.gif';
|
||||
return '<img src="'.$path.'" alt="'.$arr[1].'" />';
|
||||
}
|
||||
}
|
||||
|
||||
$sHtml=preg_replace_callback('/\[emot\s*=\s*([^\]"]+?)(?:"[^\]]*?)?\s*\/\]/i','getEmot',$sHtml);
|
||||
$sHtml=preg_replace('/\[url\]\s*(((?!")[\s\S])*?)(?:"[\s\S]*?)?\s*\[\/url\]/i','<a href="$1">$1</a>',$sHtml);
|
||||
$sHtml=preg_replace('/\[url\s*=\s*([^\]"]+?)(?:"[^\]]*?)?\s*\]\s*([\s\S]*?)\s*\[\/url\]/i','<a href="$1">$2</a>',$sHtml);
|
||||
$sHtml=preg_replace('/\[email\]\s*(((?!")[\s\S])+?)(?:"[\s\S]*?)?\s*\[\/email\]/i','<a href="mailto:$1">$1</a>',$sHtml);
|
||||
$sHtml=preg_replace('/\[email\s*=\s*([^\]"]+?)(?:"[^\]]*?)?\s*\]\s*([\s\S]+?)\s*\[\/email\]/i','<a href="mailto:$1">$2</a>',$sHtml);
|
||||
$sHtml=preg_replace("/\[quote\]([\s\S]*?)\[\/quote\]/i",'<blockquote>$1</blockquote>',$sHtml);
|
||||
if(!$bUbb2htmlFunctionInit)
|
||||
{
|
||||
function getFlash($match)
|
||||
{
|
||||
$w=$match[1];$h=$match[2];$url=$match[3];
|
||||
if(!$w)$w=480;if(!$h)$h=400;
|
||||
return '<embed type="application/x-shockwave-flash" src="'.$url.'" wmode="opaque" quality="high" bgcolor="#ffffff" menu="false" play="true" loop="true" width="'.$w.'" height="'.$h.'" />';
|
||||
}
|
||||
}
|
||||
$sHtml=preg_replace_callback('/\[flash\s*(?:=\s*(\d+)\s*,\s*(\d+)\s*)?\]\s*(((?!")[\s\S])+?)(?:"[\s\S]*?)?\s*\[\/flash\]/i','getFlash',$sHtml);
|
||||
if(!$bUbb2htmlFunctionInit)
|
||||
{
|
||||
function getMedia($match)
|
||||
{
|
||||
$w=$match[1];$h=$match[2];$play=$match[3];$url=$match[4];
|
||||
if(!$w)$w=480;if(!$h)$h=400;
|
||||
return '<embed type="application/x-mplayer2" src="'.$url.'" enablecontextmenu="false" autostart="'.($play=='1'?'true':'false').'" width="'.$w.'" height="'.$h.'" />';
|
||||
}
|
||||
}
|
||||
$sHtml=preg_replace_callback('/\[media\s*(?:=\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d+)\s*)?)?\]\s*(((?!")[\s\S])+?)(?:"[\s\S]*?)?\s*\[\/media\]/i','getMedia',$sHtml);
|
||||
if(!$bUbb2htmlFunctionInit)
|
||||
{
|
||||
function getTable($match)
|
||||
{
|
||||
return '<table'.(isset($match[1])?' width="'.$match[1].'"':'').(isset($match[2])?' bgcolor="'.$match[2].'"':'').'>';
|
||||
}
|
||||
}
|
||||
$sHtml=preg_replace_callback('/\[table\s*(?:=(\d{1,4}%?)\s*(?:,\s*([^\]"]+)(?:"[^\]]*?)?)?)?\s*\]/i','getTable',$sHtml);
|
||||
if(!$bUbb2htmlFunctionInit)
|
||||
{
|
||||
function getTR($match){return '<tr'.(isset($match[1])?' bgcolor="'.$match[1].'"':'').'>';}
|
||||
}
|
||||
$sHtml=preg_replace_callback('/\[tr\s*(?:=(\s*[^\]"]+))?(?:"[^\]]*?)?\s*\]/i','getTR',$sHtml);
|
||||
if(!$bUbb2htmlFunctionInit)
|
||||
{
|
||||
function getTD($match)
|
||||
{
|
||||
$col=isset($match[1])?$match[1]:0;$row=isset($match[2])?$match[2]:0;$w=isset($match[3])?$match[3]:null;
|
||||
return '<td'.($col>1?' colspan="'.$col.'"':'').($row>1?' rowspan="'.$row.'"':'').($w?' width="'.$w.'"':'').'>';
|
||||
}
|
||||
}
|
||||
$sHtml=preg_replace_callback("/\[td\s*(?:=\s*(\d{1,2})\s*,\s*(\d{1,2})\s*(?:,\s*(\d{1,4}%?))?)?\s*\]/i",'getTD',$sHtml);
|
||||
$sHtml=preg_replace("/\[\/(table|tr|td)\]/i",'</$1>',$sHtml);
|
||||
$sHtml=preg_replace("/\[\*\]((?:(?!\[\*\]|\[\/list\]|\[list\s*(?:=[^\]]+)?\])[\s\S])+)/i",'<li>$1</li>',$sHtml);
|
||||
if(!$bUbb2htmlFunctionInit)
|
||||
{
|
||||
function getUL($match)
|
||||
{
|
||||
$str='<ul';
|
||||
if(isset($match[1]))$str.=' type="'.$match[1].'"';
|
||||
return $str.'>';
|
||||
}
|
||||
}
|
||||
$sHtml=preg_replace_callback('/\[list\s*(?:=\s*([^\]"]+))?(?:"[^\]]*?)?\s*\]/i','getUL',$sHtml);
|
||||
$sHtml=preg_replace("/\[\/list\]/i",'</ul>',$sHtml);
|
||||
|
||||
for($i=1;$i<=$cnum;$i++)$sHtml=str_replace("[\tubbcodeplace_".$i."\t]", $arrcode[$i],$sHtml);
|
||||
|
||||
if(!$bUbb2htmlFunctionInit)
|
||||
{
|
||||
function fixText($match)
|
||||
{
|
||||
$text=$match[2];
|
||||
$text=preg_replace("/\t/",' ',$text);
|
||||
$text=preg_replace("/ /",' ',$text);
|
||||
return $match[1].$text;
|
||||
}
|
||||
}
|
||||
$sHtml=preg_replace_callback('/(^|<\/?\w+(?:\s+[^>]*?)?>)([^<$]+)/i','fixText',$sHtml);
|
||||
|
||||
$bUbb2htmlFunctionInit=true;
|
||||
|
||||
return $sHtml;
|
||||
}
|
||||
}
|
||||
+49
-19
@@ -13,6 +13,7 @@ window.setZentaoSlashMenu = function(menus, title, vision, position)
|
||||
{
|
||||
if(vision == 'or' || vision == 'lite') return;
|
||||
if(!menus?.length) return;
|
||||
|
||||
const slashMenus = menus.map(menu =>
|
||||
{
|
||||
if(menu.subMenu)
|
||||
@@ -20,7 +21,7 @@ window.setZentaoSlashMenu = function(menus, title, vision, position)
|
||||
menu.subMenu = menu.subMenu.map(subMenu => {
|
||||
subMenu.action = function (context) {
|
||||
zui.Modal.open({
|
||||
size: 'lg',
|
||||
size: subMenu.modalSize ? subMenu.modalSize : 'lg',
|
||||
url: $.createLink(subMenu.module, subMenu.method, subMenu.params)
|
||||
});
|
||||
}
|
||||
@@ -29,11 +30,24 @@ window.setZentaoSlashMenu = function(menus, title, vision, position)
|
||||
}
|
||||
else
|
||||
{
|
||||
menu.action = function (context) {
|
||||
zui.Modal.open({
|
||||
size: 'lg',
|
||||
url: $.createLink(menu.module, menu.method, menu.params)
|
||||
});
|
||||
if(menu.key == 'gantt' && !menu.isModal)
|
||||
{
|
||||
menu.action = function (context) {
|
||||
const doc = getDocApp().doc;
|
||||
$.ajaxSubmit({
|
||||
url: $.createLink(menu.module, menu.method, menu.params),
|
||||
data: {templateID: doc.data.id}
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
menu.action = function (context) {
|
||||
zui.Modal.open({
|
||||
size: menu.modalSize ? menu.modalSize : 'lg',
|
||||
url: $.createLink(menu.module, menu.method, menu.params)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return menu;
|
||||
@@ -48,6 +62,8 @@ window.setZentaoSlashMenu = function(menus, title, vision, position)
|
||||
/* 获取 ZentaoList 块属性。 */
|
||||
function getZentaoListProps(type, blockID, props)
|
||||
{
|
||||
if(props && props.isTemplate) blockID = '__TML_ZENTAOLIST__' + blockID;
|
||||
|
||||
const zentaoListLang = getLang('zentaoList');
|
||||
const exportUrl = $.createLink('doc', 'ajaxExportZentaoList', `blockID=${blockID}`);
|
||||
return $.extend(
|
||||
@@ -103,7 +119,7 @@ window.reloadZentaoList = function(blockID)
|
||||
*
|
||||
* @returns {object}
|
||||
*/
|
||||
function getDocApp()
|
||||
window.getDocApp = function()
|
||||
{
|
||||
if(!currentDocApp)
|
||||
{
|
||||
@@ -144,7 +160,7 @@ window.getLang = function(key, args)
|
||||
* Check if the specified privilege exists, privileges are defined in $privs in module/doc/ui/app.html.php.
|
||||
* @param {string} priv
|
||||
*/
|
||||
function hasPriv(priv, value)
|
||||
window.hasPriv = function(priv, value)
|
||||
{
|
||||
const setting = userPrivs[priv];
|
||||
return value !== undefined ? setting === value : !!setting;
|
||||
@@ -216,7 +232,7 @@ function processDocAppAction(action, docApp)
|
||||
*
|
||||
* @param {object|number} space
|
||||
*/
|
||||
function canModifySpace(space)
|
||||
window.canModifySpace = function(space)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
if(!docApp && !space) return false;
|
||||
@@ -395,7 +411,7 @@ function mergeDocFormData(doc, formData)
|
||||
return doc;
|
||||
}
|
||||
|
||||
function showSaveFailedAlert(error)
|
||||
window.showSaveFailedAlert = function(error)
|
||||
{
|
||||
zui.Modal.alert(
|
||||
{
|
||||
@@ -444,6 +460,7 @@ function submitNewDoc(doc, spaceID, libID, moduleID, formData, afterCreate)
|
||||
acl : 'private',
|
||||
space : spaceType,
|
||||
uid : (doc.uid || `doc${doc.id}`),
|
||||
template : doc.template
|
||||
};
|
||||
if(formData) mergeDocFormData(docData, formData);
|
||||
const getErrorMessage = (res) => {
|
||||
@@ -817,6 +834,7 @@ const actionsMap =
|
||||
const doc = info.data;
|
||||
const canModify = canModifySpace();
|
||||
const isApi = isApiDoc(doc);
|
||||
const isTemplate = doc.templateType !== '';
|
||||
const canEditDoc = canModify && hasPriv(isApi ? 'editApi' : 'edit');
|
||||
const isChapter = doc.type === 'chapter';
|
||||
|
||||
@@ -828,7 +846,7 @@ const actionsMap =
|
||||
[
|
||||
hasPriv('addChapter') ? {icon: 'plus', text: lang.addSubChapter, command: `addChapter/${doc.id}`} : null,
|
||||
hasPriv('addChapter') && doc.parent != 0 ? {icon: 'plus', text: lang.addSameChapter, command: `addChapter/${doc.parent}`} : null,
|
||||
hasPriv('create') ? {icon: 'plus', text: lang.addSubDoc, command: `startCreateDoc/${doc.id}`} : null,
|
||||
!isTemplate && hasPriv('create') ? {icon: 'plus', text: lang.addSubDoc, command: `startCreateDoc/${doc.id}`} : null,
|
||||
!isChapter && canMoveDoc(doc) ? {icon: 'folder-move', text: lang.moveDoc, command: `moveDoc/${doc.id}`} : null,
|
||||
!isChapter && hasPriv('delete') ? {icon: 'trash', text: lang.delete, command: `deleteDoc/${doc.id}`} : null,
|
||||
isChapter && hasPriv('editChapter') ? {icon: 'pencil', text: lang.editChapter, command: `editChapter/${doc.id}`} : null,
|
||||
@@ -836,7 +854,7 @@ const actionsMap =
|
||||
];
|
||||
return [
|
||||
(!isChapter && hasPriv('sortDoc')) || (isChapter && hasPriv('sortChapter')) ? {icon: 'move cursor-move', className: 'sort-handler', hint: lang.sortDoc, size: 'xs'} : null,
|
||||
moreItems.length ? {icon: 'ellipsis-v', caret: false, placement: 'bottom-end', size: 'xs', items: moreItems} : null,
|
||||
moreItems.every(item => item === null) ? null : {icon: 'ellipsis-v', caret: false, placement: 'bottom-end', size: 'xs', items: moreItems},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -844,7 +862,7 @@ const actionsMap =
|
||||
if(canModify && canMoveDoc(doc)) moreItems.push({icon: 'folder-move', text: lang.moveDoc, command: `moveDoc/${doc.id}`});
|
||||
if(canModify && hasPriv('delete')) moreItems.push({icon: 'trash', text: lang.delete, command: `deleteDoc/${doc.id}`});
|
||||
if(!isApi && canModify && hasPriv('effort')) moreItems.push({icon: 'time', text: lang.effort, command: `effortDoc/${doc.id}`});
|
||||
if(!isApi)
|
||||
if(!isApi && !isTemplate)
|
||||
{
|
||||
const canExportWord = hasPriv('exportDoc');
|
||||
if(doc.contentType === 'doc' || doc.contentType === 'markdown')
|
||||
@@ -866,7 +884,7 @@ const actionsMap =
|
||||
}
|
||||
const docApp = this;
|
||||
const isOpen = isOpenVersion(config.version);
|
||||
if(!isOpen && docApp && docApp.mode === 'view' && doc.status != 'draft' && !doc.api)
|
||||
if(!isOpen && docApp && docApp.mode === 'view' && doc.status != 'draft' && !doc.api && !isTemplate)
|
||||
{
|
||||
moreItems.push({icon: 'link', text: getLang('relateObject'), className: 'relateObject-btn', command: 'toggleViewSideTab/relateObject'})
|
||||
}
|
||||
@@ -874,7 +892,7 @@ const actionsMap =
|
||||
const isToolbar = info.ui === 'toolbar';
|
||||
const actions = [
|
||||
isToolbar ? {hint: docApp.fullscreen ? lang.exitFullscreen : lang.enterFullscreen, icon: docApp.fullscreen ? 'fullscreen-exit' : 'fullscreen', command: 'toggleFullscreen'} : null,
|
||||
canEditDoc ? {icon: 'edit', type: 'ghost text-primary', hint: lang.edit, rounded: 'lg', command: 'startEditDoc'} : null,
|
||||
canEditDoc ? {icon: 'edit', class: doc.editable ? null : 'disabled', type: doc.editable ? 'ghost text-primary' : 'ghost text-gray', hint: doc.editable ? lang.edit : lang.needEditable, rounded: 'lg', command: doc.editable ? 'startEditDoc' : null} : null,
|
||||
(isToolbar && docApp.props.showDocOutline !== false) ? {hint: lang.docOutline, icon: 'list-box', command: 'toggleViewSideTab/outline'} : null,
|
||||
(isToolbar && docApp.props.showDocHistory !== false) ? {hint: lang.history, icon: 'history', command: 'toggleViewSideTab/history'} : null,
|
||||
moreItems.length ? {icon: 'icon-ellipsis-v', type: 'dropdown', rounded: 'lg', placement: 'bottom-end', caret: false, items: moreItems} : null,
|
||||
@@ -889,10 +907,11 @@ const actionsMap =
|
||||
*/
|
||||
lib: function(info)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
const lang = getLang();
|
||||
const items = [];
|
||||
const lib = info.data;
|
||||
const canModify = canModifySpace();
|
||||
const canModify = canModifySpace() || docApp === null;
|
||||
const canAddModule = canModify && hasPriv('addModule');
|
||||
|
||||
/* 获取侧边栏没有模块时的操作按钮。 Get actions when sidebar no module. */
|
||||
@@ -1176,12 +1195,13 @@ const commands =
|
||||
const {spaceType} = docApp;
|
||||
if(spaceType === 'api' || docType === 'api') return docApp.startCreateDoc();
|
||||
|
||||
const templateID = args?.[1] ?? 0;
|
||||
const {spaceID, libID, moduleID} = docApp;
|
||||
return showDocBasicModal(args?.[0] ?? 0, 0, true, docType).then((formData) => {
|
||||
zui.Editor.loadModule().then(() => {
|
||||
const emptyDoc = zui.Editor.createEmptyDoc();
|
||||
const snapshot = zui.Editor.toSnapshot(emptyDoc);
|
||||
const doc = {contentType: 'doc', status: 'draft', content: JSON.stringify(snapshot)};
|
||||
const doc = {contentType: 'doc', status: 'draft', content: JSON.stringify(snapshot), template: templateID};
|
||||
return submitNewDoc(doc, spaceID, libID, moduleID, formData, (newDoc) => {
|
||||
docApp.selectDoc(newDoc.id);
|
||||
docApp.startEditDoc(newDoc.id);
|
||||
@@ -1886,6 +1906,8 @@ function getTableOptions(options, info)
|
||||
if(col.name === 'actions' && col.actionsMap)
|
||||
{
|
||||
if(!canModify) col.actions = [];
|
||||
col.actions = col.actions.filter(action => hasPriv(action == 'move' ? 'moveDoc' : action));
|
||||
|
||||
const actionHints = {edit: lang.editDoc, move: lang.moveDoc, delete: lang.deleteDoc};
|
||||
const privMap = {edit: hasPriv('edit'), move: hasPriv('moveDoc'), delete: hasPriv('delete')};
|
||||
$.each(col.actionsMap, (key, value) =>
|
||||
@@ -1950,6 +1972,7 @@ function isMatchFilter(type, filterType, item)
|
||||
if(filterType === 'editedByMe') return item.editedBy === currentUser;
|
||||
if(filterType === 'draft') return item.status === 'draft';
|
||||
if(filterType === 'collect') return item.isCollector;
|
||||
if(filterType === 'released') return item.status === 'normal';
|
||||
}
|
||||
if(type === 'project' || type === 'product')
|
||||
{
|
||||
@@ -1967,7 +1990,7 @@ function isMatchFilter(type, filterType, item)
|
||||
*/
|
||||
function formatOrders(orders, useIndex)
|
||||
{
|
||||
const orderedKeys = useIndex ? [] : Array.from(orders).sort();
|
||||
const orderedKeys = useIndex ? [] : Array.from(orders).sort((a, b) => a - b);
|
||||
return orders.reduce((map, key, index) =>
|
||||
{
|
||||
map[key] = useIndex ? index : orderedKeys[index];
|
||||
@@ -2038,13 +2061,20 @@ function getSortableOptions(type)
|
||||
if(fromType !== 'doc') key = key.substring(1);
|
||||
orderedList.push(+key);
|
||||
});
|
||||
if(fromType === 'doc')
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
const doc = docApp.getDoc(orderedList[0]);
|
||||
const lib = doc ? docApp.getLib(doc.lib) : null;
|
||||
if(lib && typeof lib.data.orderBy === 'string' && lib.data.orderBy.endsWith('desc')) orderedList.reverse();
|
||||
}
|
||||
sortItems(fromType, orderedList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkResponse(res)
|
||||
window.checkResponse = function(res)
|
||||
{
|
||||
if(typeof res === 'string') res = JSON.parse(res);
|
||||
if(typeof res !== 'object' || !res) return true;
|
||||
|
||||
@@ -71,7 +71,8 @@ class docApp extends wg
|
||||
'onSwitchView' => '?string', // 切换视图事件。
|
||||
'getDocViewSidebarTabs' => '?string', // 获取文档视图侧边栏选项。
|
||||
'formatDataItem' => '?string', // 格式化数据条目。
|
||||
'viewModeUrl' => '?string' // 应用视图 URL 格式。
|
||||
'viewModeUrl' => '?string', // 应用视图 URL 格式。
|
||||
'hasZentaoSlashMenu' => '?boolean' // 是否显示禅道数据。
|
||||
);
|
||||
|
||||
public static function getPageJS(): ?string
|
||||
@@ -184,6 +185,7 @@ class docApp extends wg
|
||||
$langData->createRelease = $lang->api->createRelease;
|
||||
$langData->libTypeList = $lang->api->libTypeList;
|
||||
$langData->latestVersion = $lang->api->latestVersion;
|
||||
$langData->template = $lang->doc->template;
|
||||
|
||||
/**
|
||||
* 通过语言项定义文档表格列显示名称。
|
||||
@@ -245,6 +247,9 @@ class docApp extends wg
|
||||
}
|
||||
}
|
||||
|
||||
$hasZentaoSlashMenu = $this->prop('hasZentaoSlashMenu');
|
||||
if($hasZentaoSlashMenu === null ) $hasZentaoSlashMenu = true;
|
||||
|
||||
$app->control->loadModel('file');
|
||||
|
||||
$canDownload = common::hasPriv('file', 'download');
|
||||
@@ -317,7 +322,7 @@ class docApp extends wg
|
||||
set::showToolbar(true),
|
||||
set::canPreviewOffice($canPreviewOffice),
|
||||
set::fileInfoUrl($fileInfoUrl),
|
||||
jsCall('setZentaoSlashMenu', $this->getZentaoListMenu(), $lang->doc->zentaoData, $config->vision, $config->doc->zentaoListMenuPosition)
|
||||
$hasZentaoSlashMenu ? jsCall('setZentaoSlashMenu', $this->getZentaoListMenu(), $lang->doc->zentaoData, $config->vision, $config->doc->zentaoListMenuPosition) : null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ class mainNavbar extends nav
|
||||
$badgeMap = $this->prop('badgeMap');
|
||||
$onRenderItem = $this->prop('onRenderItem');
|
||||
$itemProps = $this->prop('itemProps');
|
||||
$activeItem = $this->prop('active');
|
||||
$activeItem = $this->prop('active') ?: data('activeMenuItem');
|
||||
|
||||
foreach($menu as $key => $menuItem)
|
||||
{
|
||||
|
||||
@@ -76,6 +76,7 @@ function createMonaco(id, action, options, diffContent, onMouseDown, onMouseMove
|
||||
if(onMouseDown) editor.onMouseDown(function(obj){eval(onMouseDown + '(obj)')})
|
||||
if(onMouseMove) editor.onMouseMove(function(obj){eval(onMouseMove + '(obj)')})
|
||||
|
||||
let range = null;
|
||||
if(selectedLines)
|
||||
{
|
||||
const lines = selectedLines.split(',');
|
||||
@@ -98,13 +99,22 @@ function createMonaco(id, action, options, diffContent, onMouseDown, onMouseMove
|
||||
});
|
||||
}
|
||||
|
||||
const range = new monaco.Range(startLine, startCol, endLine, endCol);
|
||||
range = new monaco.Range(startLine, startCol, endLine, endCol);
|
||||
programmaticSelectionRange = range;
|
||||
editor.setSelection(range);
|
||||
editor.revealRangeInCenter(range);
|
||||
updateDecorations();
|
||||
}
|
||||
|
||||
editor.onMouseDown(function(e)
|
||||
{
|
||||
if(range)
|
||||
{
|
||||
programmaticSelectionRange = range;
|
||||
updateDecorations();
|
||||
}
|
||||
});
|
||||
|
||||
function updateDecorations()
|
||||
{
|
||||
editor.deltaDecorations(decorations, []);
|
||||
|
||||
@@ -22,6 +22,7 @@ $config->action->objectNameFields['boardspace'] = 'name';
|
||||
$config->action->objectNameFields['doc'] = 'title';
|
||||
$config->action->objectNameFields['doclib'] = 'name';
|
||||
$config->action->objectNameFields['docspace'] = 'name';
|
||||
$config->action->objectNameFields['doctemplate'] = 'title';
|
||||
$config->action->objectNameFields['todo'] = 'name';
|
||||
$config->action->objectNameFields['branch'] = 'name';
|
||||
$config->action->objectNameFields['module'] = 'name';
|
||||
@@ -88,7 +89,7 @@ $config->action->majorList['doc'] = array('releaseddoc');
|
||||
|
||||
$config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,';
|
||||
$config->action->needGetRelateField = ',branch,story,epic,requirement,productplan,release,task,build,bug,testcase,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,module,review,';
|
||||
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,instance,gitea,gogs,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,user,entry,repo,pivot,scene,boardspace,auditplan,auditresult,productline,chapter,';
|
||||
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,instance,gitea,gogs,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,user,entry,repo,pivot,scene,boardspace,auditplan,auditresult,productline,chapter,doc,';
|
||||
$config->action->ignoreObjectType4Dynamic = 'kanbanregion,kanbanlane,kanbancolumn';
|
||||
$config->action->ignoreActions4Dynamic = 'disconnectxuanxuan,reconnectxuanxuan,loginxuanxuan,logoutxuanxuan,editmr,removemr,syncdoingbyticket,syncdoingbystory,syncdoingbyuserstory,syncdoingbyepic,syncdoingbytask,syncdoingbybug,syncdoingbytodo,syncdoingbydemand';
|
||||
|
||||
|
||||
@@ -206,6 +206,31 @@ class action extends control
|
||||
$url = $this->createLink('action', 'trash', "browseType=boardspace");
|
||||
if($isDeleted) return $this->send(array('result' => 'fail', 'callback' => "zui.Modal.confirm({message: '{$this->lang->action->undeleteBoardTip}'}).then((res) => {if(res) loadPage('{$url}');});"));
|
||||
}
|
||||
elseif($oldAction->objectType == 'doctemplate')
|
||||
{
|
||||
$templateScopeAndType = $this->dao->select('id,lib,module')->from(TABLE_DOC)->where('id')->eq($oldAction->objectID)->fetchAll('id');
|
||||
$scopeID = zget($templateScopeAndType[$oldAction->objectID], 'lib', 0);
|
||||
$typeID = zget($templateScopeAndType[$oldAction->objectID], 'module', 0);
|
||||
if($confirmChange == 'no')
|
||||
{
|
||||
$isDeletedType = $this->dao->select('deleted')->from(TABLE_MODULE)->where('type')->eq('docTemplate')->andWhere('id')->eq($typeID)->fetch('deleted');
|
||||
$isDeletedScope = $this->dao->select('deleted')->from(TABLE_DOCLIB)->where('type')->eq('template')->andWhere('id')->eq($scopeID)->fetch('deleted');
|
||||
|
||||
if($isDeletedType == '1' || $isDeletedScope == '1')
|
||||
{
|
||||
$url = $this->createLink('action', 'undelete', "action={$actionID}&browseType={$browseType}&confirmChange=yes");
|
||||
return $this->send(array('result' => 'fail', 'callback' => "zui.Modal.confirm({message: '{$this->lang->action->undeleteTemplateTip}', icon: 'icon-exclamation-sign', iconClass: 'warning-pale rounded-full icon-2x'}).then((res) => {if(res) $.ajaxSubmit({url: '{$url}'});});"));
|
||||
}
|
||||
}
|
||||
|
||||
if($confirmChange == 'yes')
|
||||
{
|
||||
$this->dao->update(TABLE_DOCLIB)->set('deleted')->eq('0')->where('id')->eq($scopeID)->exec();
|
||||
$this->dao->update(TABLE_MODULE)->set('deleted')->eq('0')->where('id')->eq($typeID)->exec();
|
||||
$parentType = $this->dao->select('parent')->from(TABLE_MODULE)->where('id')->eq($typeID)->fetch('parent');
|
||||
if(!empty($parentType)) $this->dao->update(TABLE_MODULE)->set('deleted')->eq('0')->where('id')->eq($parentType)->exec();
|
||||
}
|
||||
}
|
||||
|
||||
$result = $this->action->undelete($actionID);
|
||||
if(true !== $result) return $this->send(array('result' => 'fail', 'load' => array('confirm' => $result)));
|
||||
|
||||
+25
-17
@@ -58,23 +58,24 @@ $lang->action->refusescene = 'Before restoring the scene, please restore the pa
|
||||
$lang->action->refusemodule = 'Before restoring the module, please restore the parent module of this module ';
|
||||
$lang->action->refusekanban = 'Before restoring the Kanban board, make sure to restore the space it belongs to';
|
||||
|
||||
$lang->action->trashTips = 'Hinweis: Alle Löschungen in ZenTao sind logische Löschungen.';
|
||||
$lang->action->textDiff = 'Text Format';
|
||||
$lang->action->original = 'Original Format';
|
||||
$lang->action->confirmHideAll = 'Möchten Sie alle Einträge verstecken?';
|
||||
$lang->action->needEdit = '%s existiert bereits. Bitte bearbeiten.';
|
||||
$lang->action->historyEdit = 'Der Verlauf darf nicht leer sein.';
|
||||
$lang->action->noDynamic = 'Kein Verlauf. ';
|
||||
$lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.';
|
||||
$lang->action->executionNoProject = "The execution does not belong to a {$lang->projectCommon},please restore the {$lang->projectCommon} first";
|
||||
$lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first';
|
||||
$lang->action->hasCreatedTask = 'Tasks have been created in this parent phase and cannot be restored!';
|
||||
$lang->action->hasDeletedParent = 'Restoring this phase requires restoring the deleted parent phase %s at the same time.';
|
||||
$lang->action->hasChangedAttr = "After recovery, the phase type will be adjusted to '%s' according to the parent phase type.";
|
||||
$lang->action->whetherToRestore = 'Confirm to restore?';
|
||||
$lang->action->undeleteModuleTip = 'Once the subdirectory has been restored, its parent directory will also be automatically recovered and synchronized, would you like to proceed with restoring the directory?';
|
||||
$lang->action->undeleteTaskTip = 'The execution associated with this task has been removed. If you choose to restore it, the task will no longer be visible. Would you like to proceed with restoring the task?';
|
||||
$lang->action->undeleteBoardTip = 'Before restoring the board, please restore its affiliated space first.';
|
||||
$lang->action->trashTips = 'Hinweis: Alle Löschungen in ZenTao sind logische Löschungen.';
|
||||
$lang->action->textDiff = 'Text Format';
|
||||
$lang->action->original = 'Original Format';
|
||||
$lang->action->confirmHideAll = 'Möchten Sie alle Einträge verstecken?';
|
||||
$lang->action->needEdit = '%s existiert bereits. Bitte bearbeiten.';
|
||||
$lang->action->historyEdit = 'Der Verlauf darf nicht leer sein.';
|
||||
$lang->action->noDynamic = 'Kein Verlauf. ';
|
||||
$lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.';
|
||||
$lang->action->executionNoProject = "The execution does not belong to a {$lang->projectCommon},please restore the {$lang->projectCommon} first";
|
||||
$lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first';
|
||||
$lang->action->hasCreatedTask = 'Tasks have been created in this parent phase and cannot be restored!';
|
||||
$lang->action->hasDeletedParent = 'Restoring this phase requires restoring the deleted parent phase %s at the same time.';
|
||||
$lang->action->hasChangedAttr = "After recovery, the phase type will be adjusted to '%s' according to the parent phase type.";
|
||||
$lang->action->whetherToRestore = 'Confirm to restore?';
|
||||
$lang->action->undeleteModuleTip = 'Once the subdirectory has been restored, its parent directory will also be automatically recovered and synchronized, would you like to proceed with restoring the directory?';
|
||||
$lang->action->undeleteTaskTip = 'The execution associated with this task has been removed. If you choose to restore it, the task will no longer be visible. Would you like to proceed with restoring the task?';
|
||||
$lang->action->undeleteBoardTip = 'Before restoring the board, please restore its affiliated space first.';
|
||||
$lang->action->undeleteTemplateTip = 'The type (and scope) of this template has been deleted. Are you sure you want to synchronize and restore them?';
|
||||
|
||||
$lang->action->hasOtherType = array();
|
||||
$lang->action->hasOtherType['stage'] = "Only subtypes of {$lang->executionCommon} / Kanban types can be created at this parent stage, so the current stage cannot be restored.";
|
||||
@@ -133,6 +134,7 @@ $lang->action->objectTypes['doc'] = 'Dok';
|
||||
$lang->action->objectTypes['api'] = 'Interface';
|
||||
$lang->action->objectTypes['doclib'] = 'Dok Bibliothek';
|
||||
$lang->action->objectTypes['docspace'] = 'Dok Space';
|
||||
$lang->action->objectTypes['doctemplate'] = 'Doc Template';
|
||||
$lang->action->objectTypes['apistruct'] = 'API struct';
|
||||
$lang->action->objectTypes['todo'] = 'Todo';
|
||||
$lang->action->objectTypes['risk'] = 'Risk';
|
||||
@@ -294,6 +296,7 @@ $lang->action->desc->managedteam = '$date, by <strong>$actor</strong> m
|
||||
$lang->action->desc->syncexecutionteam = '$date, synchronise members when execution adds members.' . "\n";
|
||||
$lang->action->desc->syncprojectteam = '$date, synchronise members when project removes members' . "\n";
|
||||
$lang->action->desc->syncbycase = '$date, running the testcase sets the request status as Doing.' . "\n";
|
||||
$lang->action->desc->converttonewdoc = '$date, <strong>$actor</strong> completed the conversion.';
|
||||
|
||||
/* Used to describe the history of operations related to parent-child tasks. */
|
||||
$lang->action->desc->createchildren = '$date, <strong>$actor</strong> created a child task <strong>$extra</strong>。' . "\n";
|
||||
@@ -329,6 +332,9 @@ $lang->action->desc->releaseddoc = '$date, <strong>$actor</strong> released <str
|
||||
/* Describe the operation records of document conversion.。*/
|
||||
$lang->action->desc->convertdoc = '$date, <strong>$actor</strong> complete document conversion <strong>$extra</strong>.' . "\n";
|
||||
|
||||
/* Describe the operation records of template conversion. */
|
||||
$lang->action->desc->convertdoctemplate = '$date, <strong>$actor</strong> complete template conversion <strong>$extra</strong>.' . "\n";
|
||||
|
||||
/* This parameter describes historical operations that are performed when a document is collected or uncollected. */
|
||||
$lang->action->desc->collected = '$date, <strong>$actor</strong> collected <strong>$extra</strong>.' . "\n";
|
||||
$lang->action->desc->uncollected = '$date, <strong>$actor</strong> uncollected <strong>$extra</strong>.' . "\n";
|
||||
@@ -550,6 +556,7 @@ $lang->action->label->deletesnapshot = 'deleted snapshot';
|
||||
$lang->action->label->saveddraft = 'save draft';
|
||||
$lang->action->label->releaseddoc = 'released';
|
||||
$lang->action->label->convertdoc = 'Convert doc';
|
||||
$lang->action->label->convertdoctemplate = 'Convert template';
|
||||
$lang->action->label->collected = 'collected';
|
||||
$lang->action->label->uncollected = 'uncollected';
|
||||
$lang->action->label->online = 'online';
|
||||
@@ -911,6 +918,7 @@ $lang->action->label->todo = 'Todo|todo|view|todoID=%s';
|
||||
$lang->action->label->doclib = 'Dok Bibliothek|doc|teamspace|objectID=%s&libID=%s';
|
||||
$lang->action->label->docspace = 'Dok Space';
|
||||
$lang->action->label->doc = 'Dok|doc|view|docID=%s';
|
||||
$lang->action->label->doctemplate = 'Doc Template|doc|view|docID=%s';
|
||||
$lang->action->label->user = 'Benutzer|user|view|account=%s';
|
||||
$lang->action->label->testreport = 'Berichte|testreport|view|report=%s';
|
||||
$lang->action->label->entry = 'Eintrag|entry|browse|';
|
||||
|
||||
+25
-17
@@ -58,23 +58,24 @@ $lang->action->refusescene = 'Before restoring the scene, please restore the pa
|
||||
$lang->action->refusemodule = 'Before restoring the module, please restore the parent module of this module ';
|
||||
$lang->action->refusekanban = 'Before restoring the Kanban board, make sure to restore the space it belongs to';
|
||||
|
||||
$lang->action->trashTips = 'Note: Delete in ZenTao is logic.';
|
||||
$lang->action->textDiff = 'Text Format';
|
||||
$lang->action->original = 'Original Format';
|
||||
$lang->action->confirmHideAll = 'Do you want to hide all the records?';
|
||||
$lang->action->needEdit = '%s that you want to restore. Please edit it.';
|
||||
$lang->action->historyEdit = 'The history EditBy cannot be empty.';
|
||||
$lang->action->noDynamic = 'No dynamics. ';
|
||||
$lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.';
|
||||
$lang->action->executionNoProject = "The execution does not belong to a {$lang->projectCommon},please restore the {$lang->projectCommon} first";
|
||||
$lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first';
|
||||
$lang->action->hasCreatedTask = 'Tasks have been created in this parent phase and cannot be restored!';
|
||||
$lang->action->hasDeletedParent = 'Restoring this phase requires restoring the deleted parent phase %s at the same time.';
|
||||
$lang->action->hasChangedAttr = "After recovery, the phase type will be adjusted to '%s' according to the parent phase type.";
|
||||
$lang->action->whetherToRestore = 'Confirm to restore?';
|
||||
$lang->action->undeleteModuleTip = 'Once the subdirectory has been restored, its parent directory will also be automatically recovered and synchronized, would you like to proceed with restoring the directory?';
|
||||
$lang->action->undeleteTaskTip = 'The execution associated with this task has been removed. If you choose to restore it, the task will no longer be visible. Would you like to proceed with restoring the task?';
|
||||
$lang->action->undeleteBoardTip = 'Before restoring the board, please restore its affiliated space first.';
|
||||
$lang->action->trashTips = 'Note: Delete in ZenTao is logic.';
|
||||
$lang->action->textDiff = 'Text Format';
|
||||
$lang->action->original = 'Original Format';
|
||||
$lang->action->confirmHideAll = 'Do you want to hide all the records?';
|
||||
$lang->action->needEdit = '%s that you want to restore. Please edit it.';
|
||||
$lang->action->historyEdit = 'The history EditBy cannot be empty.';
|
||||
$lang->action->noDynamic = 'No dynamics. ';
|
||||
$lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.';
|
||||
$lang->action->executionNoProject = "The execution does not belong to a {$lang->projectCommon},please restore the {$lang->projectCommon} first";
|
||||
$lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first';
|
||||
$lang->action->hasCreatedTask = 'Tasks have been created in this parent phase and cannot be restored!';
|
||||
$lang->action->hasDeletedParent = 'Restoring this phase requires restoring the deleted parent phase %s at the same time.';
|
||||
$lang->action->hasChangedAttr = "After recovery, the phase type will be adjusted to '%s' according to the parent phase type.";
|
||||
$lang->action->whetherToRestore = 'Confirm to restore?';
|
||||
$lang->action->undeleteModuleTip = 'Once the subdirectory has been restored, its parent directory will also be automatically recovered and synchronized, would you like to proceed with restoring the directory?';
|
||||
$lang->action->undeleteTaskTip = 'The execution associated with this task has been removed. If you choose to restore it, the task will no longer be visible. Would you like to proceed with restoring the task?';
|
||||
$lang->action->undeleteBoardTip = 'Before restoring the board, please restore its affiliated space first.';
|
||||
$lang->action->undeleteTemplateTip = 'The category (and scope) of this template has been deleted. Are you sure you want to synchronize and restore them?';
|
||||
|
||||
$lang->action->hasOtherType = array();
|
||||
$lang->action->hasOtherType['stage'] = "Only subtypes of {$lang->executionCommon} / Kanban types can be created at this parent stage, so the current stage cannot be restored.";
|
||||
@@ -133,6 +134,7 @@ $lang->action->objectTypes['doc'] = 'Document';
|
||||
$lang->action->objectTypes['api'] = 'Interface';
|
||||
$lang->action->objectTypes['doclib'] = 'Document Library';
|
||||
$lang->action->objectTypes['docspace'] = 'Document Space';
|
||||
$lang->action->objectTypes['doctemplate'] = 'Doc Template';
|
||||
$lang->action->objectTypes['apistruct'] = 'API struct';
|
||||
$lang->action->objectTypes['todo'] = 'Todo';
|
||||
$lang->action->objectTypes['risk'] = 'Risk';
|
||||
@@ -294,6 +296,7 @@ $lang->action->desc->managedteam = '$date, by <strong>$actor</strong> m
|
||||
$lang->action->desc->syncexecutionteam = '$date, synchronise members when execution adds members.' . "\n";
|
||||
$lang->action->desc->syncprojectteam = '$date, synchronise members when project removes members' . "\n";
|
||||
$lang->action->desc->syncbycase = '$date, running the testcase sets the request status as Doing.' . "\n";
|
||||
$lang->action->desc->converttonewdoc = '$date, <strong>$actor</strong> completed the conversion.';
|
||||
|
||||
/* Used to describe the history of operations related to parent-child tasks. */
|
||||
$lang->action->desc->createchildren = '$date, <strong>$actor</strong> created a child task <strong>$extra</strong>。' . "\n";
|
||||
@@ -329,6 +332,9 @@ $lang->action->desc->releaseddoc = '$date, <strong>$actor</strong> released <str
|
||||
/* Describe the operation records of document conversion.。*/
|
||||
$lang->action->desc->convertdoc = '$date, <strong>$actor</strong> complete document conversion <strong>$extra</strong>.' . "\n";
|
||||
|
||||
/* Describe the operation records of template conversion. */
|
||||
$lang->action->desc->convertdoctemplate = '$date, <strong>$actor</strong> complete template conversion <strong>$extra</strong>.' . "\n";
|
||||
|
||||
/* This parameter describes historical operations that are performed when a document is collected or uncollected. */
|
||||
$lang->action->desc->collected = '$date, <strong>$actor</strong> collected <strong>$extra</strong>.' . "\n";
|
||||
$lang->action->desc->uncollected = '$date, <strong>$actor</strong> uncollected <strong>$extra</strong>.' . "\n";
|
||||
@@ -550,6 +556,7 @@ $lang->action->label->deletesnapshot = 'deleted snapshot';
|
||||
$lang->action->label->saveddraft = 'save draft';
|
||||
$lang->action->label->releaseddoc = 'released';
|
||||
$lang->action->label->convertdoc = 'Convert doc';
|
||||
$lang->action->label->convertdoctemplate = 'Convert template';
|
||||
$lang->action->label->collected = 'collected';
|
||||
$lang->action->label->uncollected = 'uncollected';
|
||||
$lang->action->label->online = 'online';
|
||||
@@ -911,6 +918,7 @@ $lang->action->label->todo = 'Todo|todo|view|todoID=%s';
|
||||
$lang->action->label->doclib = 'Doc Library|doc|teamspace|objectID=%s&libID=%s';
|
||||
$lang->action->label->docspace = 'Doc Space';
|
||||
$lang->action->label->doc = 'Doc|doc|view|docID=%s';
|
||||
$lang->action->label->doctemplate = 'Doc Template|doc|view|docID=%s';
|
||||
$lang->action->label->user = 'User|user|view|account=%s';
|
||||
$lang->action->label->testreport = 'Report|testreport|view|report=%s';
|
||||
$lang->action->label->entry = 'Application|entry|browse|';
|
||||
|
||||
+25
-17
@@ -58,23 +58,24 @@ $lang->action->refusescene = 'Before restoring the scene, please restore the pa
|
||||
$lang->action->refusemodule = 'Before restoring the module, please restore the parent module of this module ';
|
||||
$lang->action->refusekanban = 'Before restoring the Kanban board, make sure to restore the space it belongs to';
|
||||
|
||||
$lang->action->trashTips = 'Note: Les suppressions dans ZenTao sont purement logiques.';
|
||||
$lang->action->textDiff = 'Text Format';
|
||||
$lang->action->original = 'Original Format';
|
||||
$lang->action->confirmHideAll = 'Voulez-vous masquer tous les enregistrements ?';
|
||||
$lang->action->needEdit = '%s que vous voulez restaurer. SVP éditez la.';
|
||||
$lang->action->historyEdit = "l'historique Edité Par ne peut pas être vide.";
|
||||
$lang->action->noDynamic = "Pas d'historique.";
|
||||
$lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.';
|
||||
$lang->action->executionNoProject = "The execution does not belong to a {$lang->projectCommon},please restore the {$lang->projectCommon} first";
|
||||
$lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first';
|
||||
$lang->action->hasCreatedTask = 'Tasks have been created in this parent phase and cannot be restored!';
|
||||
$lang->action->hasDeletedParent = 'Restoring this phase requires restoring the deleted parent phase %s at the same time.';
|
||||
$lang->action->hasChangedAttr = "After recovery, the phase type will be adjusted to '%s' according to the parent phase type.";
|
||||
$lang->action->whetherToRestore = 'Confirm to restore?';
|
||||
$lang->action->undeleteModuleTip = 'Once the subdirectory has been restored, its parent directory will also be automatically recovered and synchronized, would you like to proceed with restoring the directory?';
|
||||
$lang->action->undeleteTaskTip = 'The execution associated with this task has been removed. If you choose to restore it, the task will no longer be visible. Would you like to proceed with restoring the task?';
|
||||
$lang->action->undeleteBoardTip = 'Before restoring the board, please restore its affiliated space first.';
|
||||
$lang->action->trashTips = 'Note: Les suppressions dans ZenTao sont purement logiques.';
|
||||
$lang->action->textDiff = 'Text Format';
|
||||
$lang->action->original = 'Original Format';
|
||||
$lang->action->confirmHideAll = 'Voulez-vous masquer tous les enregistrements ?';
|
||||
$lang->action->needEdit = '%s que vous voulez restaurer. SVP éditez la.';
|
||||
$lang->action->historyEdit = "l'historique Edité Par ne peut pas être vide.";
|
||||
$lang->action->noDynamic = "Pas d'historique.";
|
||||
$lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.';
|
||||
$lang->action->executionNoProject = "The execution does not belong to a {$lang->projectCommon},please restore the {$lang->projectCommon} first";
|
||||
$lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first';
|
||||
$lang->action->hasCreatedTask = 'Tasks have been created in this parent phase and cannot be restored!';
|
||||
$lang->action->hasDeletedParent = 'Restoring this phase requires restoring the deleted parent phase %s at the same time.';
|
||||
$lang->action->hasChangedAttr = "After recovery, the phase type will be adjusted to '%s' according to the parent phase type.";
|
||||
$lang->action->whetherToRestore = 'Confirm to restore?';
|
||||
$lang->action->undeleteModuleTip = 'Once the subdirectory has been restored, its parent directory will also be automatically recovered and synchronized, would you like to proceed with restoring the directory?';
|
||||
$lang->action->undeleteTaskTip = 'The execution associated with this task has been removed. If you choose to restore it, the task will no longer be visible. Would you like to proceed with restoring the task?';
|
||||
$lang->action->undeleteBoardTip = 'Before restoring the board, please restore its affiliated space first.';
|
||||
$lang->action->undeleteTemplateTip = 'The category (and scope) of this template has been deleted. Are you sure you want to synchronize and restore them?';
|
||||
|
||||
$lang->action->hasOtherType = array();
|
||||
$lang->action->hasOtherType['stage'] = "Only subtypes of {$lang->executionCommon} / Kanban types can be created at this parent stage, so the current stage cannot be restored.";
|
||||
@@ -133,6 +134,7 @@ $lang->action->objectTypes['doc'] = 'Document';
|
||||
$lang->action->objectTypes['api'] = 'Interface';
|
||||
$lang->action->objectTypes['doclib'] = 'Répertoire Documents';
|
||||
$lang->action->objectTypes['docspace'] = 'Répertoire Space';
|
||||
$lang->action->objectTypes['doctemplate'] = 'Doc Template';
|
||||
$lang->action->objectTypes['apistruct'] = 'API struct';
|
||||
$lang->action->objectTypes['todo'] = 'Todo';
|
||||
$lang->action->objectTypes['risk'] = 'Risk';
|
||||
@@ -294,6 +296,7 @@ $lang->action->desc->managedteam = '$date, by <strong>$actor</strong> m
|
||||
$lang->action->desc->syncexecutionteam = '$date, synchronise members when execution adds members.' . "\n";
|
||||
$lang->action->desc->syncprojectteam = '$date, synchronise members when project removes members' . "\n";
|
||||
$lang->action->desc->syncbycase = '$date, running the testcase sets the request status as Doing.' . "\n";
|
||||
$lang->action->desc->converttonewdoc = '$date, <strong>$actor</strong> completed the conversion.';
|
||||
|
||||
/* Used to describe the history of operations related to parent-child tasks. */
|
||||
$lang->action->desc->createchildren = '$date, <strong>$actor</strong> a créé un sous-tâche <strong>$extra</strong>。' . "\n";
|
||||
@@ -329,6 +332,9 @@ $lang->action->desc->releaseddoc = '$date, <strong>$actor</strong> released <str
|
||||
/* Describe the operation records of document conversion.。*/
|
||||
$lang->action->desc->convertdoc = '$date, <strong>$actor</strong> complete document conversion <strong>$extra</strong>.' . "\n";
|
||||
|
||||
/* Describe the operation records of template conversion. */
|
||||
$lang->action->desc->convertdoctemplate = '$date, <strong>$actor</strong> complete template conversion <strong>$extra</strong>.' . "\n";
|
||||
|
||||
/* This parameter describes historical operations that are performed when a document is collected or uncollected. */
|
||||
$lang->action->desc->collected = '$date, <strong>$actor</strong> collected <strong>$extra</strong>.' . "\n";
|
||||
$lang->action->desc->uncollected = '$date, <strong>$actor</strong> uncollected <strong>$extra</strong>.' . "\n";
|
||||
@@ -550,6 +556,7 @@ $lang->action->label->deletesnapshot = 'deleted snapshot';
|
||||
$lang->action->label->saveddraft = 'save draft';
|
||||
$lang->action->label->releaseddoc = 'released';
|
||||
$lang->action->label->convertdoc = 'Convert doc';
|
||||
$lang->action->label->convertdoctemplate = 'Convert template';
|
||||
$lang->action->label->collected = 'collected';
|
||||
$lang->action->label->uncollected = 'uncollected';
|
||||
$lang->action->label->online = 'online';
|
||||
@@ -911,6 +918,7 @@ $lang->action->label->todo = 'Agenda|todo|view|todoID=%s';
|
||||
$lang->action->label->doclib = 'Bibliothèque|doc|teamspace|objectID=%s&libID=%s';
|
||||
$lang->action->label->docspace = 'Doc Space';
|
||||
$lang->action->label->doc = 'Document|doc|view|docID=%s';
|
||||
$lang->action->label->doctemplate = 'Doc Template|doc|view|docID=%s';
|
||||
$lang->action->label->user = 'Utilisateur|user|view|account=%s';
|
||||
$lang->action->label->testreport = 'Rapport|testreport|view|report=%s';
|
||||
$lang->action->label->entry = 'Application|entry|browse|';
|
||||
|
||||
@@ -58,23 +58,24 @@ $lang->action->refusescene = '还原场景之前,请先还原该场景的父
|
||||
$lang->action->refusemodule = '还原模块之前,请先还原该模块的父模块';
|
||||
$lang->action->refusekanban = '还原看板之前,请先还原该看板所属空间';
|
||||
|
||||
$lang->action->trashTips = '提示:为了保证系统的完整性,禅道系统的删除都是标记删除。';
|
||||
$lang->action->textDiff = '文本格式';
|
||||
$lang->action->original = '原始格式';
|
||||
$lang->action->confirmHideAll = '您确定要全部隐藏这些记录吗?';
|
||||
$lang->action->needEdit = '要还原%s的名称或代号已经存在,请编辑更改。';
|
||||
$lang->action->historyEdit = '历史记录编辑不能为空。';
|
||||
$lang->action->noDynamic = '暂时没有动态。';
|
||||
$lang->action->undeletedTips = '该数据在版本升级过程中未参与数据归并流程,不支持还原。';
|
||||
$lang->action->executionNoProject = "该执行没有所属的{$lang->projectCommon},请先还原{$lang->projectCommon}再还原执行";
|
||||
$lang->action->repoNoServer = '该代码库没有所属的服务器,请先还原服务器再还原代码库';
|
||||
$lang->action->hasCreatedTask = '该父阶段已创建任务,无法恢复!';
|
||||
$lang->action->hasDeletedParent = '恢复该阶段需要同时恢复已删除的父阶段%s,';
|
||||
$lang->action->hasChangedAttr = '恢复后阶段类型将根据父阶段类型均调整为“%s”,';
|
||||
$lang->action->whetherToRestore = '是否恢复?';
|
||||
$lang->action->undeleteModuleTip = '子目录恢复后,会同步恢复他的上级目录,确认要恢复吗?';
|
||||
$lang->action->undeleteTaskTip = '该任务所属执行已删除,还原后不能看到该任务,是否继续还原任务?';
|
||||
$lang->action->undeleteBoardTip = '还原白板之前,请先还原该白板的所属空间。';
|
||||
$lang->action->trashTips = '提示:为了保证系统的完整性,禅道系统的删除都是标记删除。';
|
||||
$lang->action->textDiff = '文本格式';
|
||||
$lang->action->original = '原始格式';
|
||||
$lang->action->confirmHideAll = '您确定要全部隐藏这些记录吗?';
|
||||
$lang->action->needEdit = '要还原%s的名称或代号已经存在,请编辑更改。';
|
||||
$lang->action->historyEdit = '历史记录编辑不能为空。';
|
||||
$lang->action->noDynamic = '暂时没有动态。';
|
||||
$lang->action->undeletedTips = '该数据在版本升级过程中未参与数据归并流程,不支持还原。';
|
||||
$lang->action->executionNoProject = "该执行没有所属的{$lang->projectCommon},请先还原{$lang->projectCommon}再还原执行";
|
||||
$lang->action->repoNoServer = '该代码库没有所属的服务器,请先还原服务器再还原代码库';
|
||||
$lang->action->hasCreatedTask = '该父阶段已创建任务,无法恢复!';
|
||||
$lang->action->hasDeletedParent = '恢复该阶段需要同时恢复已删除的父阶段%s,';
|
||||
$lang->action->hasChangedAttr = '恢复后阶段类型将根据父阶段类型均调整为“%s”,';
|
||||
$lang->action->whetherToRestore = '是否恢复?';
|
||||
$lang->action->undeleteModuleTip = '子目录恢复后,会同步恢复他的上级目录,确认要恢复吗?';
|
||||
$lang->action->undeleteTaskTip = '该任务所属执行已删除,还原后不能看到该任务,是否继续还原任务?';
|
||||
$lang->action->undeleteBoardTip = '还原白板之前,请先还原该白板的所属空间。';
|
||||
$lang->action->undeleteTemplateTip = '该文档模板的分类(和范围)已被删除,确认要同步还原吗?';
|
||||
|
||||
$lang->action->hasOtherType = array();
|
||||
$lang->action->hasOtherType['stage'] = "当前阶段的父级现在只允许创建{$lang->executionCommon}/看板类型的子级,故无法恢复当前阶段。";
|
||||
@@ -133,6 +134,7 @@ $lang->action->objectTypes['doc'] = '文档';
|
||||
$lang->action->objectTypes['api'] = '接口';
|
||||
$lang->action->objectTypes['doclib'] = '文档库';
|
||||
$lang->action->objectTypes['docspace'] = '文档空间';
|
||||
$lang->action->objectTypes['doctemplate'] = '文档模板';
|
||||
$lang->action->objectTypes['apistruct'] = '数据结构';
|
||||
$lang->action->objectTypes['todo'] = '待办';
|
||||
$lang->action->objectTypes['risk'] = '风险';
|
||||
@@ -294,6 +296,7 @@ $lang->action->desc->managedteam = '$date, 由 <strong>$actor</strong>
|
||||
$lang->action->desc->syncexecutionteam = '$date, 同步更新执行增加的团队成员。' . "\n";
|
||||
$lang->action->desc->syncprojectteam = '$date, 同步更新项目删除的团队成员。' . "\n";
|
||||
$lang->action->desc->syncbycase = '$date, 系统判断由于执行了用例,将测试单状态置为进行中。' . "\n";
|
||||
$lang->action->desc->converttonewdoc = '$date, 由 <strong>$actor</strong> 完成了文档转换。';
|
||||
|
||||
/* 用来描述和父子任务相关的操作历史记录。*/
|
||||
$lang->action->desc->createchildren = '$date, 由 <strong>$actor</strong> 创建子任务 <strong>$extra</strong>。' . "\n";
|
||||
@@ -329,6 +332,9 @@ $lang->action->desc->releaseddoc = '$date, 由 <strong>$actor</strong> 发布 <s
|
||||
/* 用来描述文档转换的操作记录。*/
|
||||
$lang->action->desc->convertdoc = '$date, 由 <strong>$actor</strong> 完成文档转换 <strong>$extra</strong>。' . "\n";
|
||||
|
||||
/* 用来描述文档模板转换的操作记录。*/
|
||||
$lang->action->desc->convertdoctemplate = '$date, 由 <strong>$actor</strong> 完成文档模板转换 <strong>$extra</strong>。' . "\n";
|
||||
|
||||
/* 用来描述文档收藏或取消收藏时的历史操作记录。*/
|
||||
$lang->action->desc->collected = '$date, 由 <strong>$actor</strong> 收藏 <strong>$extra</strong>。' . "\n";
|
||||
$lang->action->desc->uncollected = '$date, 由 <strong>$actor</strong> 取消收藏 <strong>$extra</strong>。' . "\n";
|
||||
@@ -550,6 +556,7 @@ $lang->action->label->deletesnapshot = '编辑了快照';
|
||||
$lang->action->label->saveddraft = '存为草稿';
|
||||
$lang->action->label->releaseddoc = '发布了';
|
||||
$lang->action->label->convertdoc = '转为新文档';
|
||||
$lang->action->label->convertdoctemplate = '转为新文档模板';
|
||||
$lang->action->label->collected = '收藏了';
|
||||
$lang->action->label->uncollected = '取消收藏了';
|
||||
$lang->action->label->online = '上架了';
|
||||
@@ -911,6 +918,7 @@ $lang->action->label->todo = '待办|todo|view|todoID=%s';
|
||||
$lang->action->label->doclib = '文档库|doc|teamspace|objectID=%s&libID=%s';
|
||||
$lang->action->label->docspace = '文档空间';
|
||||
$lang->action->label->doc = '文档|doc|view|docID=%s';
|
||||
$lang->action->label->doctemplate = '文档模板|doc|view|docID=%s';
|
||||
$lang->action->label->user = '用户|user|view|account=%s';
|
||||
$lang->action->label->testreport = '报告|testreport|view|report=%s';
|
||||
$lang->action->label->entry = '应用|entry|browse|';
|
||||
|
||||
@@ -1497,11 +1497,13 @@ class actionModel extends model
|
||||
|
||||
/* 区别是否有diff信息,以便于将有diff信息的字段放在最后。 */
|
||||
/* Diff histories by hasing diff info or not. Thus we can to make sure the field with diff show at last. */
|
||||
if($objectType == 'doctemplate') $this->app->loadLang('doc');
|
||||
foreach($histories as $history)
|
||||
{
|
||||
$fieldName = $history->field;
|
||||
$history->fieldLabel = isset($this->lang->{$objectType}) && isset($this->lang->{$objectType}->{$fieldName}) ? $this->lang->{$objectType}->{$fieldName} : $fieldName;
|
||||
if($objectType == 'module') $history->fieldLabel = $this->lang->tree->{$fieldName};
|
||||
if($objectType == 'doctemplate') $history->fieldLabel = zget($this->lang->docTemplate, $fieldName, zget($this->lang->doc, $fieldName, $fieldName));
|
||||
if($fieldName == 'fileName') $history->fieldLabel = $this->lang->file->{$fieldName};
|
||||
if(($length = strlen($history->fieldLabel)) > $maxLength) $maxLength = $length;
|
||||
$history->diff ? $historiesWithDiff[] = $history : $historiesWithoutDiff[] = $history;
|
||||
|
||||
@@ -431,26 +431,30 @@ class actionTest
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function computeBeginAndEndTest($period)
|
||||
public function computeBeginAndEndTest($period, string $date, string $direction)
|
||||
{
|
||||
$date = $this->objectModel->computeBeginAndEnd($period, '', '');
|
||||
$result = $this->objectModel->computeBeginAndEnd($period, $date, $direction);
|
||||
|
||||
$today = date('Y-m-d');
|
||||
$tomorrow = date('Y-m-d', strtotime('+1 days'));
|
||||
$yesterday = date('Y-m-d', strtotime('-1 days'));
|
||||
$twoDaysAgo = date('Y-m-d', strtotime('-2 days'));
|
||||
|
||||
if($period == 'all') return $date['begin'] == '1970-01-01' and $date['end'] == '2030-01-01';
|
||||
if($period == 'today') return $date['begin'] == $today and $date['end'] == $tomorrow;
|
||||
if($period == 'yesterday') return $date['begin'] == $yesterday and $date['end'] == $today;
|
||||
if($period == 'twodaysago') return $date['begin'] == $twoDaysAgo and $date['end'] == $yesterday;
|
||||
if($period == 'latest3days') return $date['begin'] == $twoDaysAgo and $date['end'] == $tomorrow;
|
||||
if($period == 'thismonth') return $date == date::getThisMonth();
|
||||
if($period == 'lastmonth') return $date == date::getLastMonth();
|
||||
if(!empty($date) && empty($direction)) return $result['begin'] == '2025-04-23' && $result['end'] == '2025-04-23';
|
||||
|
||||
if($direction == 'pre') return $result['begin'] == '2025-04-23' && $result['end'] == '2030-01-01';
|
||||
if($direction == 'next') return $result['begin'] == '1970-01-01' && $result['end'] == '2025-04-23';
|
||||
if($period == 'all') return $result['begin'] == '2025-01-01' && $result['end'] == '2030-01-01';
|
||||
if($period == 'today') return $result['begin'] == $today && $result['end'] == $tomorrow;
|
||||
if($period == 'yesterday') return $result['begin'] == $yesterday && $result['end'] == $today;
|
||||
if($period == 'twodaysago') return $result['begin'] == $twoDaysAgo && $result['end'] == $yesterday;
|
||||
if($period == 'latest3days') return $result['begin'] == $twoDaysAgo && $result['end'] == $tomorrow;
|
||||
if($period == 'thismonth') return $result == date::getThisMonth();
|
||||
if($period == 'lastmonth') return $result == date::getLastMonth();
|
||||
$func = "get$period";
|
||||
extract(date::$func());
|
||||
if($period == 'thisweek') return $date['begin'] == $begin and $date['end'] == $end;
|
||||
if($period == 'lastweek') return $date['begin'] == $begin and $date['end'] == $end;
|
||||
if($period == 'thisweek') return $result['begin'] == $begin && $result['end'] == $end;
|
||||
if($period == 'lastweek') return $result['begin'] == $begin && $result['end'] == $end;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -811,4 +815,21 @@ class actionTest
|
||||
$history = $this->objectModel->dao->select('*')->from(TABLE_HISTORY)->where('id')->eq($historyID)->fetch();
|
||||
return $this->objectModel->processHistory($history);
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染每一个action的历史记录。
|
||||
* Render histories of every action.
|
||||
*
|
||||
* @param string $objectType
|
||||
* @param int $historyID
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function renderChangesTest(string $objectType, int $historyID = 0): string
|
||||
{
|
||||
$histories = $this->objectModel->dao->select('*')->from(TABLE_HISTORY)->where('id')->eq($historyID)->fetchAll('id', false);
|
||||
$content = $this->objectModel->renderChanges($objectType, 0, $histories);
|
||||
$content = str_replace("\n", '', $content);
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,19 +19,27 @@ cid=1
|
||||
- 测试计算lastweek的日期 @1
|
||||
- 测试计算thismonth的日期 @1
|
||||
- 测试计算lastmonth的日期 @1
|
||||
- 测试返回具体的日期 @1
|
||||
- 测试返回具体日期的结束日期 @1
|
||||
- 测试返回具体日期的开始日期 @1
|
||||
|
||||
*/
|
||||
|
||||
$typeList = array('all', 'today', 'yesterday', 'twodaysago', 'latest3days', 'thisweek', 'lastweek', 'thismonth', 'lastmonth');
|
||||
$typeList = array('all', 'today', 'yesterday', 'twodaysago', 'latest3days', 'thisweek', 'lastweek', 'thismonth', 'lastmonth');
|
||||
$dateList = array('', '2025-04-23');
|
||||
$directionList = array('', 'pre', 'next');
|
||||
|
||||
$action = new actionTest();
|
||||
|
||||
r($action->computeBeginAndEndTest($typeList[0])) && p() && e('0'); // 测试计算all的日期
|
||||
r($action->computeBeginAndEndTest($typeList[1])) && p() && e('1'); // 测试计算today的日期
|
||||
r($action->computeBeginAndEndTest($typeList[2])) && p() && e('1'); // 测试计算yesterday的日期
|
||||
r($action->computeBeginAndEndTest($typeList[3])) && p() && e('1'); // 测试计算twodaysago的日期
|
||||
r($action->computeBeginAndEndTest($typeList[4])) && p() && e('1'); // 测试计算latest3days的日期
|
||||
r($action->computeBeginAndEndTest($typeList[5])) && p() && e('1'); // 测试计算thisweek的日期
|
||||
r($action->computeBeginAndEndTest($typeList[6])) && p() && e('1'); // 测试计算lastweek的日期
|
||||
r($action->computeBeginAndEndTest($typeList[7])) && p() && e('1'); // 测试计算thismonth的日期
|
||||
r($action->computeBeginAndEndTest($typeList[8])) && p() && e('1'); // 测试计算lastmonth的日期
|
||||
r($action->computeBeginAndEndTest($typeList[0], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算all的日期
|
||||
r($action->computeBeginAndEndTest($typeList[1], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算today的日期
|
||||
r($action->computeBeginAndEndTest($typeList[2], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算yesterday的日期
|
||||
r($action->computeBeginAndEndTest($typeList[3], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算twodaysago的日期
|
||||
r($action->computeBeginAndEndTest($typeList[4], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算latest3days的日期
|
||||
r($action->computeBeginAndEndTest($typeList[5], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算thisweek的日期
|
||||
r($action->computeBeginAndEndTest($typeList[6], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算lastweek的日期
|
||||
r($action->computeBeginAndEndTest($typeList[7], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算thismonth的日期
|
||||
r($action->computeBeginAndEndTest($typeList[8], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算lastmonth的日期
|
||||
r($action->computeBeginAndEndTest($typeList[0], $dateList[1], $directionList[0])) && p() && e('1'); // 测试返回具体的日期
|
||||
r($action->computeBeginAndEndTest($typeList[0], $dateList[1], $directionList[1])) && p() && e('1'); // 测试返回具体日期的结束日期
|
||||
r($action->computeBeginAndEndTest($typeList[0], $dateList[1], $directionList[2])) && p() && e('1'); // 测试返回具体日期的开始日期
|
||||
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
|
||||
title=测试 actionModel->renderChanges();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 测试type为空 @0
|
||||
- 测试bug解决方案历史记录 @修改了 <strong><i>解决方案</i></strong>,旧值为 "oldValue",新值为 "newValue"。<br />
|
||||
- 测试bug解决版本历史记录 @修改了 <strong><i>解决版本</i></strong>,旧值为 "oldValue",新值为 "newValue"。<br />
|
||||
- 测试bug解决日期历史记录 @修改了 <strong><i>解决日期</i></strong>,旧值为 "oldValue",新值为 "newValue"。<br />
|
||||
- 测试产品状态历史记录 @修改了 <strong><i>状态</i></strong>,旧值为 "oldValue",新值为 "newValue"。<br />
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/action.unittest.class.php';
|
||||
|
||||
su('admin');
|
||||
zenData('action')->gen(10);
|
||||
|
||||
$history = zenData('history');
|
||||
$history->old->range('oldValue');
|
||||
$history->oldValue->range('oldValue');
|
||||
$history->new->range('newValue');
|
||||
$history->newValue->range('newValue');
|
||||
$history->gen(10);
|
||||
|
||||
$action = new actionTest();
|
||||
r($action->renderChangesTest('')) && p('') && e('0'); // 测试type为空
|
||||
r($action->renderChangesTest('bug', 1)) && p('') && e('修改了 <strong><i>解决方案</i></strong>,旧值为 "oldValue",新值为 "newValue"。<br />'); // 测试bug解决方案历史记录
|
||||
r($action->renderChangesTest('bug', 2)) && p('') && e('修改了 <strong><i>解决版本</i></strong>,旧值为 "oldValue",新值为 "newValue"。<br />'); // 测试bug解决版本历史记录
|
||||
r($action->renderChangesTest('bug', 3)) && p('') && e('修改了 <strong><i>解决日期</i></strong>,旧值为 "oldValue",新值为 "newValue"。<br />'); // 测试bug解决日期历史记录
|
||||
r($action->renderChangesTest('product', 4)) && p('') && e('修改了 <strong><i>状态</i></strong>,旧值为 "oldValue",新值为 "newValue"。<br />'); // 测试产品状态历史记录
|
||||
@@ -24,6 +24,6 @@ form
|
||||
(
|
||||
set::name('actioncomment')
|
||||
),
|
||||
$objectType != 'story' ? fileSelector() : null,
|
||||
!in_array($objectType, array('story', 'doctemplate')) ? fileSelector() : null,
|
||||
set::actions($actions)
|
||||
);
|
||||
|
||||
@@ -92,8 +92,9 @@ class actionZen extends action
|
||||
}
|
||||
else
|
||||
{
|
||||
$module = $trash->objectType == 'case' ? 'testcase' : $trash->objectType;
|
||||
$params = $trash->objectType == 'user' ? "account={$trash->objectName}" : "id={$trash->objectID}";
|
||||
$module = $trash->objectType == 'case' ? 'testcase' : $trash->objectType;
|
||||
$module = $trash->objectType == 'doctemplate' ? 'doc' : $trash->objectType;
|
||||
$params = $trash->objectType == 'user' ? "account={$trash->objectName}" : "id={$trash->objectID}";
|
||||
$methodName = 'view';
|
||||
if($module == 'basicmeas')
|
||||
{
|
||||
@@ -111,11 +112,6 @@ class actionZen extends action
|
||||
$params = "libID=0&moduelID=0&apiID={$trash->objectID}";
|
||||
$methodName = 'index';
|
||||
}
|
||||
if($trash->objectType == 'doc')
|
||||
{
|
||||
$params = "docID={$trash->objectID}";
|
||||
if($trash->comment == 'chapter') $module = 'chapter';
|
||||
}
|
||||
if(in_array($module, array('traincourse','traincontents')))
|
||||
{
|
||||
$methodName = $module == 'traincourse' ? 'viewcourse' : 'viewchapter';
|
||||
|
||||
@@ -10,7 +10,6 @@ $config->admin->menuGroup['company'] = array('dept', 'company', 'user', 'group
|
||||
$config->admin->menuGroup['switch'] = array('admin|setmodule');
|
||||
$config->admin->menuGroup['model'] = array('auditcl', 'stage', 'deliverable', 'design', 'cmcl', 'reviewcl', 'custom|required', 'custom|set', 'custom|flow', 'custom|code', 'custom|percent','custom|estimate', 'custom|hours', 'subject', 'process', 'activity', 'zoutput', 'classify', 'holiday', 'reviewsetting', 'custom|project');
|
||||
$config->admin->menuGroup['feature'] = array('custom|set', 'custom|product', 'custom|execution', 'custom|required', 'custom|kanban', 'measurement', 'meetingroom', 'custom|browsestoryconcept', 'custom|kanban', 'sqlbuilder', 'report', 'custom|limittaskdate', 'measurement');
|
||||
$config->admin->menuGroup['template'] = array('custom|set', 'baseline');
|
||||
$config->admin->menuGroup['message'] = array('mail', 'webhook', 'sms', 'message');
|
||||
$config->admin->menuGroup['dev'] = array('dev', 'entry', 'editor');
|
||||
$config->admin->menuGroup['extension'] = array('extension');
|
||||
@@ -21,7 +20,6 @@ $config->admin->menuModuleGroup['model']['custom|set'] = array('project',
|
||||
$config->admin->menuModuleGroup['model']['custom|required'] = array('project', 'build');
|
||||
$config->admin->menuModuleGroup['feature']['custom|set'] = array('todo', 'block', 'epic', 'requirement', 'story', 'task', 'bug', 'testcase', 'testtask', 'feedback', 'user', 'ticket');
|
||||
$config->admin->menuModuleGroup['feature']['custom|required'] = array('bug', 'doc', 'product', 'epic', 'requirement', 'story', 'productplan', 'release', 'task', 'testcase', 'testsuite', 'testtask', 'testreport', 'caselib', 'doc', 'feedback', 'user', 'execution');
|
||||
$config->admin->menuModuleGroup['template']['custom|set'] = array('baseline');
|
||||
if($config->vision == 'lite')
|
||||
{
|
||||
$config->admin->menuModuleGroup['model']['custom|set'] = array();
|
||||
@@ -80,7 +78,6 @@ $config->admin->helpURL['company'] = 'https://www.zentao.net/book/zentaopms/38
|
||||
$config->admin->helpURL['switch'] = 'https://www.zentao.net/book/zentaopms/38.html';
|
||||
$config->admin->helpURL['model'] = 'https://www.zentao.net/book/zentaopms/533.html';
|
||||
$config->admin->helpURL['feature'] = 'https://www.zentao.net/book/zentaopms/38.html';
|
||||
$config->admin->helpURL['template'] = 'https://www.zentao.net/book/zentaopms/38.html';
|
||||
$config->admin->helpURL['message'] = 'https://www.zentao.net/book/zentaopms/email-notification-541.html';
|
||||
$config->admin->helpURL['extension'] = 'https://www.zentao.net/book/zentaopms/536.html';
|
||||
$config->admin->helpURL['dev'] = 'https://www.zentao.net/book/zentaopms/537.html';
|
||||
@@ -94,7 +91,6 @@ $config->admin->navsGroup['feature']['execution'] = ',execution,task,';
|
||||
$config->admin->navsGroup['feature']['project'] = ',project,story,';
|
||||
$config->admin->navsGroup['feature']['qa'] = ',bug,testcase,testsuite,testtask,testreport,caselib,';
|
||||
$config->admin->navsGroup['model']['common'] = ',project,build,issue,risk,opportunity,nc,';
|
||||
$config->admin->navsGroup['template']['type'] = ',baseline,';
|
||||
if($config->vision == 'lite') $config->admin->navsGroup['feature']['my'] .= 'task,';
|
||||
|
||||
global $lang, $app;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
$config->admin->register = new stdclass();
|
||||
$config->admin->register->community = 'https://www.zentao.net';
|
||||
$config->admin->register->apiRoot = 'https://www.zentao.net';
|
||||
$config->admin->register->bindCommunity = 'false';
|
||||
$config->admin->register->bindCommunityMobile = '';
|
||||
$config->admin->register->agreeUX = 'false';
|
||||
+146
-95
@@ -77,101 +77,6 @@ class admin extends control
|
||||
return $this->send(array('result' => 'success'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 登记禅道社区。
|
||||
* Register zentao.
|
||||
*
|
||||
* @param string $from admin|mail
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function register(string $from = 'admin')
|
||||
{
|
||||
if($_POST)
|
||||
{
|
||||
$response = $this->adminZen->registerByAPI();
|
||||
$response = json_decode($response);
|
||||
if($response->result == 'fail')
|
||||
{
|
||||
$message = '';
|
||||
if(is_string($response->message))
|
||||
{
|
||||
$message = $response->message;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach($response->message as $item) $message .= is_array($item) ? join('\n', $item) . '\n' : $item . '\n';
|
||||
}
|
||||
$message = str_replace(array('<strong>', '</strong>'), '', $message);
|
||||
|
||||
return $this->send(array('result' => 'fail', 'message' => $message));
|
||||
}
|
||||
|
||||
$user = $response->data;
|
||||
$data['community'] = $user->account;
|
||||
$data['ztPrivateKey'] = $user->private;
|
||||
|
||||
$this->loadModel('setting');
|
||||
$this->setting->deleteItems('owner=system&module=common§ion=global&key=community');
|
||||
$this->setting->deleteItems('owner=system&module=common§ion=global&key=ztPrivateKey');
|
||||
$this->setting->setItems('system.common.global', $data);
|
||||
|
||||
$locate = true;
|
||||
if($from == 'admin') $locate = inlink('index');
|
||||
if($from == 'mail') $locate = $this->createLink('mail', 'ztcloud');
|
||||
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->admin->registerNotice->success, 'load' => $locate));
|
||||
}
|
||||
|
||||
$this->adminZen->initSN();
|
||||
|
||||
$this->view->title = $this->lang->admin->registerNotice->caption;
|
||||
$this->view->register = $this->adminZen->getRegisterInfo();
|
||||
$this->view->sn = $this->config->global->sn;
|
||||
$this->view->from = $from;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定禅道账号。
|
||||
* Bind zentao.
|
||||
*
|
||||
* @param string $from admin|mail
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function bind(string $from = 'admin')
|
||||
{
|
||||
if($_POST)
|
||||
{
|
||||
$response = $this->adminZen->bindByAPI();
|
||||
$response = json_decode($response);
|
||||
|
||||
if($response->result == 'fail') return $this->send($response);
|
||||
|
||||
$user = $response->data;
|
||||
$data['community'] = $user->account;
|
||||
$data['ztPrivateKey'] = $user->private;
|
||||
|
||||
$this->loadModel('setting')->deleteItems('owner=system&module=common§ion=global&key=community');
|
||||
$this->setting->deleteItems('owner=system&module=common§ion=global&key=ztPrivateKey');
|
||||
$this->setting->setItems('system.common.global', $data);
|
||||
|
||||
$locate = true;
|
||||
if($from == 'admin') $locate = inlink('index');
|
||||
if($from == 'mail') $locate = $this->createLink('mail', 'ztcloud');
|
||||
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->admin->bind->success, 'load' => $locate));
|
||||
}
|
||||
|
||||
$this->adminZen->initSN();
|
||||
|
||||
$this->view->title = $this->lang->admin->bind->caption;
|
||||
$this->view->sn = $this->config->global->sn;
|
||||
$this->view->from = $from;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统安全设置。
|
||||
* System security Settings.
|
||||
@@ -590,4 +495,150 @@ class admin extends control
|
||||
|
||||
echo 'success';
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定社区账号。
|
||||
* Bind community account.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
if($this->loadModel('user')->isLogon() && !$this->app->user->admin) $this->locate(helper::createLink('user', 'deny', 'module=admin&method=register'));
|
||||
|
||||
$bindCommunity = $this->config->admin->register->bindCommunity == 'true';
|
||||
$agreeUX = $this->config->admin->register->agreeUX == 'true';
|
||||
|
||||
$this->view->bindCommunity = $bindCommunity;
|
||||
$this->view->agreeUX = $agreeUX;
|
||||
|
||||
if($bindCommunity)
|
||||
{
|
||||
if(!$this->loadModel('user')->isLogon()) $this->locate(helper::createLink('user', 'deny', 'module=admin&method=register'));
|
||||
$bindCommunityMobile = $this->config->admin->register->bindCommunityMobile;
|
||||
$this->view->bindCommunityMobile = $bindCommunityMobile;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!empty($_POST))
|
||||
{
|
||||
if(!$this->post->mobile || !$this->post->code) return $this->send(array('result' => 'fail', 'message' => $this->lang->admin->register->loginFailedNoInfo));
|
||||
|
||||
$apiRoot = $this->config->admin->register->apiRoot;
|
||||
$sessionVar = $this->config->sessionVar;
|
||||
$zentaosid = $_COOKIE[$sessionVar];
|
||||
$apiURL = $apiRoot . "/user-apiRegister.json" . "?{$sessionVar}={$zentaosid}";
|
||||
|
||||
if(empty($this->config->global->sn)) $this->loadModel('setting')->setSN();
|
||||
$httpData['sn'] = $this->config->global->sn;
|
||||
$httpData['mobile'] = $this->post->mobile;
|
||||
$httpData['code'] = $this->post->code;
|
||||
|
||||
$response = common::http($apiURL, $httpData);
|
||||
|
||||
$response = json_decode($response, true);
|
||||
|
||||
if(isset($response['result']) && $response['result'] == 'success')
|
||||
{
|
||||
$this->loadModel('setting')->setItem('system.admin.register.bindCommunity', 'true');
|
||||
$this->loadModel('setting')->setItem('system.admin.register.bindCommunityMobile', $this->post->mobile);
|
||||
$this->config->admin->register->bindCommunity = 'true';
|
||||
$this->config->admin->register->bindCommunityMobile = $this->post->mobile;
|
||||
|
||||
$agreeUX = $this->post->agreeUX;
|
||||
$agreeUX = $agreeUX == 1 ? 'true' : 'false';
|
||||
$this->loadModel('setting')->setItem('system.admin.register.agreeUX', $agreeUX);
|
||||
$this->config->admin->agreeUX = $agreeUX;
|
||||
|
||||
return $this->send(array('result' => 'success', 'load' => inlink('register')));
|
||||
}
|
||||
return $this->send(array('result' => 'fail', 'message' => isset($response['message']) ? $response['message'] : $this->lang->admin->register->loginFailed));
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->admin->register->registerTitle;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解绑社区账号
|
||||
* Unbind community account。
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function unBindCommunity()
|
||||
{
|
||||
$this->loadModel('setting')->setItem('system.admin.register.bindCommunity', 'false');
|
||||
$this->loadModel('setting')->setItem('system.admin.register.bindCommunityMobile', '');
|
||||
$this->loadModel('setting')->setItem('system.admin.register.agreeUX', 'false');
|
||||
$this->config->admin->register->bindCommunity = 'false';
|
||||
$this->config->admin->register->bindCommunityMobile = '';
|
||||
$this->config->admin->register->agreeUX = 'false';
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->admin->register->unBind->success, 'load' => inlink('register')));
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换同意改进计划
|
||||
* Change the agreement to improve the plan。
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function changeAgreeUX()
|
||||
{
|
||||
$agreeUX = $this->post->agreeUX;
|
||||
$this->loadModel('setting')->setItem('system.admin.register.agreeUX', $agreeUX);
|
||||
$this->config->admin->register->agreeUX = $agreeUX;
|
||||
$message = $agreeUX == 'true' ? $this->lang->admin->register->uxPlan->agree : $this->lang->admin->register->uxPlan->cancel;
|
||||
return $this->send(array('result' => 'success', 'message' => $message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图形验证码
|
||||
* Obtain graphical captcha。
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getCaptcha()
|
||||
{
|
||||
$apiRoot = $this->config->admin->register->apiRoot;
|
||||
$sessionVar = $this->config->sessionVar;
|
||||
$zentaosid = $_COOKIE[$sessionVar];
|
||||
$apiURL = $apiRoot . "/guarder-apiGetCaptcha.json" . "?{$sessionVar}={$zentaosid}";
|
||||
$response = common::http($apiURL);
|
||||
$response = json_decode($response, true);
|
||||
return $this->send($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发动短信验证码
|
||||
* Activate SMS verification code
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function sendCode()
|
||||
{
|
||||
$apiRoot = $this->config->admin->register->apiRoot;
|
||||
$sessionVar = $this->config->sessionVar;
|
||||
$zentaosid = $_COOKIE[$sessionVar];
|
||||
$apiURL = $apiRoot . "/sms-apiSendCode.json" . "?{$sessionVar}={$zentaosid}";
|
||||
$response = common::http($apiURL, $_POST);
|
||||
$response = json_decode($response, true);
|
||||
return $this->send($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户体验改进计划详情
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function planModal()
|
||||
{
|
||||
$this->display();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#main {min-height: 94%;}
|
||||
.page-title {position: absolute; top: 1rem; float: left}
|
||||
.page-title span {margin-left: 1rem;}
|
||||
.panel-form {padding: 0; max-width: 36rem;}
|
||||
.form-title {background: linear-gradient(98.73deg, #28A5FF 1.4%, #0084FF 100%); display: block; color: #ffffff; margin: 0 auto; margin-top: 5%; max-width: 36rem; padding-left: 12px;}
|
||||
.form-title .main-title {padding-top: 26px; padding-left: 12px;}
|
||||
.form-title .sub-title {width: 24%; display: inline-block; color: #ffffff; margin-top: 28px; text-align: center;}
|
||||
.form-title .sub-title .icon {margin-right: 4px;}
|
||||
.label-text {font-size: 16px; margin-left: 10px;}
|
||||
.no-label-mobile {width: 32rem;}
|
||||
.no-label-code {width: 32rem; margin-left: 0.9rem;}
|
||||
.no-label-input {height: 40px;}
|
||||
#captchaImageLabel {margin-top: -1.5rem}
|
||||
#captchaImage {width: 8rem; margin-left: 0.8rem; display: inline;}
|
||||
#checkMobileSenderID {display: inline; cursor: pointer;}
|
||||
#captcha-btn {width: 7rem; line-height: 40px; padding-left: 2rem; font-size: 15px; color: #0084FF}
|
||||
.form-agree-ux {color: #5A6D88}
|
||||
.form-agree-ux-text {max-width: 90%;}
|
||||
#experience-plan-show {color: #0084FF}
|
||||
.open-url{display: none;}
|
||||
.captcha-mobile-sender {width: 204px; height: 124px; position: absolute; margin-left: 562px; box-shadow: 0px 2px 24px 3px #1F232914; background-color: #fff; margin-top: -16rem;}
|
||||
.captcha-wrapper {height:68px; margin-bottom: 12px;}
|
||||
.captcha-wrapper img, .image-box {width: 100%;height: 100%;}
|
||||
#checkMobileSender {height: 36px; line-height: 36px; color: #007AFF; background: #fff; padding:0;}
|
||||
#checkMobileSender:hover,#checkMobileSender:active,#checkMobileSender:focus {box-shadow: none;}
|
||||
button[type="submit"] {height: 40px; width: 120px;}
|
||||
.panel-form {padding: 0; max-width: 36rem;}
|
||||
.z-box-container {width: 100%; margin: 0 auto; background: white; border-radius: 8px; padding: 24px; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);}
|
||||
.z-bind-info-image {display: flex; align-items: center; margin-top: 0.4rem; margin-left: 0.4rem;}
|
||||
.z-bind-info-image img {width: 44px; height: 44px; margin-right: 12px;}
|
||||
.z-bind-info-website {font-size: 18px; color: #666; margin-bottom: 4px; width: 10rem; display: flex;}
|
||||
.z-bind-info-website span {width: 10rem; display: flex;}
|
||||
.z-bind-info-mobile {font-size: 15px;}
|
||||
.z-unbind-btn {border: 1px solid #E6ECF8; color: #0084FF; border-radius: 16px; padding: 6px 16px; margin-left: 12rem; font-size: 15px; line-height: 15px; width: 6rem;}
|
||||
.z-plan-info {margin-top: 20px; padding-top: 20px;}
|
||||
.z-plan-info-box {margin-top: -2px; margin-left: 12px}
|
||||
.z-plan-info-box a {color: #0084FF; text-decoration: none;}
|
||||
.z-plan-info-box span {color: #666;}
|
||||
.z-plan-info-box-text {float: left; width: 80%}
|
||||
.z-switch {float: left; display: inline-block; margin-left: 2.6rem;}
|
||||
.switch {min-height: 16px;}
|
||||
.z-switch-toggle {height: 24px; background: #0084FF; border-radius: 12px; position: relative;}
|
||||
.z-footer-btn {margin-top: 24px; display: flex; justify-content: center; align-items: center; height: 40px;}
|
||||
.z-footer-btn button {height: 40px; width: 120px; font-size: 16px;}
|
||||
.z-bind-info {border: 1px solid #f0f0f0; border-radius: 5px;height: 4.4rem;}
|
||||
.z-plan-info {border: 1px solid #f0f0f0; border-radius: 5px;height: 3.6rem;}
|
||||
.install-logo {position: relative; top: 3rem; left: 3rem; float: left; margin-right: -12rem;}
|
||||
.install-logo img {height: auto; max-width: 9rem;}
|
||||
.unbind-modal-title {font-size: 18px; font-weight: bold}
|
||||
.modal-dialog {width: 28rem; border-radius: 8px;}
|
||||
.modal-footer button {margin-left: 16.5rem;}
|
||||
.modal-footer {display: block}
|
||||
.skip-btn {float: right; margin-top: -4.5rem;margin-right: 1rem;z-index: 100;height: 40px;}
|
||||
@@ -1,20 +1,80 @@
|
||||
function sendCaptcha(event, type)
|
||||
window.changeAgreeUX = function(e)
|
||||
{
|
||||
var $target = $(event.target);
|
||||
var url = $target.data('url');
|
||||
var data = {[type]: $target.closest('.input-group').find('input').val()};
|
||||
|
||||
$.post(url, data, function(response)
|
||||
e = $(e);
|
||||
$.post($.createLink('admin', 'changeAgreeUX'),{agreeUX:e.prop('checked')},function(response)
|
||||
{
|
||||
response = JSON.parse(response);
|
||||
zui.Messager.show(response.message);
|
||||
});
|
||||
}
|
||||
|
||||
window.unBind = function()
|
||||
{
|
||||
$.post($.createLink('admin', 'unBindCommunity'),{},function(response)
|
||||
{
|
||||
response = JSON.parse(response);
|
||||
zui.Messager.show(response.message);
|
||||
if(response.result == 'success')
|
||||
{
|
||||
zui.Messager.show({content: response.message, type: 'success', time: 1500});
|
||||
setTimeout(function() {
|
||||
location.href = response.load;
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.getCaptchaContent = function(ele)
|
||||
{
|
||||
$ele = $(ele);
|
||||
$.get($.createLink('admin', 'getCaptcha'), function(response)
|
||||
{
|
||||
response = JSON.parse(response);
|
||||
if(response.result == 'success') $ele.html(response.captchaContent);
|
||||
});
|
||||
}
|
||||
|
||||
window.showCaptcha = function()
|
||||
{
|
||||
$('.captcha-mobile-sender').show();
|
||||
}
|
||||
|
||||
window.checkMobileSender = function()
|
||||
{
|
||||
$.post($.createLink('admin', 'sendCode'),{mobile:$('#mobile-captcha').val(), captchaContent: $('#captchaImage').val()},function(response)
|
||||
{
|
||||
response = JSON.parse(response);
|
||||
zui.Messager.show(response.message);
|
||||
if(response.result == 'success')
|
||||
{
|
||||
countdown = 60;
|
||||
setSmsSenderTime();
|
||||
$('.captcha-mobile-sender').hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
zui.Modal.alert(response.message);
|
||||
if(response.captchaContent) $('.captcha-box .image-box').html(response.captchaContent);
|
||||
}
|
||||
}, 'json')
|
||||
return false;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
window.setSmsSenderTime = function()
|
||||
{
|
||||
$('#captcha-btn').html(countdown + 's').off('click').removeClass('captcha-btn-class');
|
||||
smsSenderTimer = setInterval(function(){
|
||||
countdown -= 1;
|
||||
if(countdown > 0){
|
||||
$('#captcha-btn').html(countdown + 's').off('click').removeClass('captcha-btn-class');
|
||||
}else{
|
||||
window.clearInterval(smsSenderTimer);
|
||||
$('#captcha-btn').html(reSendText).on('click', function(e)
|
||||
{
|
||||
$('.captcha-mobile-sender').show();
|
||||
}).addClass('captcha-btn-class');
|
||||
}
|
||||
},1000);
|
||||
}
|
||||
|
||||
window.goCommunity = function(link)
|
||||
{
|
||||
window.open(link)
|
||||
}
|
||||
+63
-22
@@ -165,28 +165,30 @@ $lang->admin->safe->noticeWeakMode = 'The password will be checked when logging
|
||||
$lang->admin->safe->noticeStrong = 'The longer the password, the more letters, numbers, or special characters it contains, and the less repetitive the password, the more secure it is!';
|
||||
$lang->admin->safe->noticeGd = 'Your server does not have GD module installed or enabled FreeType support, you cannot use the Captcha function, Please use it after installation.';
|
||||
|
||||
$lang->admin->menuSetting['system']['name'] = 'System';
|
||||
$lang->admin->menuSetting['system']['desc'] = 'System elements configuration, such as backup, chat, security etc.';
|
||||
$lang->admin->menuSetting['user']['name'] = 'User';
|
||||
$lang->admin->menuSetting['user']['desc'] = 'Manage departments,add members and group configuration permissions.';
|
||||
$lang->admin->menuSetting['switch']['name'] = 'Switch';
|
||||
$lang->admin->menuSetting['switch']['desc'] = 'Turn on and off some functions of the system.';
|
||||
$lang->admin->menuSetting['model']['name'] = 'Model';
|
||||
$lang->admin->menuSetting['model']['desc'] = 'Configure different project management models and project common elements.';
|
||||
$lang->admin->menuSetting['feature']['name'] = 'Feature';
|
||||
$lang->admin->menuSetting['feature']['desc'] = 'Configure the elements of the system according to the function menu.';
|
||||
$lang->admin->menuSetting['template']['name'] = 'Template';
|
||||
$lang->admin->menuSetting['template']['desc'] = 'Configure the template type and template content of the document.';
|
||||
$lang->admin->menuSetting['message']['name'] = 'Message';
|
||||
$lang->admin->menuSetting['message']['desc'] = 'Configure notification paths and customize the actions to be notified.';
|
||||
$lang->admin->menuSetting['extension']['name'] = 'Extension';
|
||||
$lang->admin->menuSetting['extension']['desc'] = 'Browse and install plugins.';
|
||||
$lang->admin->menuSetting['dev']['name'] = 'Develop';
|
||||
$lang->admin->menuSetting['dev']['desc'] = 'Support for secondary development of the system.';
|
||||
$lang->admin->menuSetting['convert']['name'] = 'Data Import';
|
||||
$lang->admin->menuSetting['convert']['desc'] = 'Data import from third-party systems.';
|
||||
$lang->admin->menuSetting['ai']['name'] = 'AI Configurations';
|
||||
$lang->admin->menuSetting['ai']['desc'] = 'Support configuration and management of AI auto-suggestions, AI mini-programs, and large language models.';
|
||||
$lang->admin->menuSetting['system']['name'] = 'System';
|
||||
$lang->admin->menuSetting['system']['desc'] = 'System elements configuration, such as backup, chat, security etc.';
|
||||
$lang->admin->menuSetting['user']['name'] = 'User';
|
||||
$lang->admin->menuSetting['user']['desc'] = 'Manage departments,add members and group configuration permissions.';
|
||||
$lang->admin->menuSetting['switch']['name'] = 'Switch';
|
||||
$lang->admin->menuSetting['switch']['desc'] = 'Turn on and off some functions of the system.';
|
||||
$lang->admin->menuSetting['model']['name'] = 'Model';
|
||||
$lang->admin->menuSetting['model']['desc'] = 'Configure different project management models and project common elements.';
|
||||
$lang->admin->menuSetting['feature']['name'] = 'Feature';
|
||||
$lang->admin->menuSetting['feature']['desc'] = 'Configure the elements of the system according to the function menu.';
|
||||
$lang->admin->menuSetting['template']['name'] = 'Template';
|
||||
$lang->admin->menuSetting['template']['desc'] = 'Configure the template type and template content of the document.';
|
||||
$lang->admin->menuSetting['message']['name'] = 'Message';
|
||||
$lang->admin->menuSetting['message']['desc'] = 'Configure notification paths and customize the actions to be notified.';
|
||||
$lang->admin->menuSetting['extension']['name'] = 'Extension';
|
||||
$lang->admin->menuSetting['extension']['desc'] = 'Browse and install plugins.';
|
||||
$lang->admin->menuSetting['dev']['name'] = 'Develop';
|
||||
$lang->admin->menuSetting['dev']['desc'] = 'Support for secondary development of the system.';
|
||||
$lang->admin->menuSetting['convert']['name'] = 'Data Import';
|
||||
$lang->admin->menuSetting['convert']['desc'] = 'Data import from third-party systems.';
|
||||
$lang->admin->menuSetting['ai']['name'] = 'AI Configurations';
|
||||
$lang->admin->menuSetting['ai']['desc'] = 'Support configuration and management of AI auto-suggestions, AI mini-programs, and large language models.';
|
||||
$lang->admin->menuSetting['adminregister']['name'] = 'ZenTao community';
|
||||
$lang->admin->menuSetting['adminregister']['desc'] = 'Get the project management package, technical support services, and experience a version demo.';
|
||||
|
||||
$lang->admin->updateDynamics = 'Dynamics';
|
||||
$lang->admin->updatePatch = 'Patch';
|
||||
@@ -222,4 +224,43 @@ $lang->admin->ai->miniPrograms = 'AI Mini Programs';
|
||||
$lang->admin->ai->prompt = 'AI Prompts';
|
||||
$lang->admin->ai->assistant = 'AI Assistant';
|
||||
|
||||
$lang->admin->register = new stdclass();
|
||||
$lang->admin->register->registerTitle = 'Join ZenTao';
|
||||
$lang->admin->register->skip = 'Skip';
|
||||
$lang->admin->register->uxPlanTitle = 'ZenTao User Experience Improvement Program';
|
||||
$lang->admin->register->loginFailed = 'Login failed';
|
||||
$lang->admin->register->loginFailedNoInfo = 'Please fill in the registration information';
|
||||
$lang->admin->register->officialWebsite = '<span style="font-size: 12px;">ZenTao Official website </span>';
|
||||
$lang->admin->register->uxPlanWithBookTitle = ' "ZenTao User Experience Improvement Program" ';
|
||||
$lang->admin->register->uxPlanStatusTitle = 'Help us understand the usage of the product, you can turn off this feature in the background.';
|
||||
$lang->admin->register->mobile = 'phone number';
|
||||
$lang->admin->register->smsCode = 'Verification code';
|
||||
$lang->admin->register->sendCode = 'send code';
|
||||
$lang->admin->register->join = 'join the';
|
||||
$lang->admin->register->joinDesc = 'and help us understand the usage of the product';
|
||||
$lang->admin->register->captchaTip = 'verification code';
|
||||
$lang->admin->register->sure = 'send';
|
||||
$lang->admin->register->unBindText = 'unbind';
|
||||
$lang->admin->register->welcome = 'Welcome to join the ZenTao community. Here, you can obtain:';
|
||||
$lang->admin->register->advantage1 = 'PM Gift Pack';
|
||||
$lang->admin->register->advantage2 = 'Support Services';
|
||||
$lang->admin->register->advantage3 = 'Experience Demo';
|
||||
$lang->admin->register->advantage4 = 'ZenTao Manual';
|
||||
$lang->admin->register->goCommunity = 'Jump To';
|
||||
$lang->admin->register->enterMobile = 'Please enter your phone number';
|
||||
$lang->admin->register->enterCode = 'Please enter the verification code';
|
||||
$lang->admin->register->goBack = 'back';
|
||||
$lang->admin->register->reSend = 'resend';
|
||||
$lang->admin->register->unbindTitle = 'Are you sure you want to unbind from the ZenTao';
|
||||
$lang->admin->register->unbindContent = 'After unbinding, you will not be able to log in directly to the ZenTao official website through the ZenTao software';
|
||||
$lang->admin->register->cancelButton = 'cancel';
|
||||
$lang->admin->register->unbindButton = 'yes';
|
||||
|
||||
$lang->admin->register->uxPlan = new stdclass();
|
||||
$lang->admin->register->uxPlan->agree = 'Agreed';
|
||||
$lang->admin->register->uxPlan->cancel = 'Canceled';
|
||||
|
||||
$lang->admin->register->unBind = new stdclass();
|
||||
$lang->admin->register->unBind->success = 'Unbound';
|
||||
|
||||
include dirname(__FILE__) . '/menu.php';
|
||||
|
||||
+63
-22
@@ -165,28 +165,30 @@ $lang->admin->safe->noticeWeakMode = 'The password will be checked when logging
|
||||
$lang->admin->safe->noticeStrong = 'The longer the password, the more letters, numbers, or special characters it contains, and the less repetitive the password, the more secure it is!';
|
||||
$lang->admin->safe->noticeGd = 'Your server does not have GD module installed or enabled FreeType support, you cannot use the Captcha function, Please use it after installation.';
|
||||
|
||||
$lang->admin->menuSetting['system']['name'] = 'System';
|
||||
$lang->admin->menuSetting['system']['desc'] = 'System elements configuration, such as backup, chat, security etc.';
|
||||
$lang->admin->menuSetting['user']['name'] = 'User';
|
||||
$lang->admin->menuSetting['user']['desc'] = 'Manage departments,add members and group configuration permissions.';
|
||||
$lang->admin->menuSetting['switch']['name'] = 'Switch';
|
||||
$lang->admin->menuSetting['switch']['desc'] = 'Turn on and off some functions of the system.';
|
||||
$lang->admin->menuSetting['model']['name'] = 'Model';
|
||||
$lang->admin->menuSetting['model']['desc'] = 'Configure different project management models and project common elements.';
|
||||
$lang->admin->menuSetting['feature']['name'] = 'Feature';
|
||||
$lang->admin->menuSetting['feature']['desc'] = 'Configure the elements of the system according to the function menu.';
|
||||
$lang->admin->menuSetting['template']['name'] = 'Template';
|
||||
$lang->admin->menuSetting['template']['desc'] = 'Configure the template type and template content of the document.';
|
||||
$lang->admin->menuSetting['message']['name'] = 'Message';
|
||||
$lang->admin->menuSetting['message']['desc'] = 'Configure notification paths and customize the actions to be notified.';
|
||||
$lang->admin->menuSetting['extension']['name'] = 'Extension';
|
||||
$lang->admin->menuSetting['extension']['desc'] = 'Browse and install plugins.';
|
||||
$lang->admin->menuSetting['dev']['name'] = 'Develop';
|
||||
$lang->admin->menuSetting['dev']['desc'] = 'Support for secondary development of the system.';
|
||||
$lang->admin->menuSetting['convert']['name'] = 'Data Import';
|
||||
$lang->admin->menuSetting['convert']['desc'] = 'Data import from third-party systems.';
|
||||
$lang->admin->menuSetting['ai']['name'] = 'AI Configurations';
|
||||
$lang->admin->menuSetting['ai']['desc'] = 'Support configuration and management of AI auto-suggestions, AI mini-programs, and large language models.';
|
||||
$lang->admin->menuSetting['system']['name'] = 'System';
|
||||
$lang->admin->menuSetting['system']['desc'] = 'System elements configuration, such as backup, chat, security etc.';
|
||||
$lang->admin->menuSetting['user']['name'] = 'User';
|
||||
$lang->admin->menuSetting['user']['desc'] = 'Manage departments,add members and group configuration permissions.';
|
||||
$lang->admin->menuSetting['switch']['name'] = 'Switch';
|
||||
$lang->admin->menuSetting['switch']['desc'] = 'Turn on and off some functions of the system.';
|
||||
$lang->admin->menuSetting['model']['name'] = 'Model';
|
||||
$lang->admin->menuSetting['model']['desc'] = 'Configure different project management models and project common elements.';
|
||||
$lang->admin->menuSetting['feature']['name'] = 'Feature';
|
||||
$lang->admin->menuSetting['feature']['desc'] = 'Configure the elements of the system according to the function menu.';
|
||||
$lang->admin->menuSetting['template']['name'] = 'Template';
|
||||
$lang->admin->menuSetting['template']['desc'] = 'Configure the template type and template content of the document.';
|
||||
$lang->admin->menuSetting['message']['name'] = 'Message';
|
||||
$lang->admin->menuSetting['message']['desc'] = 'Configure notification paths and customize the actions to be notified.';
|
||||
$lang->admin->menuSetting['extension']['name'] = 'Extension';
|
||||
$lang->admin->menuSetting['extension']['desc'] = 'Browse and install plugins.';
|
||||
$lang->admin->menuSetting['dev']['name'] = 'Develop';
|
||||
$lang->admin->menuSetting['dev']['desc'] = 'Support for secondary development of the system.';
|
||||
$lang->admin->menuSetting['convert']['name'] = 'Data Import';
|
||||
$lang->admin->menuSetting['convert']['desc'] = 'Data import from third-party systems.';
|
||||
$lang->admin->menuSetting['ai']['name'] = 'AI Configurations';
|
||||
$lang->admin->menuSetting['ai']['desc'] = 'Support configuration and management of AI auto-suggestions, AI mini-programs, and large language models.';
|
||||
$lang->admin->menuSetting['adminregister']['name'] = 'ZenTao community';
|
||||
$lang->admin->menuSetting['adminregister']['desc'] = 'Get the project management package, technical support services, and experience a version demo.';
|
||||
|
||||
$lang->admin->updateDynamics = 'Dynamics';
|
||||
$lang->admin->updatePatch = 'Patch';
|
||||
@@ -222,4 +224,43 @@ $lang->admin->ai->miniPrograms = 'AI Mini Programs';
|
||||
$lang->admin->ai->prompt = 'AI Prompts';
|
||||
$lang->admin->ai->assistant = 'AI Assistant';
|
||||
|
||||
$lang->admin->register = new stdclass();
|
||||
$lang->admin->register->registerTitle = 'Join ZenTao';
|
||||
$lang->admin->register->skip = 'Skip';
|
||||
$lang->admin->register->uxPlanTitle = 'ZenTao User Experience Improvement Program';
|
||||
$lang->admin->register->loginFailed = 'Login failed';
|
||||
$lang->admin->register->loginFailedNoInfo = 'Please fill in the registration information';
|
||||
$lang->admin->register->officialWebsite = '<span style="font-size: 12px;">ZenTao Official website </span>';
|
||||
$lang->admin->register->uxPlanWithBookTitle = ' "ZenTao User Experience Improvement Program" ';
|
||||
$lang->admin->register->uxPlanStatusTitle = 'Help us understand the usage of the product, you can turn off this feature in the background.';
|
||||
$lang->admin->register->mobile = 'phone number';
|
||||
$lang->admin->register->smsCode = 'Verification code';
|
||||
$lang->admin->register->sendCode = 'send code';
|
||||
$lang->admin->register->join = 'join the';
|
||||
$lang->admin->register->joinDesc = 'and help us understand the usage of the product';
|
||||
$lang->admin->register->captchaTip = 'verification code';
|
||||
$lang->admin->register->sure = 'send';
|
||||
$lang->admin->register->unBindText = 'unbind';
|
||||
$lang->admin->register->welcome = 'Welcome to join the ZenTao community. Here, you can obtain:';
|
||||
$lang->admin->register->advantage1 = 'PM Gift Pack';
|
||||
$lang->admin->register->advantage2 = 'Support Services';
|
||||
$lang->admin->register->advantage3 = 'Experience Demo';
|
||||
$lang->admin->register->advantage4 = 'ZenTao Manual';
|
||||
$lang->admin->register->goCommunity = 'Jump To';
|
||||
$lang->admin->register->enterMobile = 'Please enter your phone number';
|
||||
$lang->admin->register->enterCode = 'Please enter the verification code';
|
||||
$lang->admin->register->goBack = 'back';
|
||||
$lang->admin->register->reSend = 'resend';
|
||||
$lang->admin->register->unbindTitle = 'Are you sure you want to unbind from the ZenTao';
|
||||
$lang->admin->register->unbindContent = 'After unbinding, you will not be able to log in directly to the ZenTao official website through the ZenTao software';
|
||||
$lang->admin->register->cancelButton = 'cancel';
|
||||
$lang->admin->register->unbindButton = 'yes';
|
||||
|
||||
$lang->admin->register->uxPlan = new stdclass();
|
||||
$lang->admin->register->uxPlan->agree = 'Agreed';
|
||||
$lang->admin->register->uxPlan->cancel = 'Canceled';
|
||||
|
||||
$lang->admin->register->unBind = new stdclass();
|
||||
$lang->admin->register->unBind->success = 'Unbound';
|
||||
|
||||
include dirname(__FILE__) . '/menu.php';
|
||||
|
||||
+63
-22
@@ -165,28 +165,30 @@ $lang->admin->safe->noticeWeakMode = "Le mot de passe sera vérifié lors de la
|
||||
$lang->admin->safe->noticeStrong = "Le mot de passe est d'autant plus sécurisé qu'il est long, qu'il contient plus de lettres, de chiffres ou de caractères spéciaux, et que les lettres du mot de passe sont peu répétitives !";
|
||||
$lang->admin->safe->noticeGd = 'Your server does not have GD module installed or enabled FreeType support, you cannot use the Captcha function, Please use it after installation.';
|
||||
|
||||
$lang->admin->menuSetting['system']['name'] = 'System';
|
||||
$lang->admin->menuSetting['system']['desc'] = 'System elements configuration, such as backup, chat, security etc.';
|
||||
$lang->admin->menuSetting['user']['name'] = 'User';
|
||||
$lang->admin->menuSetting['user']['desc'] = 'Manage departments,add members and group configuration permissions.';
|
||||
$lang->admin->menuSetting['switch']['name'] = 'Switch';
|
||||
$lang->admin->menuSetting['switch']['desc'] = 'Turn on and off some functions of the system.';
|
||||
$lang->admin->menuSetting['model']['name'] = 'Model';
|
||||
$lang->admin->menuSetting['model']['desc'] = 'Configure different project management models and project common elements.';
|
||||
$lang->admin->menuSetting['feature']['name'] = 'Feature';
|
||||
$lang->admin->menuSetting['feature']['desc'] = 'Configure the elements of the system according to the function menu.';
|
||||
$lang->admin->menuSetting['template']['name'] = 'Template';
|
||||
$lang->admin->menuSetting['template']['desc'] = 'Configure the template type and template content of the document.';
|
||||
$lang->admin->menuSetting['message']['name'] = 'Message';
|
||||
$lang->admin->menuSetting['message']['desc'] = 'Configure notification paths and customize the actions to be notified.';
|
||||
$lang->admin->menuSetting['extension']['name'] = 'Extension';
|
||||
$lang->admin->menuSetting['extension']['desc'] = 'Browse and install plugins.';
|
||||
$lang->admin->menuSetting['dev']['name'] = 'Develop';
|
||||
$lang->admin->menuSetting['dev']['desc'] = 'Support for secondary development of the system.';
|
||||
$lang->admin->menuSetting['convert']['name'] = 'Data Import';
|
||||
$lang->admin->menuSetting['convert']['desc'] = 'Data import from third-party systems.';
|
||||
$lang->admin->menuSetting['ai']['name'] = 'AI Configurations';
|
||||
$lang->admin->menuSetting['ai']['desc'] = 'Support configuration and management of AI auto-suggestions, AI mini-programs, and large language models.';
|
||||
$lang->admin->menuSetting['system']['name'] = 'System';
|
||||
$lang->admin->menuSetting['system']['desc'] = 'System elements configuration, such as backup, chat, security etc.';
|
||||
$lang->admin->menuSetting['user']['name'] = 'User';
|
||||
$lang->admin->menuSetting['user']['desc'] = 'Manage departments,add members and group configuration permissions.';
|
||||
$lang->admin->menuSetting['switch']['name'] = 'Switch';
|
||||
$lang->admin->menuSetting['switch']['desc'] = 'Turn on and off some functions of the system.';
|
||||
$lang->admin->menuSetting['model']['name'] = 'Model';
|
||||
$lang->admin->menuSetting['model']['desc'] = 'Configure different project management models and project common elements.';
|
||||
$lang->admin->menuSetting['feature']['name'] = 'Feature';
|
||||
$lang->admin->menuSetting['feature']['desc'] = 'Configure the elements of the system according to the function menu.';
|
||||
$lang->admin->menuSetting['template']['name'] = 'Template';
|
||||
$lang->admin->menuSetting['template']['desc'] = 'Configure the template type and template content of the document.';
|
||||
$lang->admin->menuSetting['message']['name'] = 'Message';
|
||||
$lang->admin->menuSetting['message']['desc'] = 'Configure notification paths and customize the actions to be notified.';
|
||||
$lang->admin->menuSetting['extension']['name'] = 'Extension';
|
||||
$lang->admin->menuSetting['extension']['desc'] = 'Browse and install plugins.';
|
||||
$lang->admin->menuSetting['dev']['name'] = 'Develop';
|
||||
$lang->admin->menuSetting['dev']['desc'] = 'Support for secondary development of the system.';
|
||||
$lang->admin->menuSetting['convert']['name'] = 'Data Import';
|
||||
$lang->admin->menuSetting['convert']['desc'] = 'Data import from third-party systems.';
|
||||
$lang->admin->menuSetting['ai']['name'] = 'AI Configurations';
|
||||
$lang->admin->menuSetting['ai']['desc'] = 'Support configuration and management of AI auto-suggestions, AI mini-programs, and large language models.';
|
||||
$lang->admin->menuSetting['adminregister']['name'] = 'ZenTao community';
|
||||
$lang->admin->menuSetting['adminregister']['desc'] = 'Get the project management package, technical support services, and experience a version demo.';
|
||||
|
||||
$lang->admin->updateDynamics = 'Dynamics';
|
||||
$lang->admin->updatePatch = 'Patch';
|
||||
@@ -222,4 +224,43 @@ $lang->admin->ai->miniPrograms = 'AI Mini Programs';
|
||||
$lang->admin->ai->prompt = 'AI Prompts';
|
||||
$lang->admin->ai->assistant = 'AI Assistant';
|
||||
|
||||
$lang->admin->register = new stdclass();
|
||||
$lang->admin->register->registerTitle = 'Join ZenTao';
|
||||
$lang->admin->register->skip = 'Skip';
|
||||
$lang->admin->register->uxPlanTitle = 'ZenTao User Experience Improvement Program';
|
||||
$lang->admin->register->loginFailed = 'Login failed';
|
||||
$lang->admin->register->loginFailedNoInfo = 'Please fill in the registration information';
|
||||
$lang->admin->register->officialWebsite = '<span style="font-size: 12px;">ZenTao Official website </span>';
|
||||
$lang->admin->register->uxPlanWithBookTitle = ' "ZenTao User Experience Improvement Program" ';
|
||||
$lang->admin->register->uxPlanStatusTitle = 'Help us understand the usage of the product, you can turn off this feature in the background.';
|
||||
$lang->admin->register->mobile = 'phone number';
|
||||
$lang->admin->register->smsCode = 'Verification code';
|
||||
$lang->admin->register->sendCode = 'send code';
|
||||
$lang->admin->register->join = 'join the';
|
||||
$lang->admin->register->joinDesc = 'and help us understand the usage of the product';
|
||||
$lang->admin->register->captchaTip = 'verification code';
|
||||
$lang->admin->register->sure = 'send';
|
||||
$lang->admin->register->unBindText = 'unbind';
|
||||
$lang->admin->register->welcome = 'Welcome to join the ZenTao community. Here, you can obtain:';
|
||||
$lang->admin->register->advantage1 = 'PM Gift Pack';
|
||||
$lang->admin->register->advantage2 = 'Support Services';
|
||||
$lang->admin->register->advantage3 = 'Experience Demo';
|
||||
$lang->admin->register->advantage4 = 'ZenTao Manual';
|
||||
$lang->admin->register->goCommunity = 'Jump To';
|
||||
$lang->admin->register->enterMobile = 'Please enter your phone number';
|
||||
$lang->admin->register->enterCode = 'Please enter the verification code';
|
||||
$lang->admin->register->goBack = 'back';
|
||||
$lang->admin->register->reSend = 'resend';
|
||||
$lang->admin->register->unbindTitle = 'Are you sure you want to unbind from the ZenTao';
|
||||
$lang->admin->register->unbindContent = 'After unbinding, you will not be able to log in directly to the ZenTao official website through the ZenTao software';
|
||||
$lang->admin->register->cancelButton = 'cancel';
|
||||
$lang->admin->register->unbindButton = 'yes';
|
||||
|
||||
$lang->admin->register->uxPlan = new stdclass();
|
||||
$lang->admin->register->uxPlan->agree = 'Agreed';
|
||||
$lang->admin->register->uxPlan->cancel = 'Canceled';
|
||||
|
||||
$lang->admin->register->unBind = new stdclass();
|
||||
$lang->admin->register->unBind->success = 'Unbound';
|
||||
|
||||
include dirname(__FILE__) . '/menu.php';
|
||||
|
||||
@@ -22,10 +22,6 @@ $lang->admin->menuList->feature['name'] = $lang->admin->menuSetting['feature'][
|
||||
$lang->admin->menuList->feature['desc'] = $lang->admin->menuSetting['feature']['desc'];
|
||||
$lang->admin->menuList->feature['order'] = 25;
|
||||
|
||||
$lang->admin->menuList->template['name'] = $lang->admin->menuSetting['template']['name'];
|
||||
$lang->admin->menuList->template['desc'] = $lang->admin->menuSetting['template']['desc'];
|
||||
$lang->admin->menuList->template['order'] = 30;
|
||||
|
||||
$lang->admin->menuList->message['name'] = $lang->admin->menuSetting['message']['name'];
|
||||
$lang->admin->menuList->message['desc'] = $lang->admin->menuSetting['message']['desc'];
|
||||
$lang->admin->menuList->message['order'] = 35;
|
||||
@@ -74,11 +70,11 @@ $lang->admin->menuList->company['menuOrder']['5'] = 'dept';
|
||||
$lang->admin->menuList->company['menuOrder']['10'] = 'browseUser';
|
||||
$lang->admin->menuList->company['menuOrder']['15'] = 'group';
|
||||
|
||||
$lang->admin->menuList->model['subMenu']['common'] = array('link' => "{$lang->globalSetting}|custom|required|module=project", 'subModule' => 'custom,subject,holiday,stage,deliverable', 'exclude' => 'stage-browse,stage-plusbrowse,stage-create,stage-edit,stage-batchcreate');
|
||||
$lang->admin->menuList->model['subMenu']['common'] = array('link' => "{$lang->globalSetting}|custom|required|module=project", 'subModule' => 'custom,subject,holiday,stage,deliverable,baseline', 'exclude' => 'stage-browse,stage-plusbrowse,stage-create,stage-edit,stage-batchcreate');
|
||||
$lang->admin->menuList->model['subMenu']['scrum'] = array('link' => "{$lang->scrumModel}|auditcl|scrumbrowse|", 'subModule' => 'auditcl');
|
||||
$lang->admin->menuList->model['subMenu']['waterfall'] = array('link' => "{$lang->waterfallModel}|stage|browse|", 'subModule' => 'stage', 'exclude' => 'stage-settype,stage-plusbrowse');
|
||||
$lang->admin->menuList->model['subMenu']['waterfall'] = array('link' => "{$lang->waterfallModel}|stage|browse|", 'subModule' => 'stage', 'exclude' => 'baseline-templatetype,stage-settype,stage-plusbrowse');
|
||||
$lang->admin->menuList->model['subMenu']['agileplus'] = array('link' => "{$lang->agilePlusModel}|auditcl|agileplusbrowse|", 'subModule' => 'auditcl');
|
||||
$lang->admin->menuList->model['subMenu']['waterfallplus'] = array('link' => "{$lang->waterfallPlusModel}|stage|plusbrowse|", 'subModule' => 'stage', 'exclude' => 'stage-settype,stage-browse');
|
||||
$lang->admin->menuList->model['subMenu']['waterfallplus'] = array('link' => "{$lang->waterfallPlusModel}|stage|plusbrowse|", 'subModule' => 'stage', 'exclude' => 'baseline-templatetype,stage-settype,stage-browse');
|
||||
|
||||
$lang->admin->menuList->model['menuOrder']['5'] = 'common';
|
||||
$lang->admin->menuList->model['menuOrder']['10'] = 'scrum';
|
||||
@@ -86,7 +82,7 @@ $lang->admin->menuList->model['menuOrder']['15'] = 'waterfall';
|
||||
$lang->admin->menuList->model['menuOrder']['20'] = 'agileplus';
|
||||
$lang->admin->menuList->model['menuOrder']['25'] = 'waterfallplus';
|
||||
|
||||
$lang->admin->menuList->model['tabMenu']['common']['project'] = array('link' => "{$lang->project->common}|custom|required|module=project", 'alias' => 'set,project', 'exclude' => 'custom-required', 'links' => array('custom|set|module=project&field=unitList'));
|
||||
$lang->admin->menuList->model['tabMenu']['common']['project'] = array('link' => "{$lang->project->common}|custom|required|module=project", 'alias' => 'project', 'exclude' => 'custom-required,baseline-templatetype', 'links' => array('custom|set|module=project&field=unitList'));
|
||||
if(helper::hasFeature('waterfall') || helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['common']['stage'] = array('link' => "{$lang->stage->type}|stage|settype|", 'subModule' => 'stage');
|
||||
if(helper::hasFeature('deliverable') && ($config->edition == 'max' || $config->edition == 'ipd')) $lang->admin->menuList->model['tabMenu']['common']['deliverable'] = array('link' => "{$lang->deliverable->common}|deliverable|browse|", 'subModule' => 'deliverable');
|
||||
$lang->admin->menuList->model['tabMenu']['common']['build'] = array('link' => "{$lang->build->common}|custom|required|module=build", 'alias' => 'set', 'exclude' => 'custom');
|
||||
@@ -210,13 +206,17 @@ if($config->edition != 'open') {
|
||||
$lang->admin->menuList->ai['menuOrder']['20'] = 'assistants';
|
||||
}
|
||||
|
||||
$lang->admin->menuList->adminregister['name'] = $lang->admin->menuSetting['adminregister']['name'];
|
||||
$lang->admin->menuList->adminregister['desc'] = $lang->admin->menuSetting['adminregister']['desc'];
|
||||
$lang->admin->menuList->adminregister['link'] = 'admin|register';
|
||||
$lang->admin->menuList->adminregister['order'] = 61;
|
||||
|
||||
if($config->edition != 'max' and $config->edition != 'ipd')
|
||||
{
|
||||
unset($lang->admin->menuList->model['subMenu']['scrum']);
|
||||
unset($lang->admin->menuList->model['subMenu']['agileplus']);
|
||||
unset($lang->admin->menuList->model['menuOrder']['10']);
|
||||
unset($lang->admin->menuList->model['menuOrder']['20']);
|
||||
unset($lang->admin->menuList->template);
|
||||
}
|
||||
if(!helper::hasFeature('waterfall'))
|
||||
{
|
||||
|
||||
+63
-22
@@ -165,28 +165,30 @@ $lang->admin->safe->noticeWeakMode = '系统会在登录、创建和修改用户
|
||||
$lang->admin->safe->noticeStrong = '密码长度越长,含有大写字母或数字或特殊符号越多,密码字母越不重复,安全度越强!';
|
||||
$lang->admin->safe->noticeGd = '系统检测到您的服务器未安装GD模块或未启用FreeType支持,无法使用验证码功能,请安装后使用。';
|
||||
|
||||
$lang->admin->menuSetting['system']['name'] = '系统设置';
|
||||
$lang->admin->menuSetting['system']['desc'] = '备份、聊天、安全等系统各要素配置。';
|
||||
$lang->admin->menuSetting['user']['name'] = '人员管理';
|
||||
$lang->admin->menuSetting['user']['desc'] = '维护部门、添加人员、分组配置权限。';
|
||||
$lang->admin->menuSetting['switch']['name'] = '功能开关';
|
||||
$lang->admin->menuSetting['switch']['desc'] = '打开、关闭系统部分功能。';
|
||||
$lang->admin->menuSetting['model']['name'] = '项目模型配置';
|
||||
$lang->admin->menuSetting['model']['desc'] = '不同项目管理模型和项目通用要素配置。';
|
||||
$lang->admin->menuSetting['feature']['name'] = '功能配置';
|
||||
$lang->admin->menuSetting['feature']['desc'] = '按照功能菜单进行系统的要素配置。';
|
||||
$lang->admin->menuSetting['template']['name'] = '文档模板';
|
||||
$lang->admin->menuSetting['template']['desc'] = '配置文档的模板类型和模板内容。';
|
||||
$lang->admin->menuSetting['message']['name'] = '通知设置';
|
||||
$lang->admin->menuSetting['message']['desc'] = '配置通知路径,自定义需要通知的动作。';
|
||||
$lang->admin->menuSetting['extension']['name'] = '插件管理';
|
||||
$lang->admin->menuSetting['extension']['desc'] = '浏览、安装插件。';
|
||||
$lang->admin->menuSetting['dev']['name'] = '二次开发';
|
||||
$lang->admin->menuSetting['dev']['desc'] = '支持对系统进行二次开发。';
|
||||
$lang->admin->menuSetting['convert']['name'] = '数据导入';
|
||||
$lang->admin->menuSetting['convert']['desc'] = '第三方系统的数据导入。';
|
||||
$lang->admin->menuSetting['ai']['name'] = 'AI 配置';
|
||||
$lang->admin->menuSetting['ai']['desc'] = '支持配置与管理AI提词、AI小程序及大语言模型。';
|
||||
$lang->admin->menuSetting['system']['name'] = '系统设置';
|
||||
$lang->admin->menuSetting['system']['desc'] = '备份、聊天、安全等系统各要素配置。';
|
||||
$lang->admin->menuSetting['user']['name'] = '人员管理';
|
||||
$lang->admin->menuSetting['user']['desc'] = '维护部门、添加人员、分组配置权限。';
|
||||
$lang->admin->menuSetting['switch']['name'] = '功能开关';
|
||||
$lang->admin->menuSetting['switch']['desc'] = '打开、关闭系统部分功能。';
|
||||
$lang->admin->menuSetting['model']['name'] = '项目模型配置';
|
||||
$lang->admin->menuSetting['model']['desc'] = '不同项目管理模型和项目通用要素配置。';
|
||||
$lang->admin->menuSetting['feature']['name'] = '功能配置';
|
||||
$lang->admin->menuSetting['feature']['desc'] = '按照功能菜单进行系统的要素配置。';
|
||||
$lang->admin->menuSetting['template']['name'] = '文档模板';
|
||||
$lang->admin->menuSetting['template']['desc'] = '配置文档的模板类型和模板内容。';
|
||||
$lang->admin->menuSetting['message']['name'] = '通知设置';
|
||||
$lang->admin->menuSetting['message']['desc'] = '配置通知路径,自定义需要通知的动作。';
|
||||
$lang->admin->menuSetting['extension']['name'] = '插件管理';
|
||||
$lang->admin->menuSetting['extension']['desc'] = '浏览、安装插件。';
|
||||
$lang->admin->menuSetting['dev']['name'] = '二次开发';
|
||||
$lang->admin->menuSetting['dev']['desc'] = '支持对系统进行二次开发。';
|
||||
$lang->admin->menuSetting['convert']['name'] = '数据导入';
|
||||
$lang->admin->menuSetting['convert']['desc'] = '第三方系统的数据导入。';
|
||||
$lang->admin->menuSetting['ai']['name'] = 'AI 配置';
|
||||
$lang->admin->menuSetting['ai']['desc'] = '支持配置与管理AI提词、AI小程序及大语言模型。';
|
||||
$lang->admin->menuSetting['adminregister']['name'] = '加入禅道社区';
|
||||
$lang->admin->menuSetting['adminregister']['desc'] = '获取项目管理大礼包、技术支持服务、体验个版本Demo。';
|
||||
|
||||
$lang->admin->updateDynamics = '更新动态';
|
||||
$lang->admin->updatePatch = '补丁更新';
|
||||
@@ -222,4 +224,43 @@ $lang->admin->ai->miniPrograms = 'AI 小程序';
|
||||
$lang->admin->ai->prompt = 'AI 提词';
|
||||
$lang->admin->ai->assistant = 'AI 助手';
|
||||
|
||||
$lang->admin->register = new stdclass();
|
||||
$lang->admin->register->registerTitle = '加入禅道社区';
|
||||
$lang->admin->register->skip = '跳过';
|
||||
$lang->admin->register->uxPlanTitle = '禅道用户体验改进计划';
|
||||
$lang->admin->register->loginFailed = '登录失败';
|
||||
$lang->admin->register->loginFailedNoInfo = '请填写注册信息';
|
||||
$lang->admin->register->officialWebsite = '禅道官网 ';
|
||||
$lang->admin->register->uxPlanWithBookTitle = '《禅道用户体验改进计划》';
|
||||
$lang->admin->register->uxPlanStatusTitle = '帮助我们了解产品使用情况,您可在后台关闭此功能。';
|
||||
$lang->admin->register->mobile = '手机号';
|
||||
$lang->admin->register->smsCode = '验证码';
|
||||
$lang->admin->register->sendCode = '获取验证码';
|
||||
$lang->admin->register->join = '加入';
|
||||
$lang->admin->register->joinDesc = '帮助我们了解产品使用情况。';
|
||||
$lang->admin->register->captchaTip = '请输入图形验证码';
|
||||
$lang->admin->register->sure = '确定';
|
||||
$lang->admin->register->unBindText = '解绑';
|
||||
$lang->admin->register->welcome = '欢迎您加入禅道社区。在这里,您可以获得:';
|
||||
$lang->admin->register->advantage1 = '项目管理大礼包';
|
||||
$lang->admin->register->advantage2 = '技术支持服务';
|
||||
$lang->admin->register->advantage3 = '体验各版本Demo';
|
||||
$lang->admin->register->advantage4 = '禅道软件手册';
|
||||
$lang->admin->register->goCommunity = '前往社区';
|
||||
$lang->admin->register->enterMobile = '请输入手机号';
|
||||
$lang->admin->register->enterCode = '请输入验证码';
|
||||
$lang->admin->register->goBack = '返回';
|
||||
$lang->admin->register->reSend = '重新发送';
|
||||
$lang->admin->register->unbindTitle = '确认与禅道解绑吗';
|
||||
$lang->admin->register->unbindContent = '解绑后将无法通过禅道软件直接登录禅道官网';
|
||||
$lang->admin->register->cancelButton = '取消';
|
||||
$lang->admin->register->unbindButton = '解绑';
|
||||
|
||||
$lang->admin->register->uxPlan = new stdclass();
|
||||
$lang->admin->register->uxPlan->agree = '已同意';
|
||||
$lang->admin->register->uxPlan->cancel = '已取消';
|
||||
|
||||
$lang->admin->register->unBind = new stdclass();
|
||||
$lang->admin->register->unBind->success = '已解绑';
|
||||
|
||||
include dirname(__FILE__) . '/menu.php';
|
||||
|
||||
@@ -205,6 +205,8 @@ class adminModel extends model
|
||||
if(common::hasPriv($module, $method)) $menu['disabled'] = false;
|
||||
}
|
||||
|
||||
if(!$this->app->user->admin && $module . $method == 'adminregister') $menu['disabled'] = true;
|
||||
|
||||
$order = $menu['order'];
|
||||
$orders[$order] = $menuKey;
|
||||
|
||||
|
||||
@@ -20,9 +20,6 @@ cid=1
|
||||
- 访问自定义待办页面 @feature
|
||||
- 访问自定义产品页面 @feature
|
||||
- 访问自定义看板页面 @feature
|
||||
- 访问模板类型页面 @template
|
||||
- 访问文档模板页面 @template
|
||||
- 访问文档目录页面 @template
|
||||
- 访问发信配置页面 @message
|
||||
- 访问Webhook页面 @message
|
||||
- 访问短信页面 @message
|
||||
@@ -61,9 +58,6 @@ r($admin->getMenuKeyTest('auditcl', 'scrumbrowse')) && p() && e('model'
|
||||
r($admin->getMenuKeyTest('custom', 'set', $params2)) && p() && e('feature'); //访问自定义待办页面
|
||||
r($admin->getMenuKeyTest('custom', 'product')) && p() && e('feature'); //访问自定义产品页面
|
||||
r($admin->getMenuKeyTest('custom', 'kanban')) && p() && e('feature'); //访问自定义看板页面
|
||||
r($admin->getMenuKeyTest('custom', 'set', $params3)) && p() && e('template'); //访问模板类型页面
|
||||
r($admin->getMenuKeyTest('baseline', 'template')) && p() && e('template'); //访问文档模板页面
|
||||
r($admin->getMenuKeyTest('baseline', 'catalog')) && p() && e('template'); //访问文档目录页面
|
||||
r($admin->getMenuKeyTest('mail', 'detect')) && p() && e('message'); //访问发信配置页面
|
||||
r($admin->getMenuKeyTest('webhook', 'browse')) && p() && e('message'); //访问Webhook页面
|
||||
r($admin->getMenuKeyTest('sms', 'index')) && p() && e('message'); //访问短信页面
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* The plan modal view file of admin module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
|
||||
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author Jialiang Zhang <zhangjialiang@chandao.com>
|
||||
* @package admin
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
|
||||
namespace zin;
|
||||
|
||||
modalHeader(set::title($this->lang->admin->register->uxPlanTitle));
|
||||
|
||||
$uxPlan = '';
|
||||
$uxPlanFile = $this->app->getAppRoot() . 'www/uxplan.html';
|
||||
if(file_exists($uxPlanFile))
|
||||
{
|
||||
$uxPlan = file_get_contents($uxPlanFile);
|
||||
}
|
||||
|
||||
echo $uxPlan;
|
||||
+293
-132
@@ -1,157 +1,318 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* The register view file of admin module of ZenTaoPMS.
|
||||
* The index view file of admin module of ZenTaoPMS.
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
|
||||
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author Gang Liu <liugang@easycorp.ltd>
|
||||
* @author Jialiang Zhang <zhangjialiang@chandao.com>
|
||||
* @package admin
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
$canBind = hasPriv('admin', 'bind');
|
||||
global $app;
|
||||
$app->loadLang('admin');
|
||||
jsVar('reSendText', $lang->admin->register->reSend);
|
||||
|
||||
$account = zget($config->global, 'community', '');
|
||||
if($account == 'na') $account = '';
|
||||
use function Symfony\Component\String\b;
|
||||
|
||||
$buildCaptchRow = function($type) : node
|
||||
set::zui(true);
|
||||
|
||||
$checked = $agreeUX == 'true' ? 'checked' : '';
|
||||
|
||||
if(strpos($_SERVER['REQUEST_URI'], '_single=1') !== false)
|
||||
{
|
||||
global $lang;
|
||||
return formRow
|
||||
(
|
||||
formGroup
|
||||
$backBtn = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$backBtn = div(
|
||||
setClass('page-title'),
|
||||
a(
|
||||
icon(setClass('icon icon-back')),
|
||||
setClass('btn capitalize primary'),
|
||||
set::href(helper::createLink('admin')),
|
||||
$lang->admin->register->goBack
|
||||
),
|
||||
span($lang->admin->register->registerTitle),
|
||||
);
|
||||
}
|
||||
|
||||
if (strpos($_SERVER['REQUEST_URI'], '_single=1') !== false) {
|
||||
$skip = div
|
||||
(
|
||||
setClass('w-1/2'),
|
||||
set::label($lang->user->$type),
|
||||
set::required(true),
|
||||
inputGroup
|
||||
(
|
||||
input
|
||||
(
|
||||
set::name($type)
|
||||
a(
|
||||
setClass('btn capitalize skip-btn'),
|
||||
$lang->admin->register->skip,
|
||||
set::href(createLink('user', 'login')),
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$skip = '';
|
||||
}
|
||||
|
||||
if($bindCommunity)
|
||||
{
|
||||
$backBtn;
|
||||
div
|
||||
(
|
||||
setID('main'),
|
||||
setClass('flex justify-center'),
|
||||
div
|
||||
(
|
||||
setID('mainContent'),
|
||||
setClass('px-1 mt-2 w-full max-w-7xl'),
|
||||
div(
|
||||
setClass('panel panel-form pt-4 size-sm is-lite'),
|
||||
div(
|
||||
setClass('max-w-7xl h-32 form-title'),
|
||||
div(setClass('main-title text-xl'),$lang->admin->register->welcome),
|
||||
div(setClass('sub-title'), icon(setClass('icon icon-diamond')), $lang->admin->register->advantage1),
|
||||
div(setClass('sub-title'), icon(setClass('icon icon-team')), $lang->admin->register->advantage2),
|
||||
div(setClass('sub-title'), icon(setClass('icon icon-statistic')), $lang->admin->register->advantage3),
|
||||
div(setClass('sub-title'), icon(setClass('icon icon-manual')), $lang->admin->register->advantage4),
|
||||
),
|
||||
span
|
||||
(
|
||||
setClass('input-group-btn'),
|
||||
button
|
||||
div(
|
||||
setClass('z-box-container'),
|
||||
div(
|
||||
setClass('z-bind-info'),
|
||||
div(
|
||||
setClass('z-bind-info-image'),
|
||||
img(set::src('static/images/register-logo.png')),
|
||||
div(
|
||||
div(setClass('z-bind-info-website'),html(nl2br($lang->admin->register->officialWebsite))),
|
||||
div(setClass('z-bind-info-mobile'),$bindCommunityMobile)
|
||||
),
|
||||
button(
|
||||
icon
|
||||
(
|
||||
setClass('icon icon-rocket')
|
||||
),
|
||||
setData(array('position' => 'center', 'toggle' => 'modal', 'target' => '#positionModal')),
|
||||
setClass('btn btn-primary z-unbind-btn'),
|
||||
setID('unBind'),
|
||||
$lang->admin->register->unBindText,
|
||||
),
|
||||
div(
|
||||
setID('positionModal'),
|
||||
setClass('modal'),
|
||||
div(
|
||||
setClass('modal-dialog shadow'),
|
||||
div(
|
||||
setClass('modal-content'),
|
||||
div(
|
||||
setClass('modal-body'),
|
||||
p(setClass('unbind-modal-title'), $lang->admin->register->unbindTitle),
|
||||
p(setClass('unbind-modal-content'),$lang->admin->register->unbindContent)
|
||||
),
|
||||
div(
|
||||
setClass('modal-footer'),
|
||||
button(
|
||||
setClass('btn'),
|
||||
set::type('button'),
|
||||
setData(array('dismiss' => 'modal')),
|
||||
$lang->admin->register->cancelButton
|
||||
),
|
||||
button(
|
||||
setClass('btn primary'),
|
||||
set::type('button'),
|
||||
$lang->admin->register->unbindButton,
|
||||
on::click()->call('unBind')
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
div(
|
||||
setClass('z-plan-info'),
|
||||
div(
|
||||
setClass('z-plan-info-box'),
|
||||
div(
|
||||
setClass('z-plan-info-box-text'),
|
||||
span($lang->admin->register->join),
|
||||
a
|
||||
(
|
||||
setID('experience-plan-show'),
|
||||
set('data-size', 'sm'),
|
||||
$lang->admin->register->uxPlanWithBookTitle,
|
||||
set::href(createLink('admin', 'planModal')),
|
||||
set('data-toggle', 'modal')
|
||||
),
|
||||
span($lang->admin->register->joinDesc)
|
||||
),
|
||||
div(
|
||||
setClass('z-switch'),
|
||||
switcher
|
||||
(
|
||||
setClass('z-switch-toggle'),
|
||||
setID('agreeUX'),
|
||||
set('checked', $checked),
|
||||
on::change()->call('changeAgreeUX', '#agreeUX'),
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
div
|
||||
(
|
||||
on::click("sendCaptcha(event, '{$type}')"),
|
||||
setClass('btn'),
|
||||
set(array('data-url' => inlink('ajaxSendCode', "type={$type}"))),
|
||||
$lang->admin->getCaptcha
|
||||
setClass('z-footer-btn'),
|
||||
button(
|
||||
setClass('btn capitalize primary'),
|
||||
$lang->admin->register->goCommunity,
|
||||
on::click()->call('goCommunity', $config->admin->register->community),
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
setClass('w-1/2'),
|
||||
set::label($lang->admin->captcha),
|
||||
set::name("{$type}Code"),
|
||||
set::required(true)
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
$buildHidden = function($sn, $siteName): array
|
||||
}
|
||||
else
|
||||
{
|
||||
$items[] = input
|
||||
$backBtn;
|
||||
div
|
||||
(
|
||||
set::type('hidden'),
|
||||
set::name('sn'),
|
||||
set::value($sn)
|
||||
);
|
||||
$items[] = input
|
||||
(
|
||||
set::type('hidden'),
|
||||
set::name($siteName),
|
||||
set::value(common::getSysURL())
|
||||
);
|
||||
return $items;
|
||||
};
|
||||
|
||||
div
|
||||
(
|
||||
setClass('flex'),
|
||||
col
|
||||
(
|
||||
setClass($canBind ? 'pr-2 w-1/2' : 'w-full'),
|
||||
formPanel
|
||||
setID('main'),
|
||||
setClass('flex justify-center'),
|
||||
div
|
||||
(
|
||||
setClass('w-full'),
|
||||
set::actions(array('submit')),
|
||||
set::title($lang->admin->registerNotice->common),
|
||||
set::submitBtnText($lang->admin->registerNotice->submit),
|
||||
formGroup
|
||||
(
|
||||
set::label($lang->user->account),
|
||||
set::name('account'),
|
||||
set::placeholder($lang->admin->registerNotice->lblAccount),
|
||||
set::required(true)
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
set::label($lang->user->realname),
|
||||
set::name('realname'),
|
||||
set::required(true)
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
set::label($lang->user->company),
|
||||
set::name('company'),
|
||||
set::value($register->company),
|
||||
set::required(true)
|
||||
),
|
||||
empty($config->isINT) ? $buildCaptchRow('mobile') : null,
|
||||
$buildCaptchRow('email'),
|
||||
formGroup
|
||||
(
|
||||
set::label($lang->user->password),
|
||||
set::control('password'),
|
||||
set::name('password1'),
|
||||
set::placeholder($lang->admin->registerNotice->lblPasswd),
|
||||
set::required(true)
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
set::label($lang->user->password2),
|
||||
set::control('password'),
|
||||
set::name('password2'),
|
||||
set::required(true)
|
||||
),
|
||||
$buildHidden($sn, 'bindSite')
|
||||
)
|
||||
),
|
||||
$canBind ? col
|
||||
(
|
||||
setClass('pl-2 w-1/2'),
|
||||
formPanel
|
||||
(
|
||||
setClass('w-full'),
|
||||
set::actions(array('submit')),
|
||||
set::title($lang->admin->registerNotice->bind),
|
||||
set::url(inlink('bind', "from={$from}")),
|
||||
set::submitBtnText($lang->admin->bind->submit),
|
||||
formGroup
|
||||
(
|
||||
setClass('w-1/2'),
|
||||
set::label($lang->user->account),
|
||||
set::name('account'),
|
||||
set::value($account),
|
||||
set::required(true)
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
setClass('w-1/2'),
|
||||
set::label($lang->user->password),
|
||||
set::control('password'),
|
||||
set::name('password'),
|
||||
set::required(true)
|
||||
),
|
||||
$buildHidden($sn, 'site')
|
||||
)
|
||||
) : null
|
||||
);
|
||||
setID('mainContent'),
|
||||
setClass('px-1 mt-2 w-full max-w-7xl'),
|
||||
div(
|
||||
setClass('panel panel-form pt-4 size-sm is-lite'),
|
||||
div(
|
||||
setClass('max-w-7xl h-32 form-title'),
|
||||
div(setClass('main-title text-xl'), $lang->admin->register->welcome),
|
||||
div(setClass('sub-title'), icon(setClass('icon icon-diamond')), $lang->admin->register->advantage1),
|
||||
div(setClass('sub-title'), icon(setClass('icon icon-team')), $lang->admin->register->advantage2),
|
||||
div(setClass('sub-title'), icon(setClass('icon icon-statistic')), $lang->admin->register->advantage3),
|
||||
div(setClass('sub-title'), icon(setClass('icon icon-manual')), $lang->admin->register->advantage4),
|
||||
),
|
||||
formPanel
|
||||
(
|
||||
set::formID('joinForm'),
|
||||
setClass('bg-canvas m-auto mw-auto'),
|
||||
set::headingClass('w-96 m-auto'),
|
||||
set::submitBtnText($lang->admin->register->registerTitle),
|
||||
set::cancelBtnText(),
|
||||
div(setClass('label-text'), $lang->admin->register->mobile),
|
||||
formRow
|
||||
(
|
||||
setClass('m-auto no-label-mobile'),
|
||||
formGroup
|
||||
(
|
||||
setClass('no-label'),
|
||||
input
|
||||
(
|
||||
setClass('no-label-input'),
|
||||
set::name('mobile'),
|
||||
setID('mobile-captcha'),
|
||||
set::placeholder($lang->admin->register->enterMobile)
|
||||
)
|
||||
)
|
||||
),
|
||||
p(setID('captchaImageError')),
|
||||
p(setID('captchaMobileError')),
|
||||
div(
|
||||
setID('captchaImageLabel'),
|
||||
setClass('label-text'),
|
||||
$lang->admin->register->smsCode,
|
||||
),
|
||||
formRow
|
||||
(
|
||||
setClass('m-auto no-label-code'),
|
||||
formGroup
|
||||
(
|
||||
setClass('no-label'),
|
||||
input
|
||||
(
|
||||
setClass('no-label-input'),
|
||||
set::name('code'),
|
||||
set::placeholder($lang->admin->register->enterCode)
|
||||
)
|
||||
),
|
||||
a
|
||||
(
|
||||
setID('captcha-btn'),
|
||||
setClass('captcha-btn-class'),
|
||||
set('href', 'javascript:;'),
|
||||
$lang->admin->register->sendCode,
|
||||
on::click()->call('showCaptcha'),
|
||||
)
|
||||
),
|
||||
formRow
|
||||
(
|
||||
setClass('m-auto form-agree-ux'),
|
||||
formGroup
|
||||
(
|
||||
checkbox
|
||||
(
|
||||
set::name('agreeUX'),
|
||||
set::value(1)
|
||||
),
|
||||
span
|
||||
(
|
||||
setClass('form-agree-ux-text'),
|
||||
$lang->admin->register->join,
|
||||
a
|
||||
(
|
||||
setID('experience-plan-show'),
|
||||
set('data-size', 'lg'),
|
||||
$lang->admin->register->uxPlanWithBookTitle,
|
||||
set::href(createLink('admin', 'planModal')),
|
||||
set('data-toggle', 'modal')
|
||||
),
|
||||
$lang->admin->register->uxPlanStatusTitle
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
$skip,
|
||||
div(
|
||||
setClass('captcha-mobile-sender captcha-box'),
|
||||
set::style(array('display' => 'none')),
|
||||
div
|
||||
(
|
||||
setClass('form-group captch-box'),
|
||||
set::style(array('margin-bottom' => 0)),
|
||||
div
|
||||
(
|
||||
set::style(array('padding-right' => 0)),
|
||||
setClass('captcha-wrapper'),
|
||||
div
|
||||
(
|
||||
setClass('image-box'),
|
||||
on::init()->call('getCaptchaContent', ".image-box"),
|
||||
on::click()->call('getCaptchaContent', ".image-box"),
|
||||
)
|
||||
)
|
||||
),
|
||||
div
|
||||
(
|
||||
setClass('w-96 m-auto'),
|
||||
input
|
||||
(
|
||||
set::name('captchaImage'),
|
||||
set::placeholder($lang->admin->register->captchaTip)
|
||||
),
|
||||
div
|
||||
(
|
||||
setID('checkMobileSenderID'),
|
||||
setClass('px-4'),
|
||||
set::type('primary'),
|
||||
$lang->admin->register->sure,
|
||||
on::click()->call('checkMobileSender', '#checkMobileSenderID'),
|
||||
)
|
||||
|
||||
render();
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
if (strpos($_SERVER['REQUEST_URI'], '_single=1') !== false) {
|
||||
render('pagebase');
|
||||
}
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* The view file of bug module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
|
||||
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
|
||||
* @package admin
|
||||
* @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<style>
|
||||
#mainContent table {width: 95%;}
|
||||
.input-group .input-group-btn .popover {font-size: 12px;}
|
||||
.input-group-btn .btn {border-left: 0px}
|
||||
.input-group:last-child .input-group-addon {border-right: 0px;}
|
||||
</style>
|
||||
<div id='mainMenu' class='clearfix'>
|
||||
<div class='btn-toolbar pull-left'>
|
||||
<span class='btn btn-link btn-active-text'><span class='text'><?php echo $lang->admin->registerNotice->caption;?></span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div id='mainContent' class='main-row'>
|
||||
<div <?php if(common::hasPriv('admin', 'bind')) echo "class='col-md-6'";?>>
|
||||
<div class='panel'>
|
||||
<div class='panel-heading'><strong><?php echo $lang->admin->registerNotice->common?></strong></div>
|
||||
<form class='mw-600px' method="post" target="hiddenwin">
|
||||
<table align='center' class='table table-form'>
|
||||
<tr>
|
||||
<th class='w-100px'><?php echo $lang->user->account;?></th>
|
||||
<td>
|
||||
<div class="required required-wrapper"></div>
|
||||
<?php echo html::input('account', '', "class='form-control' placeholder='{$lang->admin->registerNotice->lblAccount}'");?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->user->realname;?></th>
|
||||
<td><div class="required required-wrapper"></div><?php echo html::input('realname', '', "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->user->company;?></th>
|
||||
<td><div class="required required-wrapper"></div><?php echo html::input('company', $register->company, "class='form-control'");?></td>
|
||||
</tr>
|
||||
<?php if(empty($config->isINT)):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->user->mobile;?></th>
|
||||
<td>
|
||||
<div class="required required-wrapper"></div>
|
||||
<div class='input-group'>
|
||||
<?php echo html::input('mobile', '', "class='form-control'");?>
|
||||
<span class='input-group-btn'><?php echo html::a(inlink('ajaxSendCode', 'type=mobile'), $lang->admin->getCaptcha, '', "id='mobileSender' class='btn'")?></span>
|
||||
<span class='input-group-addon' style='border:0px;background:none'></span>
|
||||
<span class='input-group-addon'><?php echo $lang->admin->captcha?></span>
|
||||
<?php echo html::input('mobileCode', '', "class='form-control'");?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<tr>
|
||||
<th><?php echo $lang->user->email;?></th>
|
||||
<td>
|
||||
<div class="required required-wrapper"></div>
|
||||
<div class='input-group'>
|
||||
<?php echo html::input('email', $register->email, "class='form-control'");?>
|
||||
<span class='input-group-btn'><?php echo html::a(inlink('ajaxSendCode', 'type=email'), $lang->admin->getCaptcha, '', "id='mailSender' class='btn'")?></span>
|
||||
<span class='input-group-addon' style='border:0px;background:none'></span>
|
||||
<span class='input-group-addon'><?php echo $lang->admin->captcha?></span>
|
||||
<?php echo html::input('emailCode', '', "class='form-control'");?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->user->password;?></th>
|
||||
<td>
|
||||
<div class="required required-wrapper"></div>
|
||||
<?php echo html::password('password1', '', "class='form-control' placeholder='{$lang->admin->registerNotice->lblPasswd}'");?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->user->password2;?></th>
|
||||
<td>
|
||||
<div class="required required-wrapper"></div>
|
||||
<?php echo html::password('password2', '', "class='form-control'");?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='2' class='text-center'>
|
||||
<?php echo html::submitButton($lang->admin->registerNotice->submit) . html::hidden('sn', $sn) . html::hidden('bindSite', common::getSysURL());?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php if(common::hasPriv('admin', 'bind')):?>
|
||||
<div class='col-md-6'>
|
||||
<div class='panel'>
|
||||
<div class='panel-heading'><strong><?php echo $lang->admin->registerNotice->bind?></strong></div>
|
||||
<form class='mw-400px' method="post" target="hiddenwin" action='<?php echo inlink('bind', "from=$from")?>'>
|
||||
<table align='center' class='table table-form'>
|
||||
<tr>
|
||||
<th class='w-100px'><?php echo $lang->user->account;?></th>
|
||||
<?php
|
||||
$account = zget($config->global, 'community', '');
|
||||
if($account == 'na') $account = '';
|
||||
?>
|
||||
<td><?php echo html::input('account', $account, "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->user->password;?></th>
|
||||
<td><?php echo html::password('password', '', "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='2' class="text-center"><?php echo html::submitButton() . html::hidden('sn', $sn) . html::hidden('site', common::getSysURL());?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<script>
|
||||
$(function()
|
||||
{
|
||||
$('#mobileSender').click(function()
|
||||
{
|
||||
var data = {mobile: $('#mobile').val()};
|
||||
var url = $(this).attr('href');
|
||||
|
||||
$.post(url, data, function(response)
|
||||
{
|
||||
if(response.result == 'success')
|
||||
{
|
||||
$('#mobileSender').popover({trigger:'manual', content:response.message, placement:'right'}).popover('show');
|
||||
$('#mobileSender').next('.popover').addClass('popover-success');
|
||||
function distroy(){$('#mobileSender').popover('destroy')}
|
||||
setTimeout(distroy,2000);
|
||||
}
|
||||
else
|
||||
{
|
||||
bootbox.alert(response.message);
|
||||
}
|
||||
}, 'json')
|
||||
return false;
|
||||
})
|
||||
$('#mailSender').click(function()
|
||||
{
|
||||
var data = {email: $('#email').val()};
|
||||
var url = $(this).attr('href');
|
||||
|
||||
$.post(url, data, function(response)
|
||||
{
|
||||
if(response.result == 'success')
|
||||
{
|
||||
$('#mailSender').popover({trigger:'manual', content:response.message, placement:'right'}).popover('show');
|
||||
$('#mailSender').next('.popover').addClass('popover-success');
|
||||
function distroy(){$('#mailSender').popover('destroy')}
|
||||
setTimeout(distroy,2000);
|
||||
}
|
||||
else
|
||||
{
|
||||
bootbox.alert(response.message);
|
||||
}
|
||||
}, 'json')
|
||||
return false;
|
||||
})
|
||||
});
|
||||
</script>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
@@ -16,25 +16,6 @@ class adminZen extends admin
|
||||
*/
|
||||
const EXT_MANAGER_VERSION = '1.3';
|
||||
|
||||
/**
|
||||
* 初始化sn。
|
||||
* Init sn.
|
||||
*
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function initSN(): void
|
||||
{
|
||||
if(!isset($this->config->global->sn))
|
||||
{
|
||||
$this->loadModel('setting');
|
||||
$this->setting->setItem('system.common.global.sn', $this->setting->computeSN());
|
||||
|
||||
if(!isset($this->config->global)) $this->config->global = new stdclass();
|
||||
$this->config->global->sn = $this->setting->getItem('owner=system&module=common§ion=global&key=sn');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync extensions from zentao official website by api.
|
||||
*
|
||||
@@ -145,34 +126,6 @@ class adminZen extends admin
|
||||
if(isset($result->data)) return json_decode($result->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册禅道账号。
|
||||
* Register zentao by API.
|
||||
*
|
||||
* @access protected
|
||||
* @return string
|
||||
*/
|
||||
protected function registerByAPI(): string
|
||||
{
|
||||
$apiConfig = $this->admin->getApiConfig();
|
||||
$apiURL = $this->config->admin->apiRoot . "/user-apiRegister.json?HTTP_X_REQUESTED_WITH=XMLHttpRequest&{$apiConfig->sessionVar}={$apiConfig->sessionID}";
|
||||
return common::http($apiURL, $_POST);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定禅道账号。
|
||||
* Login zentao by API.
|
||||
*
|
||||
* @access protected
|
||||
* @return string
|
||||
*/
|
||||
protected function bindByAPI(): string
|
||||
{
|
||||
$apiConfig = $this->admin->getApiConfig();
|
||||
$apiURL = $this->config->admin->apiRoot . "/user-bindChanzhi.json?HTTP_X_REQUESTED_WITH=XMLHttpRequest&{$apiConfig->sessionVar}={$apiConfig->sessionID}";
|
||||
return common::http($apiURL, $_POST);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送验证码。
|
||||
* Send code by API.
|
||||
@@ -239,21 +192,6 @@ class adminZen extends admin
|
||||
return common::http($apiURL . '?' . $param, $_POST);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取禅道社区注册信息。
|
||||
* Get register information.
|
||||
*
|
||||
* @access protected
|
||||
* @return object
|
||||
*/
|
||||
protected function getRegisterInfo(): object
|
||||
{
|
||||
$register = new stdclass();
|
||||
$register->company = $this->app->company->name;
|
||||
$register->email = $this->app->user->email;
|
||||
return $register;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取禅道官网数据。
|
||||
* Get zentao.net data.
|
||||
|
||||
@@ -45,7 +45,7 @@ class biTest
|
||||
public function getExpressionTest($table = null, $column = null, $alias = null, $function = null)
|
||||
{
|
||||
$expression = $this->objectModel->getExpression($table, $column, $alias, $function);
|
||||
return $expression->build($expression);
|
||||
return trim($expression->build($expression));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,6 +34,7 @@ dashboard
|
||||
(
|
||||
set::key("dashboard-{$dashboard}" . (!empty($objectID) ? "-$objectID" : '')),
|
||||
set::onlyLoadVisible(false),
|
||||
set::forceUpdateID(time()),
|
||||
set::blocks(array_values($blocks)),
|
||||
set::blockMenu(array('items' => $blockMenuItems)),
|
||||
set::emptyBlockContent(array('html' => '<div class="panel rounded bg-canvas panel-block shadow"><div class="panel-heading border-b h-12"></div></div>')),
|
||||
|
||||
+19
-17
@@ -886,33 +886,35 @@ class bugModel extends model
|
||||
if($this->session->$queryName === false) $this->session->set($queryName, ' 1 = 1');
|
||||
}
|
||||
|
||||
$query = $this->session->$queryName;
|
||||
if(strpos($query, "`project` = 'all'") !== false) $query = str_replace("`project` = 'all'", '1 = 1', $query);
|
||||
|
||||
if($moduleName == 'contributeBug') $bugsAssignedByMe = $this->loadModel('my')->getAssignedByMe($account, null, $orderBy, 'bug');
|
||||
|
||||
$bugs = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) AS priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) AS severityOrder")->from(TABLE_BUG)
|
||||
->where('deleted')->eq(0)
|
||||
$query = $this->session->$queryName;
|
||||
if(strpos($query, "`project` = 'all'") !== false) $query = str_replace("`project` = 'all'", '1 = 1', $query);
|
||||
$query = preg_replace('/`(\w+)`/', 't1.`$1`', $query);
|
||||
$orderBy = str_replace('id_', 't1.id_', $orderBy);
|
||||
|
||||
return $this->dao->select("t1.*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) AS priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) AS severityOrder,t2.name AS productName, t2.shadow")
|
||||
->from(TABLE_BUG)->alias('t1')
|
||||
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')
|
||||
->where('t1.deleted')->eq(0)
|
||||
->andWhere('t2.deleted')->eq(0)
|
||||
->beginIF($type == 'bySearch')->andWhere($query)->fi()
|
||||
->beginIF($executionID)->andWhere('execution')->eq($executionID)->fi()
|
||||
->beginIF($type != 'closedBy' and $this->app->moduleName == 'block')->andWhere('status')->ne('closed')->fi()
|
||||
->beginIF($type != 'all' and $type != 'bySearch')->andWhere("`$type`")->eq($account)->fi()
|
||||
->beginIF($type == 'bySearch' and $moduleName == 'workBug')->andWhere("assignedTo")->eq($account)->fi()
|
||||
->beginIF($type == 'assignedTo' and $moduleName == 'workBug')->andWhere('status')->ne('closed')->fi()
|
||||
->beginIF($executionID)->andWhere('t1.execution')->eq($executionID)->fi()
|
||||
->beginIF($type != 'closedBy' and $this->app->moduleName == 'block')->andWhere('t1.status')->ne('closed')->fi()
|
||||
->beginIF($type != 'all' and $type != 'bySearch')->andWhere("t1.`$type`")->eq($account)->fi()
|
||||
->beginIF($type == 'bySearch' and $moduleName == 'workBug')->andWhere("t1.assignedTo")->eq($account)->fi()
|
||||
->beginIF($type == 'assignedTo' and $moduleName == 'workBug')->andWhere('t1.status')->ne('closed')->fi()
|
||||
->beginIF($type == 'bySearch' and $moduleName == 'contributeBug')
|
||||
->andWhere('openedBy', 1)->eq($account)
|
||||
->orWhere('closedBy')->eq($account)
|
||||
->orWhere('resolvedBy')->eq($account)
|
||||
->orWhere('id')->in(!empty($bugsAssignedByMe) ? array_keys($bugsAssignedByMe) : array())
|
||||
->andWhere('t1.openedBy', 1)->eq($account)
|
||||
->orWhere('t1.closedBy')->eq($account)
|
||||
->orWhere('t1.resolvedBy')->eq($account)
|
||||
->orWhere('t1.id')->in(!empty($bugsAssignedByMe) ? array_keys($bugsAssignedByMe) : array())
|
||||
->markRight(1)
|
||||
->fi()
|
||||
->orderBy($orderBy)
|
||||
->beginIF($limit > 0)->limit($limit)->fi()
|
||||
->page($pager)
|
||||
->fetchAll('id', false);
|
||||
|
||||
$this->mao->select('name AS productName, shadow')->from(TABLE_PRODUCT)->into($bugs, 'product');
|
||||
return $bugs;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,18 +23,18 @@ cid=1
|
||||
- 属性name @未设定
|
||||
- 属性value @1
|
||||
- 获取项目版本版本1 bug 数
|
||||
- 属性name @未设定
|
||||
- 属性name @项目11版本1
|
||||
- 属性value @2
|
||||
- 获取项目版本版本2 bug 数
|
||||
- 属性name @未设定
|
||||
- 属性name @项目12版本2
|
||||
- 属性value @2
|
||||
|
||||
*/
|
||||
|
||||
$bug = new bugTest();
|
||||
$result = $bug->getDataOfBugsPerBuildTest();
|
||||
r($result['']) && p('name,value') && e('未设定,9'); // 获取版本为空 bug 数
|
||||
r($result['trunk']) && p('name,value') && e('主干,6'); // 获取主干 bug 数
|
||||
r($result[0]) && p('name,value') && e('未设定,1'); // 获取没关联影响版本的 bug 数
|
||||
r($result[1]) && p('name,value') && e('未设定,2'); // 获取项目版本版本1 bug 数
|
||||
r($result[2]) && p('name,value') && e('未设定,2'); // 获取项目版本版本2 bug 数
|
||||
r($result['']) && p('name,value') && e('未设定,9'); // 获取版本为空 bug 数
|
||||
r($result['trunk']) && p('name,value') && e('主干,6'); // 获取主干 bug 数
|
||||
r($result[0]) && p('name,value') && e('未设定,1'); // 获取没关联影响版本的 bug 数
|
||||
r($result[1]) && p('name,value') && e('项目11版本1,2'); // 获取项目版本版本1 bug 数
|
||||
r($result[2]) && p('name,value') && e('项目12版本2,2'); // 获取项目版本版本2 bug 数
|
||||
|
||||
@@ -7,11 +7,11 @@ timeout=0
|
||||
cid=1
|
||||
|
||||
- 测试处理bug1 2 3的openedBuild resolvedBuild字段
|
||||
- 第1条的openedBuild属性 @1
|
||||
- 第1条的openedBuild属性 @项目11版本1
|
||||
- 第1条的resolvedBuild属性 @~~
|
||||
- 第2条的openedBuild属性 @0
|
||||
- 第2条的resolvedBuild属性 @~~
|
||||
- 第3条的openedBuild属性 @1
|
||||
- 第3条的openedBuild属性 @项目11版本1
|
||||
- 第3条的resolvedBuild属性 @~~
|
||||
- 测试处理bug4 5 6的openedBuild resolvedBuild字段
|
||||
- 第4条的openedBuild属性 @主干
|
||||
@@ -68,9 +68,9 @@ $bugIDList5 = array('81', '82', '83');
|
||||
$bugIDList6 = array('84', '85', '86');
|
||||
|
||||
$bug = new bugTest();
|
||||
r($bug->processBuildForBugsTest($bugIDList1)) && p('1:openedBuild,resolvedBuild;2:openedBuild,resolvedBuild;3:openedBuild,resolvedBuild') && e('1,~~,0,~~,1,~~'); // 测试处理bug1 2 3的openedBuild resolvedBuild字段
|
||||
r($bug->processBuildForBugsTest($bugIDList2)) && p('4:openedBuild,resolvedBuild;5:openedBuild,resolvedBuild;6:openedBuild,resolvedBuild') && e('主干,~~,主干,~~,主干,~~'); // 测试处理bug4 5 6的openedBuild resolvedBuild字段
|
||||
r($bug->processBuildForBugsTest($bugIDList3)) && p('51:openedBuild,resolvedBuild;52:openedBuild,resolvedBuild;53:openedBuild,resolvedBuild') && e('主干,~~,主干,~~,主干,~~'); // 测试处理bug51 52 53的openedBuild resolvedBuild字段
|
||||
r($bug->processBuildForBugsTest($bugIDList4)) && p('54:openedBuild,resolvedBuild;55:openedBuild,resolvedBuild;56:openedBuild,resolvedBuild') && e('主干,~~,主干,~~,主干,主干'); // 测试处理bug54 55 56的openedBuild resolvedBuild字段
|
||||
r($bug->processBuildForBugsTest($bugIDList5)) && p('81:openedBuild,resolvedBuild;82:openedBuild,resolvedBuild;83:openedBuild,resolvedBuild') && e('主干,~~,主干,~~,主干,~~'); // 测试处理bug81 82 83的openedBuild resolvedBuild字段
|
||||
r($bug->processBuildForBugsTest($bugIDList6)) && p('84:openedBuild,resolvedBuild;85:openedBuild,resolvedBuild;86:openedBuild,resolvedBuild') && e('主干,~~,主干,~~,主干,~~'); // 测试处理bug84 85 86的openedBuild resolvedBuild字段
|
||||
r($bug->processBuildForBugsTest($bugIDList1)) && p('1:openedBuild,resolvedBuild;2:openedBuild,resolvedBuild;3:openedBuild,resolvedBuild') && e('项目11版本1,~~,0,~~,项目11版本1,~~'); // 测试处理bug1 2 3的openedBuild resolvedBuild字段
|
||||
r($bug->processBuildForBugsTest($bugIDList2)) && p('4:openedBuild,resolvedBuild;5:openedBuild,resolvedBuild;6:openedBuild,resolvedBuild') && e('主干,~~,主干,~~,主干,~~'); // 测试处理bug4 5 6的openedBuild resolvedBuild字段
|
||||
r($bug->processBuildForBugsTest($bugIDList3)) && p('51:openedBuild,resolvedBuild;52:openedBuild,resolvedBuild;53:openedBuild,resolvedBuild') && e('主干,~~,主干,~~,主干,~~'); // 测试处理bug51 52 53的openedBuild resolvedBuild字段
|
||||
r($bug->processBuildForBugsTest($bugIDList4)) && p('54:openedBuild,resolvedBuild;55:openedBuild,resolvedBuild;56:openedBuild,resolvedBuild') && e('主干,~~,主干,~~,主干,主干'); // 测试处理bug54 55 56的openedBuild resolvedBuild字段
|
||||
r($bug->processBuildForBugsTest($bugIDList5)) && p('81:openedBuild,resolvedBuild;82:openedBuild,resolvedBuild;83:openedBuild,resolvedBuild') && e('主干,~~,主干,~~,主干,~~'); // 测试处理bug81 82 83的openedBuild resolvedBuild字段
|
||||
r($bug->processBuildForBugsTest($bugIDList6)) && p('84:openedBuild,resolvedBuild;85:openedBuild,resolvedBuild;86:openedBuild,resolvedBuild') && e('主干,~~,主干,~~,主干,~~'); // 测试处理bug84 85 86的openedBuild resolvedBuild字段
|
||||
|
||||
@@ -268,6 +268,7 @@ if($isFromDoc)
|
||||
if($key == 'assignedTo') $cols[$key]['type'] = 'user';
|
||||
if($key == 'pri') $cols[$key]['priList'] = $lang->bug->priList;
|
||||
if($key == 'severity') $cols[$key]['severityList'] = $lang->bug->severityList;
|
||||
if($key == 'title') $cols[$key]['link'] = array('url' => createLink('bug', 'view', "bugID={id}"), 'data-toggle' => 'modal', 'data-size' => 'lg');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -1187,13 +1187,14 @@ class bugZen extends bug
|
||||
protected function assignVarsForEdit(object $bug): void
|
||||
{
|
||||
/* Add product related to the bug when it is not in the products. */
|
||||
$product = $this->loadModel('product')->fetchByID($bug->product);
|
||||
|
||||
if(!isset($this->products[$bug->product]))
|
||||
{
|
||||
$this->products[$bug->product] = $product->name;
|
||||
$this->view->products = $this->products;
|
||||
}
|
||||
|
||||
$product = $this->loadModel('product')->fetchByID($bug->product);
|
||||
if(empty($product->shadow))
|
||||
{
|
||||
$products = $this->view->products;
|
||||
|
||||
@@ -20,9 +20,9 @@ cid=1
|
||||
- 无查询条件查询版本
|
||||
- 第17条的execution属性 @125
|
||||
- 第17条的name属性 @版本17
|
||||
- 全部执行版本查询统计 @18
|
||||
- 全部执行版本查询统计 @20
|
||||
- 单独执行版本查询统计 @2
|
||||
- 无查询条件查询版本统计 @18
|
||||
- 无查询条件查询版本统计 @20
|
||||
|
||||
*/
|
||||
|
||||
@@ -47,6 +47,6 @@ r($build->getExecutionBuildsTest($count[0], $executionIDList[2], $type[0]))
|
||||
r($build->getExecutionBuildsTest($count[0], $executionIDList[0], $type[1], $parm[0])) && p('19:execution,name') && e('101,版本19'); // 根据产品查询版本
|
||||
r($build->getExecutionBuildsTest($count[0], $executionIDList[1], $type[2], $parm[1])) && p('17') && e('0'); // 根据查询条件查询版本
|
||||
r($build->getExecutionBuildsTest($count[0], $executionIDList[0], $type[3], $parm[2])) && p('17:execution,name') && e('125,版本17'); // 无查询条件查询版本
|
||||
r($build->getExecutionBuildsTest($count[1], $executionIDList[0], $type[0])) && p() && e('18'); // 全部执行版本查询统计
|
||||
r($build->getExecutionBuildsTest($count[1], $executionIDList[0], $type[0])) && p() && e('20'); // 全部执行版本查询统计
|
||||
r($build->getExecutionBuildsTest($count[1], $executionIDList[1], $type[0])) && p() && e('2'); // 单独执行版本查询统计
|
||||
r($build->getExecutionBuildsTest($count[1], $executionIDList[0], $type[3], $parm[2])) && p() && e('18'); // 无查询条件查询版本统计
|
||||
r($build->getExecutionBuildsTest($count[1], $executionIDList[0], $type[3], $parm[2])) && p() && e('20'); // 无查询条件查询版本统计
|
||||
|
||||
@@ -85,6 +85,7 @@ if($isFromDoc)
|
||||
$cols[$key]['sortType'] = false;
|
||||
if(isset($col['link'])) unset($cols[$key]['link']);
|
||||
if($key == 'pri') $cols[$key]['priList'] = $lang->testcase->priList;
|
||||
if($key == 'title') $cols[$key]['link'] = array('url' => createLink('caselib', 'viewCase', "caseID={id}&version={version}"), 'data-toggle' => 'modal', 'data-size' => 'lg');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,10 +12,11 @@ class chartTao extends chartModel
|
||||
* @param string $group
|
||||
* @param string $metric
|
||||
* @param string $agg count|distinct|avg|sum|max|min
|
||||
* @param string $driver
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function getRows(string $defaultSql, array $filters, string $date, string $group, string $metric, string $agg, string $driver): array
|
||||
protected function getRows(string $defaultSql, array $filters, string $date, string $group, string $metric, string $agg, string $driver = 'mysql'): array
|
||||
{
|
||||
$groupSql = $groupBySql = "tt.`$group`";
|
||||
if(!empty($date))
|
||||
|
||||
Regular → Executable
+9
-8
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
|
||||
title=测试 chartModel::getRows();
|
||||
@@ -33,10 +34,10 @@ cid=1
|
||||
- 第0条的id属性 @4
|
||||
- 测试筛选器为空,所属产品为组,以ID求和为条件查询的需求数据
|
||||
- 第0条的product属性 @1
|
||||
- 第0条的id属性 @10
|
||||
- 第0条的id属性 @10.00
|
||||
- 测试筛选器为空,所属产品为组,以ID求平均值为条件查询的需求数据
|
||||
- 第0条的product属性 @1
|
||||
- 第0条的id属性 @2.5000
|
||||
- 第0条的id属性 @2.50
|
||||
- 测试筛选器为空,所属产品为组,以ID求最大值为条件查询的需求数据
|
||||
- 第0条的product属性 @1
|
||||
- 第0条的id属性 @4
|
||||
@@ -52,7 +53,7 @@ zenData('story')->loadYaml('story')->gen(50);
|
||||
zenData('user')->gen(5);
|
||||
su('admin');
|
||||
|
||||
$defaultSql = 'select * from zt_story';
|
||||
$defaultSql = 'SELECT * FROM zt_story';
|
||||
|
||||
$emptyFilters = array();
|
||||
|
||||
@@ -90,8 +91,8 @@ r($chart->getRows($defaultSql, $emptyFilters, $date['YEAR'], $group['openedDate
|
||||
r($chart->getRows($defaultSql, $emptyFilters, $date['WEEK'], $group['openedDate'], 'id', $agg['distinct'])) && p('1:openedDate,id') && e('202201,4'); //测试筛选器为空,创建日期按周分组,以ID去重后计数为条件查询的需求数据
|
||||
r($chart->getRows($defaultSql, $emptyFilters, $date['DATE'], $group['openedDate'], 'id', $agg['distinct'])) && p('2:openedDate,id') && e('2022-01-03,1'); //测试筛选器为空,创建日期按日为组,以ID去重后计数为条件查询的需求数据
|
||||
|
||||
r($chart->getRows($defaultSql, $emptyFilters, $date[''], $group['product'], 'id', $agg['count'])) && p('0:product,id') && e('1,4'); //测试筛选器为空,所属产品为组,以ID计数为条件查询的需求数据
|
||||
r($chart->getRows($defaultSql, $emptyFilters, $date[''], $group['product'], 'id', $agg['sum'])) && p('0:product,id') && e('1,10'); //测试筛选器为空,所属产品为组,以ID求和为条件查询的需求数据
|
||||
r($chart->getRows($defaultSql, $emptyFilters, $date[''], $group['product'], 'id', $agg['avg'])) && p('0:product,id') && e('1,2.5000'); //测试筛选器为空,所属产品为组,以ID求平均值为条件查询的需求数据
|
||||
r($chart->getRows($defaultSql, $emptyFilters, $date[''], $group['product'], 'id', $agg['max'])) && p('0:product,id') && e('1,4'); //测试筛选器为空,所属产品为组,以ID求最大值为条件查询的需求数据
|
||||
r($chart->getRows($defaultSql, $emptyFilters, $date[''], $group['product'], 'id', $agg['min'])) && p('0:product,id') && e('1,1'); //测试筛选器为空,所属产品为组,以ID求最小值为条件查询的需求数据
|
||||
r($chart->getRows($defaultSql, $emptyFilters, $date[''], $group['product'], 'id', $agg['count'])) && p('0:product,id') && e('1,4'); //测试筛选器为空,所属产品为组,以ID计数为条件查询的需求数据
|
||||
r($chart->getRows($defaultSql, $emptyFilters, $date[''], $group['product'], 'id', $agg['sum'])) && p('0:product,id') && e('1,10.00'); //测试筛选器为空,所属产品为组,以ID求和为条件查询的需求数据
|
||||
r($chart->getRows($defaultSql, $emptyFilters, $date[''], $group['product'], 'id', $agg['avg'])) && p('0:product,id') && e('1,2.50'); //测试筛选器为空,所属产品为组,以ID求平均值为条件查询的需求数据
|
||||
r($chart->getRows($defaultSql, $emptyFilters, $date[''], $group['product'], 'id', $agg['max'])) && p('0:product,id') && e('1,4'); //测试筛选器为空,所属产品为组,以ID求最大值为条件查询的需求数据
|
||||
r($chart->getRows($defaultSql, $emptyFilters, $date[''], $group['product'], 'id', $agg['min'])) && p('0:product,id') && e('1,1'); //测试筛选器为空,所属产品为组,以ID求最小值为条件查询的需求数据
|
||||
@@ -410,6 +410,7 @@ $lang->doc->productSpace = "{$lang->productCommon} Space";
|
||||
$lang->doc->projectSpace = "{$lang->projectCommon} Space";
|
||||
$lang->doc->apiSpace = 'API Space';
|
||||
$lang->doc->teamSpace = 'Team Space';
|
||||
$lang->doc->template = 'Document Template';
|
||||
|
||||
$lang->product->list = $lang->productCommon . ' List';
|
||||
$lang->product->kanban = $lang->productCommon . ' Kanban';
|
||||
|
||||
@@ -410,6 +410,7 @@ $lang->doc->productSpace = "{$lang->productCommon} Space";
|
||||
$lang->doc->projectSpace = "{$lang->projectCommon} Space";
|
||||
$lang->doc->apiSpace = 'API Space';
|
||||
$lang->doc->teamSpace = 'Team Space';
|
||||
$lang->doc->template = 'Document Template';
|
||||
|
||||
$lang->product->list = $lang->productCommon . ' List';
|
||||
$lang->product->kanban = $lang->productCommon . ' Kanban';
|
||||
|
||||
@@ -410,6 +410,7 @@ $lang->doc->productSpace = "{$lang->productCommon} Space";
|
||||
$lang->doc->projectSpace = "{$lang->projectCommon} Space";
|
||||
$lang->doc->apiSpace = 'API Space';
|
||||
$lang->doc->teamSpace = 'Team Space';
|
||||
$lang->doc->template = 'Document Template';
|
||||
|
||||
$lang->product->list = $lang->productCommon . ' List';
|
||||
$lang->product->kanban = $lang->productCommon . ' Kanban';
|
||||
|
||||
@@ -410,6 +410,7 @@ $lang->doc->productSpace = "{$lang->productCommon}空间";
|
||||
$lang->doc->projectSpace = "{$lang->projectCommon}空间";
|
||||
$lang->doc->apiSpace = '接口空间';
|
||||
$lang->doc->teamSpace = '团队空间';
|
||||
$lang->doc->template = '文档模板';
|
||||
|
||||
$lang->product->list = $lang->productCommon . '列表';
|
||||
$lang->product->kanban = $lang->productCommon . '看板';
|
||||
@@ -453,6 +454,7 @@ $lang->admin->data = '数据';
|
||||
$lang->admin->cron = '定时';
|
||||
$lang->admin->buildIndex = '重建索引';
|
||||
$lang->admin->tableEngine = '表引擎';
|
||||
$lang->admin->register = '禅道社区';
|
||||
|
||||
$lang->convert->importJira = '导入Jira数据';
|
||||
|
||||
|
||||
@@ -1178,6 +1178,7 @@ eof;
|
||||
|
||||
if($module == 'product' and $method == 'browse' and !empty($this->app->params['storyType']) and $this->app->params['storyType'] != 'story') $method = $this->app->params['storyType'];
|
||||
if($module == 'productplan' && ($method == 'story' || $method == 'bug')) $method = 'view';
|
||||
if($module == 'doc' && $method == 'edittemplate') $method = 'createtemplate';
|
||||
|
||||
$openMethods = array(
|
||||
'user' => array('deny', 'logout'),
|
||||
@@ -2311,7 +2312,7 @@ eof;
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public static function processMarkdown(string $markdown): string
|
||||
public static function processMarkdown(string $markdown): string|bool
|
||||
{
|
||||
if(empty($markdown)) return false;
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@ cid=1
|
||||
|
||||
- 查看替换后的菜单链接 @/execution-task-1
|
||||
- 查看替换后的菜单链接属性link @/task-create-1
|
||||
- 查看替换后的菜单链接属性link @/task-edit-1
|
||||
- 查看替换后的菜单链接属性link @/task-delete-1
|
||||
- 查看替换后的菜单链接属性link @/task-view-1
|
||||
|
||||
*/
|
||||
|
||||
@@ -23,4 +26,22 @@ $menu = array();
|
||||
$menu['link'] = "/task-create-%s";
|
||||
$menu = common::setMenuVarsEx($menu, 1);
|
||||
|
||||
r($menu) && p('link') && e('/task-create-1'); // 查看替换后的菜单链接
|
||||
r($menu) && p('link') && e('/task-create-1'); // 查看替换后的菜单链接
|
||||
|
||||
$menu = array();
|
||||
$menu['link'] = "/task-edit-%s";
|
||||
$menu = common::setMenuVarsEx($menu, 1);
|
||||
|
||||
r($menu) && p('link') && e('/task-edit-1'); // 查看替换后的菜单链接
|
||||
|
||||
$menu = array();
|
||||
$menu['link'] = "/task-delete-%s";
|
||||
$menu = common::setMenuVarsEx($menu, 1);
|
||||
|
||||
r($menu) && p('link') && e('/task-delete-1'); // 查看替换后的菜单链接
|
||||
|
||||
$menu = array();
|
||||
$menu['link'] = "/task-view-%s";
|
||||
$menu = common::setMenuVarsEx($menu, 1);
|
||||
|
||||
r($menu) && p('link') && e('/task-view-1'); // 查看替换后的菜单链接
|
||||
|
||||
@@ -11,12 +11,12 @@ $config->compile->dtable->fieldList['id']['checkbox'] = false;
|
||||
|
||||
$config->compile->dtable->fieldList['name']['title'] = $lang->compile->name;
|
||||
$config->compile->dtable->fieldList['name']['name'] = 'name';
|
||||
$config->compile->dtable->fieldList['name']['type'] = 'shortTitle';
|
||||
$config->compile->dtable->fieldList['name']['sortType'] = true;
|
||||
$config->compile->dtable->fieldList['name']['hint'] = true;
|
||||
$config->compile->dtable->fieldList['name']['checkbox'] = false;
|
||||
$config->compile->dtable->fieldList['name']['link'] = array('module' => 'job', 'method' => 'view', 'params' => 'jobID={job}&compileID={id}');
|
||||
$config->compile->dtable->fieldList['name']['data-toggle'] = 'modal';
|
||||
$config->compile->dtable->fieldList['name']['minWidth'] = '350';
|
||||
|
||||
$config->compile->dtable->fieldList['status']['title'] = $lang->compile->status;
|
||||
$config->compile->dtable->fieldList['status']['name'] = 'status';
|
||||
@@ -49,11 +49,12 @@ $config->compile->dtable->fieldList['triggerType']['sortType'] = false;
|
||||
$config->compile->dtable->fieldList['triggerType']['width'] = '80';
|
||||
$config->compile->dtable->fieldList['triggerType']['hint'] = true;
|
||||
|
||||
$config->compile->dtable->fieldList['createdDate']['title'] = $lang->compile->atTime;
|
||||
$config->compile->dtable->fieldList['createdDate']['name'] = 'createdDate';
|
||||
$config->compile->dtable->fieldList['createdDate']['type'] = 'datetime';
|
||||
$config->compile->dtable->fieldList['createdDate']['sortType'] = true;
|
||||
$config->compile->dtable->fieldList['createdDate']['hint'] = true;
|
||||
$config->compile->dtable->fieldList['createdDate']['title'] = $lang->compile->atTime;
|
||||
$config->compile->dtable->fieldList['createdDate']['name'] = 'createdDate';
|
||||
$config->compile->dtable->fieldList['createdDate']['type'] = 'datetime';
|
||||
$config->compile->dtable->fieldList['createdDate']['sortType'] = true;
|
||||
$config->compile->dtable->fieldList['createdDate']['hint'] = true;
|
||||
$config->compile->dtable->fieldList['createdDate']['formatDate'] = 'YYYY-MM-dd hh:mm';
|
||||
|
||||
$config->compile->actionList = array();
|
||||
$config->compile->actionList['logs']['icon'] = 'history';
|
||||
|
||||
@@ -6,8 +6,15 @@ window.renderCell = function(result, {col, row})
|
||||
if(row.data.status == 'failure' || row.data.status == 'create_fail') className = 'status-doing';
|
||||
if(row.data.status == 'success') className = 'status-done';
|
||||
result[0] = {html:'<span class="' + className + '">' + result[0] + '</span>'};
|
||||
}
|
||||
|
||||
return result;
|
||||
if(col.name == 'name' && row.data.engine != 'jenkins')
|
||||
{
|
||||
const pipeline = row.data.pipeline;
|
||||
if(!pipeline) return result;
|
||||
const branch = JSON.parse(pipeline).reference;
|
||||
|
||||
if(branch) result[1] = {html:'<span class="label success-pale mr-1">' + branch + '</span>'};
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -79,7 +79,7 @@ class compileModel extends model
|
||||
}
|
||||
|
||||
if(strpos($orderBy, 'id') === false) $orderBy .= ', id_desc';
|
||||
return $this->dao->select('t1.id, t1.name, t1.job, t1.status, t1.createdDate, t1.testtask, t2.pipeline, t2.triggerType, t2.svnDir, t2.comment, t2.atDay, t2.atTime, t2.engine, t2.triggerActions, t3.name as repoName, t4.name as jenkinsName')->from(TABLE_COMPILE)->alias('t1')
|
||||
return $this->dao->select('t1.id, t1.branch, t1.name, t1.job, t1.status, t1.createdDate, t1.testtask, t2.pipeline, t2.triggerType, t2.svnDir, t2.comment, t2.atDay, t2.atTime, t2.engine, t2.triggerActions, t3.name as repoName, t4.name as jenkinsName')->from(TABLE_COMPILE)->alias('t1')
|
||||
->leftJoin(TABLE_JOB)->alias('t2')->on('t1.job=t2.id')
|
||||
->leftJoin(TABLE_REPO)->alias('t3')->on('t2.repo=t3.id')
|
||||
->leftJoin(TABLE_PIPELINE)->alias('t4')->on('t2.server=t4.id')
|
||||
|
||||
@@ -96,6 +96,7 @@ class compileTao extends compileModel
|
||||
$updatedDate = $build->updated;
|
||||
}
|
||||
$data->updateDate = date('Y-m-d H:i:s', $updatedDate);
|
||||
$data->branch = !empty($build->branch) ? $build->branch : '';
|
||||
}
|
||||
|
||||
$this->dao->insert(TABLE_COMPILE)->data($data)->exec();
|
||||
|
||||
@@ -5,6 +5,7 @@ include dirname(__FILE__, 2) . '/lib/compile.unittest.class.php';
|
||||
|
||||
zenData('compile')->gen(1);
|
||||
zenData('job')->loadYaml('job')->gen(1);
|
||||
zenData('repo')->loadYaml('repo')->gen(10);
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
@@ -13,12 +14,15 @@ title=测试 compileModel->getList();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 检查是否能获取到数据第1条的name属性 @构建1
|
||||
- 检查是否能获取到数据
|
||||
- 第1条的name属性 @构建1
|
||||
- 第1条的status属性 @success
|
||||
- 第1条的pipeline属性 @simple-job
|
||||
- 第1条的triggerType属性 @tag
|
||||
- 检查获取不存在的数据会返回什么 @0
|
||||
|
||||
*/
|
||||
|
||||
$compile = new compileTest();
|
||||
|
||||
r($compile->getListTest(1, 1)) && p('1:name') && e('构建1'); //检查是否能获取到数据
|
||||
r($compile->getListTest(3, 1)) && p('') && e('0'); //检查获取不存在的数据会返回什么
|
||||
r($compile->getListTest(1, 1)) && p('1:name,status,pipeline,triggerType') && e('构建1,success,simple-job,tag'); //检查是否能获取到数据
|
||||
r($compile->getListTest(3, 1)) && p('') && e('0'); //检查获取不存在的数据会返回什么
|
||||
|
||||
@@ -12,13 +12,13 @@ cid=1
|
||||
- 测试当buildTType为jenkins的时候,判断创建的compile信息是否正确,是否与build内的信息一致。
|
||||
- 属性name @testName2
|
||||
- 属性job @2
|
||||
- 属性createdBy @admin
|
||||
- 属性createdBy @system
|
||||
- 属性queue @1
|
||||
- 属性status @success
|
||||
- 测试当buildTType为jenkins的时候,判断创建的compile信息是否正确,是否与build内的信息一致。
|
||||
- 属性name @testName3
|
||||
- 属性job @3
|
||||
- 属性createdBy @admin
|
||||
- 属性createdBy @system
|
||||
- 属性queue @1
|
||||
- 属性status @failure
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ class custom extends control
|
||||
{
|
||||
$this->customZen->setFieldListForSet($module, $field);
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
if($module == 'baseline' && $field == 'objectList') return $this->sendSuccess(array('load' => true));
|
||||
return $this->sendSuccess(array('load' => $this->createLink('custom', 'set', "module=$module&field=$field&lang=" . ($lang == 'all' ? $lang : ''))));
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
data('activeMenuItem', $module);
|
||||
|
||||
if(!in_array($module, array('block', 'baseline'))) include 'sidebar.html.php';
|
||||
|
||||
$formItems = array();
|
||||
|
||||
@@ -10,13 +10,25 @@ timeout=0
|
||||
cid=1
|
||||
|
||||
- 测试合并字段。
|
||||
- 第0条的id属性 @id
|
||||
- 第0条的title属性 @title
|
||||
- 第0条的id属性 @Bug编号
|
||||
- 第0条的title属性 @Bug标题
|
||||
- 第1条的id属性 @bug
|
||||
- 第1条的title属性 @bug
|
||||
- 测试多个表合并字段。
|
||||
- 第0条的id属性 @编号
|
||||
- 第0条的title属性 @title
|
||||
- 第1条的id属性 @product
|
||||
- 第1条的title属性 @product
|
||||
|
||||
*/
|
||||
global $tester;
|
||||
$tester->loadModel('dataview');
|
||||
|
||||
r($tester->dataview->mergeFields(array('id', 'title'), array('zt_bug.id', 'zt_bug.title'), array('zt_bug' => 'bug'))) && p('0:id;0:title;1:id;1:title') && e('id,title,bug,bug'); //测试合并字段。
|
||||
$dataFields = array('id', 'title');
|
||||
$sqlFields = array('zt_bug.id', 'zt_bug.title');
|
||||
$moduleNames = array('zt_bug' => 'bug');
|
||||
r($tester->dataview->mergeFields($dataFields, $sqlFields, $moduleNames)) && p('0:id;0:title;1:id;1:title') && e('Bug编号,Bug标题,bug,bug'); //测试合并字段。
|
||||
|
||||
$sqlFields = array('zt_product.id', 'zt_bug.title');
|
||||
$moduleNames = array('zt_bug' => 'bug', 'zt_product' => 'product');
|
||||
r($tester->dataview->mergeFields($dataFields, $sqlFields, $moduleNames)) && p('0:id;0:title;1:id;1:title') && e('编号,title,product,product'); //测试多个表合并字段。
|
||||
|
||||
@@ -320,16 +320,16 @@ class designModel extends model
|
||||
* 获取设计列表数据。
|
||||
* Get design list.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $projectID
|
||||
* @param string $type all|bySearch|HLDS|DDS|DBDS|ADS
|
||||
* @param int $param
|
||||
* @param string $orderBy
|
||||
* @param int $pager
|
||||
* @param int|array $productID
|
||||
* @param int|array $projectID
|
||||
* @param string $type all|bySearch|HLDS|DDS|DBDS|ADS
|
||||
* @param int $param
|
||||
* @param string $orderBy
|
||||
* @param int $pager
|
||||
* @access public
|
||||
* @return object[]
|
||||
*/
|
||||
public function getList(int $projectID = 0, int $productID = 0, string $type = 'all', int $param = 0, string $orderBy = 'id_desc', object $pager = null): array
|
||||
public function getList(int|array $projectID = 0, int|array $productID = 0, string $type = 'all', int $param = 0, string $orderBy = 'id_desc', object $pager = null): array
|
||||
{
|
||||
if(common::isTutorialMode()) return $this->loadModel('tutorial')->getDesigns();
|
||||
|
||||
@@ -341,9 +341,9 @@ class designModel extends model
|
||||
{
|
||||
$designs = $this->dao->select('*')->from(TABLE_DESIGN)
|
||||
->where('deleted')->eq(0)
|
||||
->beginIF($projectID)->andWhere('project')->eq($projectID)->fi()
|
||||
->beginIF($projectID)->andWhere('project')->in($projectID)->fi()
|
||||
->beginIF($type != 'all')->andWhere('type')->in($type)->fi()
|
||||
->beginIF($productID)->andWhere('product')->eq($productID)->fi()
|
||||
->beginIF($productID)->andWhere('product')->in(is_numeric($productID) ? "0,$productID" : array_merge($productID, array(0)))->fi()
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->fetchAll('id');
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
|
||||
title=设计列表检查测试
|
||||
timeout=0
|
||||
cid=10
|
||||
|
||||
- 执行tester模块的checkMenu方法,参数是'hlds', '1' 测试结果 @hlds菜单下显示数据正确
|
||||
- 执行tester模块的checkMenu方法,参数是'dds', '1' 测试结果 @dds菜单下显示数据正确
|
||||
- 执行tester模块的checkMenu方法,参数是'dbds', '1' 测试结果 @dbds菜单下显示数据正确
|
||||
- 执行tester模块的checkMenu方法,参数是'ads', '1' 测试结果 @ads菜单下显示数据正确
|
||||
- 执行tester模块的checkMenu方法,参数是'all', '4' 测试结果 @all菜单下显示数据正确
|
||||
- 执行tester模块的switchProduct方法,参数是'firstProduct', '2' 测试结果 @切换firstProduct查看设计数据成功
|
||||
- 执行tester模块的switchProduct方法,参数是'secondProduct', '2' 测试结果 @切换secondProduct查看设计数据成功
|
||||
|
||||
*/
|
||||
chdir(__DIR__);
|
||||
include '../lib/browse.ui.class.php';
|
||||
|
||||
|
||||
@@ -5,12 +5,14 @@ $config->doc = new stdclass();
|
||||
$config->doc->createlib = new stdclass();
|
||||
$config->doc->editlib = new stdclass();
|
||||
$config->doc->create = new stdclass();
|
||||
$config->doc->createTemplate = new stdclass();
|
||||
$config->doc->edit = new stdclass();
|
||||
$config->doc->showfiles = new stdclass();
|
||||
|
||||
$config->doc->createlib->requiredFields = 'name';
|
||||
$config->doc->editlib->requiredFields = 'name';
|
||||
$config->doc->create->requiredFields = 'lib,title';
|
||||
$config->doc->createTemplate->requiredFields = 'lib,title';
|
||||
$config->doc->edit->requiredFields = 'lib,title';
|
||||
|
||||
$config->doc->customObjectLibs = 'files,customFiles';
|
||||
@@ -124,6 +126,24 @@ $config->doc->quickMenu['editedby'] = array('id' => 4, 'name' => $lang->doc->my
|
||||
|
||||
$config->doc->zentaoListMenuPosition = 22;
|
||||
|
||||
$config->doc->templateTypeParents = array();
|
||||
$config->doc->templateTypeParents['PP'] = 'plan';
|
||||
$config->doc->templateTypeParents['QAP'] = 'plan';
|
||||
$config->doc->templateTypeParents['CMP'] = 'plan';
|
||||
$config->doc->templateTypeParents['ITP'] = 'plan';
|
||||
$config->doc->templateTypeParents['STP'] = 'plan';
|
||||
$config->doc->templateTypeParents['ERS'] = 'story';
|
||||
$config->doc->templateTypeParents['URS'] = 'story';
|
||||
$config->doc->templateTypeParents['SRS'] = 'story';
|
||||
$config->doc->templateTypeParents['HLDS'] = 'design';
|
||||
$config->doc->templateTypeParents['DDS'] = 'design';
|
||||
$config->doc->templateTypeParents['DBDS'] = 'design';
|
||||
$config->doc->templateTypeParents['ADS'] = 'design';
|
||||
$config->doc->templateTypeParents['Code'] = 'dev';
|
||||
$config->doc->templateTypeParents['ITTC'] = 'test';
|
||||
$config->doc->templateTypeParents['STTC'] = 'test';
|
||||
$config->doc->templateTypeParents['UM'] = 'desc';
|
||||
|
||||
$config->doc->zentaoList = array();
|
||||
$config->doc->zentaoList['story'] = array('key' => 'story', 'name' => $lang->doc->zentaoList['story'] . $lang->doc->list, 'icon' => 'lightbulb', 'subMenu' => array(), 'priv' => 'storyBrowse');
|
||||
$config->doc->zentaoList['task'] = array('key' => 'task', 'name' => $lang->doc->zentaoList['task'] . $lang->doc->list, 'icon' => 'check-sign', 'module' => 'execution', 'method' => 'task', 'params' => 'execution=0&status=unclosed¶m=0&orderBy=&recTotal=0&recPerPage=100&pageID=1&from=doc', 'priv' => 'taskBrowse');
|
||||
@@ -144,6 +164,7 @@ $config->doc->zentaoList['bug']['subMenu'][] = array('key' => 'planBug', 'nam
|
||||
|
||||
$config->doc->zentaoList['more']['subMenu'][] = array('key' => 'productPlan', 'name' => $lang->doc->zentaoList['productPlan'] . $lang->doc->list, 'icon' => 'productplan', 'module' => 'productplan', 'method' => 'browse', 'params' => 'productID=0&branch=&browseType=undone&queryID=0&orderBy=begin_desc&recTotal=0&recPerPage=20&pageID=1&from=doc', 'priv' => 'productplanBrowse');
|
||||
$config->doc->zentaoList['more']['subMenu'][] = array('key' => 'productRelease', 'name' => $lang->doc->zentaoList['productRelease'] . $lang->doc->list, 'icon' => 'send', 'module' => 'release', 'method' => 'browse', 'params' => 'productID=0&branch=all&type=all&orderBy=¶m=0&recTotal=0&recPerPage=20&pageID=1&from=doc', 'priv' => 'releaseBrowse');
|
||||
$config->doc->zentaoList['more']['subMenu'][] = array('key' => 'projectRelease', 'name' => $lang->doc->zentaoList['projectRelease'] . $lang->doc->list, 'icon' => 'send', 'module' => 'projectRelease', 'method' => 'browse', 'params' => 'projectID=0&executionID=0&type=all&orderBy=&recTotal=0&recPerPage=20&pageID=1&from=doc', 'priv' => 'projectReleaseBrowse');
|
||||
$config->doc->zentaoList['more']['subMenu'][] = array('key' => 'ER', 'name' => $lang->doc->zentaoList['ER'] . $lang->doc->list, 'icon' => 'lightbulb-alt', 'module' => 'product', 'method' => 'browse', 'params' => 'productID=0&branch=all&browseType=¶m=0&storyType=epic&orderBy=&recTotal=0&recPerPage=20&pageID=1&projectID=0&from=doc', 'priv' => 'epicBrowse');
|
||||
$config->doc->zentaoList['more']['subMenu'][] = array('key' => 'UR', 'name' => $lang->doc->zentaoList['UR'] . $lang->doc->list, 'icon' => 'customer', 'module' => 'product', 'method' => 'browse', 'params' => 'productID=0&branch=all&browseType=¶m=0&storyType=requirement&orderBy=&recTotal=0&recPerPage=20&pageID=1&projectID=0&from=doc', 'priv' => 'requirementBrowse');
|
||||
|
||||
@@ -153,6 +174,8 @@ if(in_array($config->edition, array('biz', 'max', 'ipd')))
|
||||
$config->doc->zentaoList['more']['subMenu'][] = array('key' => 'ticket', 'name' => $lang->doc->zentaoList['ticket'] . $lang->doc->list, 'icon' => 'support-ticket', 'module' => 'ticket', 'method' => 'browse', 'params' => 'browseType=wait¶m=0&orderBy=id_desc&recTotal=0&recPerPage=20&pageID=1&from=doc', 'priv' => 'ticketBrowse');
|
||||
}
|
||||
|
||||
if(in_array($config->edition, array('max', 'ipd'))) $config->doc->zentaoList['gantt'] = array('key' => 'gantt', 'name' => $lang->doc->zentaoList['gantt'], 'icon' => 'gantt', 'isModal' => true, 'module' => 'programPlan', 'method' => 'browse', "params" => 'projectID=0&productID=0&type=gantt&orderBy=id_asc&baselineID=0&browseType=&queryID=0&from=doc');
|
||||
|
||||
//$config->doc->zentaoList['storyView'] = array('key' => 'storyView', 'name' => $lang->doc->zentaoList['story'] . $lang->doc->detail, 'icon' => 'lightbulb', 'priv' => 'storyView');
|
||||
//$config->doc->zentaoList['taskView'] = array('key' => 'taskView', 'name' => $lang->doc->zentaoList['task'] . $lang->doc->detail, 'icon' => 'check-sign', 'priv' => 'taskView');
|
||||
//$config->doc->zentaoList['caseView'] = array('key' => 'caseView', 'name' => $lang->doc->zentaoList['case'] . $lang->doc->detail, 'icon' => 'testcase', 'priv' => 'caseView');
|
||||
|
||||
@@ -63,6 +63,9 @@ $config->doc->form->create['template'] = array('type' => 'string', 'requir
|
||||
$config->doc->form->create['templateType'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->doc->form->create['chapterType'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
|
||||
$config->doc->form->createtemplate = $config->doc->form->create;
|
||||
$config->doc->form->createtemplate['templateDesc'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
|
||||
$config->doc->form->edit['title'] = array('type' => 'string', 'required' => true, 'default' => '', 'filter' => 'trim');
|
||||
$config->doc->form->edit['product'] = array('type' => 'int', 'required' => false, 'default' => 0);
|
||||
$config->doc->form->edit['project'] = array('type' => 'int', 'required' => false, 'default' => 0);
|
||||
@@ -85,6 +88,9 @@ $config->doc->form->edit['mailto'] = array('type' => 'array', 'required'
|
||||
$config->doc->form->edit['editedBy'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->doc->form->edit['editedDate'] = array('type' => 'datetime', 'required' => false, 'default' => $now);
|
||||
|
||||
$config->doc->form->edittemplate = $config->doc->form->edit;
|
||||
$config->doc->form->edittemplate['templateDesc'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
|
||||
$config->doc->form->movelib['space'] = array('type' => 'string', 'required' => true, 'default' => '');
|
||||
$config->doc->form->movelib['acl'] = array('type' => 'string', 'required' => true, 'default' => '');
|
||||
$config->doc->form->movelib['groups'] = array('type' => 'array', 'required' => false, 'default' => '', 'filter' => 'join');
|
||||
@@ -99,8 +105,17 @@ $config->doc->form->movedoc['readGroups'] = array('type' => 'array', 'require
|
||||
$config->doc->form->movedoc['readUsers'] = array('type' => 'array', 'required' => false, 'default' => '', 'filter' => 'join');
|
||||
$config->doc->form->movedoc['parent'] = array('type' => 'int', 'required' => false, 'default' => 0);
|
||||
|
||||
$config->doc->form->movetemplate['lib'] = array('type' => 'int', 'required' => true, 'default' => '');
|
||||
$config->doc->form->movetemplate['module'] = array('type' => 'int', 'required' => true, 'default' => '');
|
||||
$config->doc->form->movetemplate['parent'] = array('type' => 'int', 'required' => false, 'default' => 0);
|
||||
$config->doc->form->movetemplate['acl'] = array('type' => 'string', 'required' => true, 'default' => '');
|
||||
|
||||
$config->doc->form->batchmovedoc['lib'] = array('type' => 'int', 'required' => true, 'default' => 0);
|
||||
$config->doc->form->batchmovedoc['module'] = array('type' => 'int', 'required' => false, 'default' => 0);
|
||||
$config->doc->form->batchmovedoc['acl'] = array('type' => 'string', 'required' => true, 'default' => '');
|
||||
$config->doc->form->batchmovedoc['groups'] = array('type' => 'array', 'required' => false, 'default' => '', 'filter' => 'join');
|
||||
$config->doc->form->batchmovedoc['users'] = array('type' => 'array', 'required' => false, 'default' => '', 'filter' => 'join');
|
||||
|
||||
$config->doc->form->addTemplateType['name'] = array('type' => 'string', 'required' => true, 'default' => '', 'filter' => 'trim');
|
||||
$config->doc->form->addTemplateType['root'] = array('type' => 'int', 'required' => true, 'default' => 1);
|
||||
$config->doc->form->addTemplateType['parent'] = array('type' => 'int', 'required' => false, 'default' => 0);
|
||||
|
||||
+516
-43
@@ -145,14 +145,15 @@ class doc extends control
|
||||
* 禅道数据列表。
|
||||
* Zentao data list.
|
||||
*
|
||||
* @param string $type
|
||||
* @param int $blockID
|
||||
* @param string $dataType view|markdown|html
|
||||
* @param string $type
|
||||
* @param int|string $blockID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function zentaoList(string $type, int $blockID)
|
||||
public function zentaoList(string $type, int|string $blockID)
|
||||
{
|
||||
if(is_string($blockID)) $blockID = (int)str_replace('__TML_ZENTAOLIST__', '', $blockID);
|
||||
|
||||
$blockData = $this->doc->getZentaoList($blockID);
|
||||
if(!$blockData)
|
||||
{
|
||||
@@ -164,17 +165,56 @@ class doc extends control
|
||||
return $this->sendError($this->lang->notFound);
|
||||
}
|
||||
|
||||
$this->app->loadClass('pager', true);
|
||||
$doc = $this->doc->getByID($blockData->doc);
|
||||
$this->view->isTemplate = !empty($doc->templateType) && $blockData->extra != 'fromReview';
|
||||
|
||||
$this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->doc->zentaoList[$type]);
|
||||
$this->view->type = $type;
|
||||
$this->view->settings = $blockData->settings;
|
||||
$this->view->idList = $blockData->content->idList;
|
||||
$this->view->cols = $blockData->content->cols;
|
||||
$this->view->data = $blockData->content->data;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter|pofirst|nodeleted');
|
||||
$this->view->blockID = $blockID;
|
||||
$this->view->pager = new pager(count($this->view->data), 10);
|
||||
if($this->view->isTemplate)
|
||||
{
|
||||
$this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->docTemplate->zentaoList[$type]);
|
||||
$this->view->type = $type;
|
||||
$this->view->blockID = $blockID;
|
||||
$this->view->settings = $blockData->settings;
|
||||
$this->view->searchTab = zget($blockData->content, 'searchTab', '');
|
||||
|
||||
if($type == 'productCase' || $type == 'projectCase') $this->view->caseStage = $blockData->content->caseStage;
|
||||
|
||||
return $this->display();
|
||||
}
|
||||
|
||||
$fromTemplate = $blockData->extra == 'fromTemplate' || $blockData->extra == 'fromReview';
|
||||
if($fromTemplate)
|
||||
{
|
||||
$this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->docTemplate->zentaoList[$type]);
|
||||
$this->view->searchTab = zget($blockData->content, 'searchTab', '');
|
||||
$this->view->isSetted = isset($blockData->content->data) && isset($blockData->content->cols) || isset($blockData->content->ganttOptions);
|
||||
if($type == 'productCase' || $type == 'projectCase') $this->view->caseStage = $blockData->content->caseStage;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->doc->zentaoList[$type]);
|
||||
}
|
||||
|
||||
if($type == 'gantt')
|
||||
{
|
||||
$this->view->ganttData = (array)zget($blockData->content, 'ganttOptions', array());
|
||||
$this->view->ganttFields = (array)zget($blockData->content, 'ganttFields', array());
|
||||
$this->view->showFields = zget($blockData->content, 'showFields', '');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->app->loadClass('pager', true);
|
||||
|
||||
$this->view->idList = (array)zget($blockData->content, 'idList', array());
|
||||
$this->view->cols = (array)zget($blockData->content, 'cols', array());
|
||||
$this->view->data = (array)zget($blockData->content, 'data', array());
|
||||
$this->view->pager = new pager(count($this->view->data), 10);
|
||||
}
|
||||
|
||||
$this->view->type = $type;
|
||||
$this->view->settings = $blockData->settings;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter|pofirst');
|
||||
$this->view->blockID = $blockID;
|
||||
$this->view->fromTemplate = $fromTemplate;
|
||||
|
||||
if(strpos(',productStory,ER,UR,planStory,projectStory', $type) !== false) $this->docZen->assignStoryGradeData($type);
|
||||
|
||||
@@ -193,6 +233,8 @@ class doc extends control
|
||||
* Export Zentao data list.
|
||||
*
|
||||
* @param int $blockID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxExportZentaoList(int $blockID)
|
||||
{
|
||||
@@ -208,7 +250,9 @@ class doc extends control
|
||||
* 构建禅道数据列表。
|
||||
* Build Zentao data list.
|
||||
*
|
||||
* @param int $docID
|
||||
* @param string $type
|
||||
* @param int $oldBlockID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -218,13 +262,20 @@ class doc extends control
|
||||
$docblock->doc = $docID;
|
||||
$docblock->type = $type;
|
||||
$docblock->settings = $this->post->url;
|
||||
$docblock->content = json_encode(array('cols' => json_decode($this->post->cols), 'data' => json_decode($this->post->data), 'idList' => $this->post->idList));
|
||||
if($type == 'gantt')
|
||||
{
|
||||
$docblock->content = json_encode(array('ganttOptions' => json_decode($this->post->ganttOptions), 'showFields' => $this->post->showFields, 'ganttFields' => json_decode($this->post->ganttFields)));
|
||||
}
|
||||
else
|
||||
{
|
||||
$docblock->content = json_encode(array('cols' => json_decode($this->post->cols), 'data' => json_decode($this->post->data), 'idList' => $this->post->idList));
|
||||
}
|
||||
|
||||
$this->dao->insert(TABLE_DOCBLOCK)->data($docblock)->exec();
|
||||
$newBlockID = $this->dao->lastInsertId();
|
||||
|
||||
if(dao::isError()) return print(json_encode(array('result' => 'fail', 'message' => dao::getError())));
|
||||
|
||||
$newBlockID = $this->dao->lastInsertId();
|
||||
|
||||
return print(json_encode(array('result' => 'success', 'oldBlockID' => $oldBlockID, 'newBlockID' => $newBlockID)));
|
||||
}
|
||||
|
||||
@@ -425,10 +476,10 @@ class doc extends control
|
||||
|
||||
$this->docZen->setAclForEditLib($lib);
|
||||
|
||||
$this->view->lib = $lib;
|
||||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||||
$this->view->users = $this->user->getPairs('noletter|noclosed', $lib->users);
|
||||
$this->view->libID = $libID;
|
||||
$this->view->lib = $lib;
|
||||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||||
$this->view->users = $this->user->getPairs('noletter|noclosed', $lib->users);
|
||||
$this->view->libID = $libID;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -493,6 +544,201 @@ class doc extends control
|
||||
return $this->send(array('result' => 'success', 'load' => $browseLink, 'app' => $this->app->tab));
|
||||
}
|
||||
|
||||
/**
|
||||
* 文档模板列表。
|
||||
* Browse template list.
|
||||
*
|
||||
* @param int $libID
|
||||
* @param string $type
|
||||
* @param int $docID
|
||||
* @param string $orderBy
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function browseTemplate(int $libID = 0, string $type = 'all', int $docID = 0, string $orderBy = 'id_desc', int $recPerPage = 20, int $pageID = 1, string $mode = 'home')
|
||||
{
|
||||
$this->lang->doc->menu->template['alias'] .= ',' . $this->app->rawMethod;
|
||||
$libModules = $this->doc->getTemplateModules($libID);
|
||||
if($mode == 'create' && empty($libModules)) return $this->send(array('result' => 'success', 'load' => array('alert' => $this->lang->docTemplate->createTypeFirst)));
|
||||
|
||||
$templateList = $this->doc->getDocTemplateList(0, $type, $orderBy);
|
||||
$templateList = $this->doc->filterDeletedDocs($templateList);
|
||||
$templateList = $this->doc->filterPrivDocs($templateList, 'template');
|
||||
$allModules = $this->doc->getTemplateModules();
|
||||
$allModules = array_column($allModules, 'fullName', 'id');
|
||||
foreach($templateList as $template) $template->moduleName = zget($allModules, $template->module);
|
||||
|
||||
$this->view->title = $this->lang->doc->template;
|
||||
$this->view->libID = $libID;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noclosed,noletter');
|
||||
$this->view->templateList = $templateList;
|
||||
$this->view->docID = $docID;
|
||||
$this->view->orderBy = $orderBy;
|
||||
$this->view->recPerPage = $recPerPage;
|
||||
$this->view->pageID = $pageID;
|
||||
$this->view->mode = $mode;
|
||||
$this->view->hasModules = count($libModules) ? true : false;
|
||||
$this->view->scopes = $this->doc->getTemplateScopes();
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个模板类型。
|
||||
* Add a template type.
|
||||
*
|
||||
* @param int $scope
|
||||
* @param int|string $parentModule
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function addTemplateType(int $scope, int|string $parentModule = '')
|
||||
{
|
||||
$moduleList = $this->doc->getTemplateModules($scope, '1');
|
||||
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$this->lang->doc->name = $this->lang->docTemplate->typeName;
|
||||
$moduleData = form::data($this->config->doc->form->addTemplateType)
|
||||
->setDefault('type', 'docTemplate')
|
||||
->setDefault('path', '')
|
||||
->get();
|
||||
$moduleData->grade = $moduleData->parent === 0 ? 1 : 2;
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
|
||||
$this->doc->addTemplateType($moduleData);
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
|
||||
return $this->docZen->responseAfterAddTemplateType($scope);
|
||||
}
|
||||
|
||||
$moduleItems = array();
|
||||
if($parentModule === 0)
|
||||
{
|
||||
$moduleItems[] = array('value' => 0, 'text' => '/');
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach($moduleList as $module) $moduleItems[] = array('value' => $module->id, 'text' => '/' . $module->name);
|
||||
$moduleItems[] = array('value' => 0, 'text' => '/');
|
||||
}
|
||||
|
||||
$scopeList = $this->doc->getTemplateScopes();
|
||||
|
||||
$this->view->scope = $scope;
|
||||
$this->view->scopes = $this->doc->getScopeItems($scopeList);
|
||||
$this->view->moduleItems = $moduleItems;
|
||||
$this->view->parentModule = $parentModule === '' ? current($moduleItems) : $parentModule;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除一个模板类型。
|
||||
* Delete a template type.
|
||||
*
|
||||
* @param int $moduleID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function deleteTemplateType(int $moduleID)
|
||||
{
|
||||
$templates = $this->doc->getTemplatesByType($moduleID);
|
||||
if(empty($templates))
|
||||
{
|
||||
$this->dao->update(TABLE_MODULE)->set('deleted')->eq('1')->where('id')->eq($moduleID)->andWhere('type')->eq('docTemplate')->exec();
|
||||
$this->dao->update(TABLE_MODULE)->set('deleted')->eq('1')->where('parent')->eq($moduleID)->andWhere('type')->eq('docTemplate')->exec();
|
||||
return $this->sendSuccess(array('load' => true));
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->send(array('result' => 'fail', 'message' => $this->lang->docTemplate->errorDeleteType));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑一个模板类型。
|
||||
* Edit a template type.
|
||||
*
|
||||
* @param int $moduleID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function editTemplateType(int $moduleID)
|
||||
{
|
||||
echo $this->fetch('tree', 'edit', "moduleID={$moduleID}&type=docTemplate");
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个文档模板。
|
||||
* Create a doc template.
|
||||
*
|
||||
* @param int $moduleID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function createTemplate(int $moduleID = 0)
|
||||
{
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$this->lang->doc->title = $_POST['type'] == 'chapter' ? $this->lang->doc->chapterName : $this->lang->docTemplate->title;
|
||||
|
||||
helper::setcookie('lastDocModule', $moduleID);
|
||||
$docData = form::data()
|
||||
->setDefault('addedBy', $this->app->user->account)
|
||||
->setDefault('editedBy', $this->app->user->account)
|
||||
->get();
|
||||
|
||||
if(!empty($docData->parent))
|
||||
{
|
||||
$parentTemplate = $this->doc->fetchByID((int)$docData->parent);
|
||||
$docData->module = $parentTemplate->module;
|
||||
$docData->lib = (int)$parentTemplate->lib;
|
||||
$docData->acl = $parentTemplate->acl;
|
||||
$docData->templateType = $parentTemplate->templateType;
|
||||
}
|
||||
|
||||
$docResult = $this->doc->create($docData);
|
||||
if(!$docResult || dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
return $this->docZen->responseAfterCreate($docResult, 'docTemplate');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑一个文档。
|
||||
* Edit a doc.
|
||||
*
|
||||
* @param int $docID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function editTemplate(int $docID)
|
||||
{
|
||||
$doc = $this->doc->getByID($docID);
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$changes = $files = array();
|
||||
$docData = form::data()
|
||||
->setDefault('editedBy', $this->app->user->account)
|
||||
->setIF(!isset($_POST['parent']), 'parent', $doc->parent)
|
||||
->setIF(strpos(",$doc->editedList,", ",{$this->app->user->account},") === false, 'editedList', $doc->editedList . ",{$this->app->user->account}")
|
||||
->setIF($this->post->type == 'chapter', 'content', $doc->content)
|
||||
->setIF($this->post->type == 'chapter', 'rawContent', $doc->rawContent)
|
||||
->get();
|
||||
|
||||
$result = $this->doc->update($docID, $docData);
|
||||
if(dao::isError())
|
||||
{
|
||||
if(!empty(dao::$errors['lib']) || !empty(dao::$errors['keywords'])) return $this->send(array('result' => 'fail', 'message' => dao::getError(), 'callback' => "zui.Modal.open({id: 'modalBasicInfo'});"));
|
||||
return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
}
|
||||
|
||||
$changes = $result['changes'];
|
||||
$files = $result['files'];
|
||||
return $this->docZen->responseAfterEditTemplate($doc, $changes, $files);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文档。
|
||||
* Upload docs.
|
||||
@@ -614,7 +860,7 @@ class doc extends control
|
||||
$docData->module = $parentDoc->module;
|
||||
}
|
||||
|
||||
$docResult = $this->doc->create($docData, $this->post->labels);
|
||||
$docResult = $this->doc->create($docData);
|
||||
if(!$docResult || dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
return $this->docZen->responseAfterCreate($docResult);
|
||||
}
|
||||
@@ -774,6 +1020,28 @@ class doc extends control
|
||||
return $this->sendSuccess(array('load' => $this->session->docList ? $this->session->docList : $this->createLink('doc', 'index')));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除一个文档模板。
|
||||
* Delete a doctemplate.
|
||||
*
|
||||
* @param int $templateID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function deleteTemplate(int $templateID)
|
||||
{
|
||||
$this->doc->deleteTemplate($templateID);
|
||||
|
||||
/* Delete template files. */
|
||||
$template = $this->doc->getByID($templateID);
|
||||
if($template->files) $this->doc->deleteFiles(array_keys($template->files));
|
||||
|
||||
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
|
||||
$link = $this->createLink('doc', 'browseTemplate');
|
||||
return $this->sendSuccess(array('load' => $link));
|
||||
}
|
||||
|
||||
/**
|
||||
* 收藏一个文档。
|
||||
* Collect a doc.
|
||||
@@ -844,6 +1112,27 @@ class doc extends control
|
||||
return print(json_encode(array('libs' => $libItems, 'modules' => $moduleItems)));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* AJAX: 获取范围下的类型。
|
||||
* Ajax get types of scope.
|
||||
*
|
||||
* @param int $libID
|
||||
* @access public
|
||||
* @return json
|
||||
*/
|
||||
public function ajaxGetScopeTypes(int $libID = 0)
|
||||
{
|
||||
$optionMenu = $this->loadModel('tree')->getOptionMenu($libID, 'docTemplate', 0, 'all', 'nodeleted', 'all');
|
||||
$types = array();
|
||||
foreach($optionMenu as $menuID => $menu)
|
||||
{
|
||||
if(empty($menuID)) continue;
|
||||
$types[] = array('text' => $menu, 'value' => $menuID, 'keys' => $menu);
|
||||
}
|
||||
return print(json_encode($types));
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX: 通过空间类型获取文档库。
|
||||
* AJAX: Get libs by type.
|
||||
@@ -1026,6 +1315,12 @@ class doc extends control
|
||||
}
|
||||
unset($_SESSION["doc_{$doc->id}_nopriv"]);
|
||||
|
||||
if($doc->templateType)
|
||||
{
|
||||
echo $this->fetch('doc', 'browseTemplate', "libID=$doc->lib&type=all&docID=$docID&orderBy=id_desc&recPerPage=20&pageID=1&mode=view");
|
||||
return;
|
||||
}
|
||||
|
||||
$lib = $this->doc->getLibByID((int)$doc->lib);
|
||||
$objectType = isset($lib->type) ? $lib->type : 'custom';
|
||||
if($objectType == 'api')
|
||||
@@ -1623,6 +1918,75 @@ class doc extends control
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动文档模板
|
||||
* Move document template.
|
||||
*
|
||||
* @param int $docID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function moveTemplate(int $docID)
|
||||
{
|
||||
$doc = $this->doc->getByID($docID);
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$data = form::data()
|
||||
->setIF(!isset($_POST['lib']), 'lib', $doc->lib)
|
||||
->setIF(!isset($_POST['module']), 'module', $doc->module)
|
||||
->setIF(!isset($_POST['parent']), 'parent', $doc->parent)
|
||||
->setIF(!isset($_POST['acl']), 'acl', $doc->acl)
|
||||
->get();
|
||||
$changes = common::createChanges($doc, $data);
|
||||
if($changes)
|
||||
{
|
||||
$basicInfoChanged = false;
|
||||
foreach($changes as $change)
|
||||
{
|
||||
if(in_array($change['field'], array('module', 'lib', 'acl'))) $basicInfoChanged = true;
|
||||
}
|
||||
$this->doc->doUpdateDoc($docID, $data, $basicInfoChanged);
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
|
||||
$actionID = $this->loadModel('action')->create('docTemplate', $docID, 'Moved', '', json_encode(array('from' => $doc->lib, 'to' => $data->lib)));
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
|
||||
$newDoc = $this->doc->getByID($docID);
|
||||
if(!$this->doc->checkPrivDoc($newDoc))
|
||||
{
|
||||
$link = $this->createLink('doc', 'browseTemplate', "libID={$doc->lib}&type=all&docID=0&orderBy=id_desc&recPerPage=20&pageID=1&mode=list");
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $link, 'doc' => $newDoc));
|
||||
}
|
||||
|
||||
$docAppAction = array('executeCommand', 'handleMovedDoc', array($docID, '1', $data->lib));
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'docApp' => $docAppAction));
|
||||
}
|
||||
|
||||
if(!empty($doc->parent))
|
||||
{
|
||||
$parentDoc = $this->doc->fetchByID($doc->parent);
|
||||
$chapterAndDocs = $this->doc->getDocsOfLibs(array($doc->lib), 'template', $docID, true);
|
||||
if(!isset($chapterAndDocs[$doc->parent])) $chapterAndDocs[$doc->parent] = $parentDoc;
|
||||
|
||||
$parentPath = trim($parentDoc->path, ',') . ",";
|
||||
$topTemplate = substr($parentPath, 0, strpos($parentPath, ',')) ?: $doc->parent;
|
||||
foreach($chapterAndDocs as $key => $template)
|
||||
{
|
||||
if(strpos(",{$template->path},", ",{$topTemplate},") === false) unset($chapterAndDocs[$key]);
|
||||
}
|
||||
$this->view->chapterAndDocs = $this->doc->buildNestedDocs($chapterAndDocs);
|
||||
}
|
||||
|
||||
$scopeList = $this->doc->getTemplateScopes();
|
||||
|
||||
$this->view->scopeItems = $this->doc->getScopeItems($scopeList);
|
||||
$this->view->doc = $doc;
|
||||
$this->view->docID = $docID;
|
||||
$this->view->modules = $this->loadModel('tree')->getOptionMenu((int)$doc->lib, 'docTemplate', 0, 'all', 'nodeleted', 'all');
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch move document.
|
||||
*
|
||||
@@ -1888,22 +2252,43 @@ class doc extends control
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetSpaceData(string $type = 'custom', int $spaceID = 0, string $picks = '')
|
||||
public function ajaxGetSpaceData(string $type = 'custom', int $spaceID = 0, string $picks = '', int $libID = 0)
|
||||
{
|
||||
$this->doc->setMenuByType($type, (int)$spaceID, 0);
|
||||
|
||||
$noPicks = empty($picks);
|
||||
$picks = $noPicks ? '' : ",$picks,";
|
||||
if($type === 'template')
|
||||
{
|
||||
$modules = $this->doc->getTemplateModules();
|
||||
$moduleNames = array_column($modules, 'fullName', 'id');
|
||||
$templateList = $this->doc->getDocTemplateList(0, 'all');
|
||||
$templateList = $this->doc->filterDeletedDocs($templateList);
|
||||
$templateList = $this->doc->filterPrivDocs($templateList, 'template');
|
||||
foreach($templateList as $template)
|
||||
{
|
||||
$template->moduleName = zget($moduleNames, $template->module);
|
||||
}
|
||||
$data = array('spaceID' => $spaceID, 'docs' => array_values($templateList));
|
||||
$data['spaces'][] = array('name' => $this->lang->doc->template, 'id' => $spaceID);
|
||||
$data['modules'] = $modules;
|
||||
|
||||
list($spaces, $spaceID) = $this->doc->getSpaces($type, $spaceID);
|
||||
$data = array('spaceID' => (int)$spaceID);
|
||||
$libs = $this->doc->getLibsOfSpace($type, $spaceID);
|
||||
$libIds = array_keys($libs);
|
||||
$scopeList = $this->doc->getTemplateScopes();
|
||||
foreach($scopeList as $scope) $data['libs'][] = array('id' => $scope->id, 'name' => $scope->name, 'space' => $spaceID);
|
||||
}
|
||||
else
|
||||
{
|
||||
$noPicks = empty($picks);
|
||||
$picks = $noPicks ? '' : ",$picks,";
|
||||
|
||||
if($noPicks || strpos($picks, ',space,') !== false) $data['spaces'] = $spaces;
|
||||
if($noPicks || strpos($picks, ',lib,') !== false) $data['libs'] = array_values($libs);
|
||||
if($noPicks || strpos($picks, ',module,') !== false) $data['modules'] = array_values($this->doc->getModulesOfLibs($libIds));
|
||||
if($noPicks || strpos($picks, ',doc,') !== false) $data['docs'] = array_values($this->doc->getDocsOfLibs($libIds + array($spaceID), $type));
|
||||
list($spaces, $spaceID) = $this->doc->getSpaces($type, $spaceID);
|
||||
$data = array('spaceID' => (int)$spaceID);
|
||||
$libs = $this->doc->getLibsOfSpace($type, $spaceID);
|
||||
$libIds = array_keys($libs);
|
||||
|
||||
if($noPicks || strpos($picks, ',space,') !== false) $data['spaces'] = $spaces;
|
||||
if($noPicks || strpos($picks, ',lib,') !== false) $data['libs'] = array_values($libs);
|
||||
if($noPicks || strpos($picks, ',module,') !== false) $data['modules'] = array_values($this->doc->getModulesOfLibs($libIds));
|
||||
if($noPicks || strpos($picks, ',doc,') !== false) $data['docs'] = array_values($this->doc->getDocsOfLibs($libIds + array($spaceID), $type));
|
||||
}
|
||||
|
||||
$this->send($data);
|
||||
}
|
||||
@@ -1930,9 +2315,9 @@ class doc extends control
|
||||
$doc = $this->doc->getByID($docID, $version);
|
||||
$doc->lib = (int)$doc->lib;
|
||||
$doc->module = (int)$doc->module;
|
||||
$doc->privs = array('edit' => common::hasPriv('doc', 'edit', $doc));
|
||||
$doc->privs = array('edit' => common::hasPriv('doc', 'edit', $doc) && $doc->acl == 'open');
|
||||
$doc->editors = $this->doc->getEditors($docID);
|
||||
$doc->draft = $this->doc->getDraft($docID);
|
||||
$doc->draft = $doc->status == 'draft' ? $this->doc->getContent($docID, $version) : null;
|
||||
|
||||
$lib = $this->doc->getLibByID((int)$doc->lib);
|
||||
$objectType = $lib->type;
|
||||
@@ -2040,15 +2425,27 @@ class doc extends control
|
||||
if($modalType == 'doc')
|
||||
{
|
||||
$title = $parentID ? $this->lang->doc->addSubDoc : $this->lang->doc->create;
|
||||
if($objectType == 'template') $title = $parentID ? $this->lang->docTemplate->addSubDocTemplate : $this->lang->docTemplate->create;
|
||||
if($isDraft == 'no') $title = $this->lang->settings;
|
||||
}
|
||||
if($modalType == 'chapter') $title = $isCreate ? $this->lang->doc->addChapter : $this->lang->doc->editChapter;
|
||||
|
||||
$chapterAndDocs = $this->doc->getDocsOfLibs(array($libID), $objectType, $docID);
|
||||
$modulePairs = empty($libID) || $modalType == 'chapter' ? array() : $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
|
||||
$chapterAndDocs = $this->doc->getDocsOfLibs(array($libID), $objectType, $docID, $objectType == 'template' ? true : false);
|
||||
if($objectType == 'template' && !empty($moduleID)) $chapterAndDocs = array_filter($chapterAndDocs, fn($docInfo) => $docInfo->module == $moduleID);
|
||||
if(isset($doc) && !empty($doc->parent) && !isset($chapterAndDocs[$doc->parent])) $chapterAndDocs[$doc->parent] = $this->doc->fetchByID($doc->parent);
|
||||
$chapterAndDocs = $this->doc->buildNestedDocs($chapterAndDocs, $modulePairs);
|
||||
$this->view->chapterAndDocs = $chapterAndDocs;
|
||||
$modulePairs = empty($libID) || $modalType == 'chapter' || $objectType == 'template' ? array() : $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
|
||||
|
||||
if($objectType == 'template' && !empty($parentID))
|
||||
{
|
||||
$parentDoc = $this->doc->fetchByID($parentID);
|
||||
$parentPath = trim($parentDoc->path, ',') . ",";
|
||||
$topTemplate = substr($parentPath, 0, strpos($parentPath, ',')) ?: $parentID;
|
||||
foreach($chapterAndDocs as $key => $template)
|
||||
{
|
||||
if(strpos(",{$template->path},", ",{$topTemplate},") === false) unset($chapterAndDocs[$key]);
|
||||
}
|
||||
}
|
||||
$this->view->chapterAndDocs = $this->doc->buildNestedDocs($chapterAndDocs, $modulePairs);
|
||||
|
||||
if($isCreate)
|
||||
{
|
||||
@@ -2059,7 +2456,7 @@ class doc extends control
|
||||
}
|
||||
|
||||
if(empty($objectID) && $lib) $objectID = $this->doc->getObjectIDByLib($lib);
|
||||
if($lib) $objectType = $lib->type;
|
||||
if($lib && $objectType != 'template') $objectType = $lib->type;
|
||||
|
||||
$unclosed = strpos($this->config->doc->custom->showLibs, 'unclosed') !== false ? 'unclosedProject' : '';
|
||||
$libPairs = $this->doc->getLibs($objectType, "{$unclosed}", $libID, $objectID);
|
||||
@@ -2077,7 +2474,7 @@ class doc extends control
|
||||
$moduleID = (int)$doc->module;
|
||||
$libID = (int)$doc->lib;
|
||||
$lib = $this->doc->getLibByID($libID);
|
||||
$objectType = $lib->type;
|
||||
if($lib && $objectType != 'template') $objectType = $lib->type;
|
||||
$objectID = $this->doc->getObjectIDByLib($lib);
|
||||
|
||||
$libPairs = $this->doc->getLibs($objectType, '', $libID, $objectID);
|
||||
@@ -2088,10 +2485,19 @@ class doc extends control
|
||||
$this->view->optionMenu = $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0);
|
||||
}
|
||||
|
||||
if($objectType == 'template')
|
||||
{
|
||||
$scopeList = $this->doc->getTemplateScopes();
|
||||
$this->view->scopeItems = $this->doc->getScopeItems($scopeList);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->view->users = $this->user->getPairs('nocode|noclosed|nodeleted');
|
||||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||||
}
|
||||
|
||||
$this->view->docID = $docID;
|
||||
$this->view->mode = empty($docID) ? 'create' : 'edit';
|
||||
$this->view->users = $this->user->getPairs('nocode|noclosed|nodeleted');
|
||||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||||
$this->view->libID = $libID;
|
||||
$this->view->moduleID = $moduleID;
|
||||
$this->view->objectID = $objectID;
|
||||
@@ -2140,4 +2546,71 @@ class doc extends control
|
||||
$user = $this->doc->getUserByConfluenceUserID($username);
|
||||
return $this->send(array('result' => 'success', 'data'=> $user));
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage scope.
|
||||
* 维护范围。
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function manageScope()
|
||||
{
|
||||
$scopeList = $this->doc->getTemplateScopes();
|
||||
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$scopes = $this->post->scopes;
|
||||
|
||||
$oldScopes = $newScopes = array();
|
||||
foreach($scopes as $id => $name)
|
||||
{
|
||||
if(strpos((string)$id, 'id') !== false)
|
||||
{
|
||||
$scopeID = str_replace('id', '', $id);
|
||||
$oldScopes[$scopeID] = $name;
|
||||
}
|
||||
else
|
||||
{
|
||||
$newScopes[$id] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
$deletedScopes = array_diff(array_keys($scopeList), array_keys($oldScopes));
|
||||
if(!empty($deletedScopes)) $this->doc->deleteTemplateScopes($deletedScopes);
|
||||
if(dao::isError()) return $this->sendError(array('message' => dao::getError()));
|
||||
|
||||
if(!empty($oldScopes)) $this->doc->updateTemplateScopes($oldScopes);
|
||||
if(dao::isError()) return $this->sendError(array('message' => dao::getError()));
|
||||
|
||||
if(!empty($newScopes)) $this->doc->insertTemplateScopes($newScopes);
|
||||
if(dao::isError()) return $this->sendError(array('message' => dao::getError()));
|
||||
|
||||
return $this->sendSuccess(array('closeModal' => true, 'load' => true));
|
||||
}
|
||||
|
||||
$this->view->scopeList = $scopeList;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX: Judge can be deleted scope.
|
||||
* AJAX: 判断范围是否可以被删除。
|
||||
*
|
||||
* @param int $scopeID
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function ajaxJudgeCanBeDeleted(int $scopeID = 0)
|
||||
{
|
||||
if(empty($scopeID)) return $this->sendSuccess(array('message' => 'success'));
|
||||
|
||||
$templates = $this->doc->getScopeTemplates(array($scopeID));
|
||||
if(!empty($templates[$scopeID])) return $this->sendError($this->lang->docTemplate->scopeHasTemplateTips);
|
||||
|
||||
$modules = $this->doc->getTemplateModules($scopeID);
|
||||
if(!empty($modules)) return $this->sendError($this->lang->docTemplate->scopeHasModuleTips);
|
||||
|
||||
return $this->sendSuccess(array('message' => 'success'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.config-tip{background-color: var(--color-surface-light); color: var(--color-gray-400)}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
window.changeScope = function(e)
|
||||
{
|
||||
const scope = e.target.value;
|
||||
loadModal($.createLink('doc', 'addTemplateType', `scope=${scope}`));
|
||||
}
|
||||
@@ -0,0 +1,681 @@
|
||||
const savingDocData = {};
|
||||
let docBasicModal = {};
|
||||
let currentUser = null;
|
||||
/**
|
||||
* 获取文档界面上的表格初始化选项。
|
||||
* Get the table initialization options on the doc UI.
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {object} info
|
||||
* @returns {object}
|
||||
*/
|
||||
function getTableOptions(options, info)
|
||||
{
|
||||
const lang = getDocAppLang();
|
||||
|
||||
options.data.sort((a, b) => a.addedDate > b.addedDate ? -1 : 1);
|
||||
|
||||
templateCols = [];
|
||||
templateCols.push({...options.cols.find(col => col.name === 'rawID'), type: 'id'});
|
||||
|
||||
let title = options.cols.find(col => col.name == 'title');
|
||||
let addedBy = options.cols.find(col => col.name == 'addedBy');
|
||||
let addedDate = options.cols.find(col => col.name == 'addedDate');
|
||||
let editedBy = options.cols.find(col => col.name == 'editedBy');
|
||||
let editedDate = options.cols.find(col => col.name == 'editedDate');
|
||||
let actionsCol = options.cols.find(col => col.name == 'actions');
|
||||
let typeCol = {name: 'moduleName', title: lang.tableCols.type, type: 'string', sort: true};
|
||||
let viewsCol = {name: 'views', title: lang.tableCols.views, type: 'number', sort: true};
|
||||
let descCol = {name: 'templateDesc', title: lang.tableCols.desc, type: 'desc', sort: true}
|
||||
|
||||
title.title = lang.tableCols.title;
|
||||
addedBy.title = lang.tableCols.addedBy;
|
||||
addedDate.title = lang.tableCols.addedDate;
|
||||
editedBy.title = lang.tableCols.editedBy;
|
||||
editedDate.title = lang.tableCols.editedDate;
|
||||
actionsCol.title = lang.tableCols.actions;
|
||||
|
||||
templateCols.push(title);
|
||||
templateCols.push(typeCol);
|
||||
templateCols.push(addedBy);
|
||||
templateCols.push(addedDate);
|
||||
templateCols.push(editedBy);
|
||||
templateCols.push(editedDate);
|
||||
templateCols.push(viewsCol);
|
||||
templateCols.push(descCol);
|
||||
templateCols.push(actionsCol);
|
||||
|
||||
options.cols = templateCols;
|
||||
options.cols.forEach(col =>
|
||||
{
|
||||
if(col.name === 'actions' && col.actionsMap)
|
||||
{
|
||||
col.actions = col.actions.filter(action => (action !== 'move' && docAppHasPriv(action)));
|
||||
delete col.actionsMap.move;
|
||||
|
||||
const privMap = {edit: docAppHasPriv('edit'), delete: docAppHasPriv('delete')};
|
||||
const actionHints = {edit: lang.editTemplate, delete: lang.deleteTemplate};
|
||||
$.each(col.actionsMap, (key, value) =>
|
||||
{
|
||||
if(typeof actionHints[key] === 'string') value.hint = actionHints[key];
|
||||
value.disabled = !privMap[key];
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
options.checkable = false;
|
||||
|
||||
options.footer = options.footer.filter(f => f !== 'checkbox');
|
||||
options.footer = options.footer.filter(f => f !== 'checkedInfo');
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
function mergeDocFormData(doc, formData)
|
||||
{
|
||||
if(!doc || !formData) return;
|
||||
const keys = new Set(formData.keys());
|
||||
for(const key of keys)
|
||||
{
|
||||
const values = formData.getAll(key);
|
||||
if(!values.length) continue;
|
||||
if(key === 'module' || key === 'lib') doc[key] = +values[0];
|
||||
else doc[key] = values.length > 1 ? values : values[0];
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
function showDocBasicModal(parentID, docID, isDraft, modalType = 'doc')
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
const spaceID = docApp.spaceID;
|
||||
const libID = docApp.libID;
|
||||
const moduleID = docApp.moduleID;
|
||||
const url = $.createLink('doc', 'setDocBasic', `objectType=template&objectID=${spaceID}&libID=${libID}&moduleID=${moduleID}&parentID=${parentID || 0}&docID=${docID || 0}&isDraft=${isDraft ? 'yes' : 'no'}&modalType=${modalType}`);
|
||||
|
||||
if(docBasicModal.doc === docID && docBasicModal.current)
|
||||
{
|
||||
docBasicModal.current.show();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(docBasicModal.current) docBasicModal.current.destroy();
|
||||
docBasicModal.doc = docID;
|
||||
zui.Modal.open(
|
||||
{
|
||||
ref : docBasicModal,
|
||||
url : url,
|
||||
destroyOnHide: false,
|
||||
cache : true,
|
||||
request: {
|
||||
error: error => {
|
||||
if(docBasicModal.current) docBasicModal.current.hide();
|
||||
showSaveFailedAlert(error);
|
||||
}
|
||||
},
|
||||
onHidden: () => {
|
||||
if(!docBasicModal.keepOnHide && docBasicModal.current) docBasicModal.current.destroy();
|
||||
},
|
||||
$onDestroy: () => {
|
||||
if(docBasicModal.current) docBasicModal = {};
|
||||
}
|
||||
});
|
||||
}
|
||||
return new Promise((resolve) => {window.docBasicModalResolver = resolve;});
|
||||
}
|
||||
|
||||
function showDocSettingModal(_, args)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
const doc = docApp.doc;
|
||||
const docID = args[0] || doc.id;
|
||||
const docType = args[1] || doc.contentType;
|
||||
const saveEdited = args[2] || 0;
|
||||
showDocBasicModal(doc.data.parent, docID).then(formData => {
|
||||
savingDocData[docID] = formData;
|
||||
if(saveEdited == 1)
|
||||
{
|
||||
const docData = {
|
||||
content : doc.data.content,
|
||||
status : doc.data.status,
|
||||
contentType: doc.data.contentType,
|
||||
type : doc.data.type,
|
||||
lib : doc.data.lib,
|
||||
module : doc.data.module,
|
||||
title : doc.data.title,
|
||||
keywords : doc.data.keywords,
|
||||
acl : doc.data.acl,
|
||||
space : doc.data.space,
|
||||
uid : doc.data.uid,
|
||||
};
|
||||
mergeDocFormData(docData, formData);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 向服务器提交新文档。
|
||||
* Submit new doc to server.
|
||||
*
|
||||
* @param {object} doc
|
||||
* @param {number} spaceID
|
||||
* @param {number} libID
|
||||
* @param {number} moduleID
|
||||
* @param {FormData} formData
|
||||
* @returns
|
||||
*/
|
||||
function submitNewDoc(doc, spaceID, libID, moduleID, formData, afterCreate)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
|
||||
if(docApp.isSavingDoc) return;
|
||||
docApp.isSavingDoc = true;
|
||||
$(docApp.element).find('[zui-command^="saveDoc"],[zui-command^="saveNewDoc"]').attr('disabled', true);
|
||||
|
||||
const spaceType = docApp.signals.spaceType.value;
|
||||
const module = docApp.treeMap.modules.get(formData && moduleID === 0 ? parseInt(formData.get('module')) : moduleID);
|
||||
const url = $.createLink('doc', 'createTemplate', `libID=${libID}&moduleID=${moduleID}`);
|
||||
const docData =
|
||||
{
|
||||
rawContent : doc.content,
|
||||
content : doc.html,
|
||||
status : doc.status || 'normal',
|
||||
contentType : doc.contentType,
|
||||
type : doc.type || 'text',
|
||||
lib : libID,
|
||||
module : moduleID,
|
||||
title : doc.title,
|
||||
keywords : doc.keywords,
|
||||
acl : 'private',
|
||||
space : spaceType,
|
||||
project : 0,
|
||||
templateType: module && module.data ? module.data.short : '',
|
||||
uid : (doc.uid || `doc${doc.id}`),
|
||||
parent : doc.parent
|
||||
};
|
||||
if(formData) mergeDocFormData(docData, formData);
|
||||
docApp.props.fetcher = $.createLink('doc', 'ajaxGetSpaceData', `type=template&spaceID=${spaceID}&picks={picks}&libID=${libID}`);
|
||||
const getErrorMessage = (res) => {
|
||||
if(typeof res.message === 'string') return res.message;
|
||||
if(typeof res.message === 'object' && res.message && Object.values(res.message).length)
|
||||
{
|
||||
for(const x of Object.values(res.message))
|
||||
{
|
||||
if(typeof x === 'string') return x;
|
||||
if(Array.isArray(x) && x.length) return x[0];
|
||||
}
|
||||
}
|
||||
if(typeof data.error === 'string') return data.error;
|
||||
return getLang('errorOccurred');
|
||||
};
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
$.post(url, docData, (res) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
const data = JSON.parse(res);
|
||||
if(!checkResponse(data)) return;
|
||||
if(typeof data !== 'object' || data.result === 'fail')
|
||||
{
|
||||
throw new Error(getErrorMessage(data));
|
||||
}
|
||||
const newDoc = $.extend(doc, {id: data.id}, docData, data.doc, {status: doc.status || data.status});
|
||||
if (!newDoc.space.includes('.')) {
|
||||
newDoc.space = `${spaceType}.${docData[spaceType]}`;
|
||||
}
|
||||
resolve(newDoc);
|
||||
if(afterCreate)
|
||||
{
|
||||
docApp.load(null, null, null, {noLoading: true, picks: 'doc'}).then(() => {
|
||||
afterCreate(newDoc);
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (error)
|
||||
{
|
||||
showSaveFailedAlert(error);
|
||||
reject(error);
|
||||
}
|
||||
}).fail(error => {
|
||||
resolve(false);
|
||||
showSaveFailedAlert(error);
|
||||
}).complete(() => {
|
||||
docApp.isSavingDoc = false;
|
||||
$(docApp.element).find('[zui-command^="saveDoc"],[zui-command^="saveNewDoc"]').removeAttr('disabled');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 向服务器提交编辑文档内容。
|
||||
* Submit edit doc to server.
|
||||
*
|
||||
* @param {FormData} formData
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function submitEditDoc(formData)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
const doc = docApp.doc.data;
|
||||
const url = $.createLink('doc', 'editTemplate', `templateID=${doc.id}`);
|
||||
if(formData) mergeDocFormData(doc, formData);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
$.post(url, doc, (res) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
const data = JSON.parse(res);
|
||||
if(!checkResponse(data)) return;
|
||||
if(typeof data !== 'object' || data.result === 'fail')
|
||||
{
|
||||
let message = data.message || data.error || getLang('errorOccurred');
|
||||
if(typeof message === 'object') message = Object.values(message).map(x => Array.isArray(x) ? x.join('\n') : x).join('\n');
|
||||
throw new Error(message);
|
||||
}
|
||||
resolve(doc);
|
||||
}
|
||||
catch (error)
|
||||
{
|
||||
resolve(false);
|
||||
showSaveFailedAlert(error);
|
||||
if(!error.message) return;
|
||||
}
|
||||
}).fail(error => {
|
||||
resolve(false);
|
||||
showSaveFailedAlert(error);
|
||||
}).complete(() => {
|
||||
docApp.load(null, null, null, {noLoading: true, picks: 'doc'});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理创建文档的操作请求,向服务器发送请求并返回创建的文档对象。
|
||||
* Handle the create doc operation request, send a request to the server and return the created doc object.
|
||||
*/
|
||||
function handleCreateDoc(doc, spaceID, libID, moduleID)
|
||||
{
|
||||
return showDocBasicModal(0, 0, doc.status === 'draft').then((formData) => {
|
||||
moduleID = parseInt(formData.get('module'));
|
||||
return submitNewDoc(doc, spaceID, libID, moduleID, formData);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理保存文档的操作请求,向服务器发送请求并返回保存的文档对象。
|
||||
* Handle the save doc operation request, send a request to the server and return the saved doc object.
|
||||
*/
|
||||
function handleSaveDoc(doc)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
const spaceType = docApp.signals.spaceType.value;
|
||||
const libID = docApp.signals.libID.value;
|
||||
const moduleID = docApp.signals.moduleID.value;
|
||||
const url = $.createLink('doc', 'editTemplate', `docID=${doc.id}`);
|
||||
const docData = {
|
||||
rawContent : doc.content,
|
||||
status : doc.status || 'normal',
|
||||
contentType: doc.contentType,
|
||||
type : 'text',
|
||||
lib : libID,
|
||||
module : moduleID,
|
||||
title : doc.title,
|
||||
keywords : doc.keywords,
|
||||
acl : doc.acl,
|
||||
content : doc.html,
|
||||
space : spaceType,
|
||||
uid : (doc.uid || `doc${doc.id}`),
|
||||
};
|
||||
|
||||
const docAppData = docApp.doc.data;
|
||||
if (doc.id === docAppData.id) docData.mailto = docAppData.mailto;
|
||||
|
||||
if(savingDocData[doc.id])
|
||||
{
|
||||
mergeDocFormData(docData, savingDocData[doc.id]);
|
||||
delete savingDocData[doc.id];
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
$.post(url, docData, (res) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
const data = JSON.parse(res);
|
||||
if(!checkResponse(data)) return;
|
||||
if(typeof data !== 'object' || data.result === 'fail')
|
||||
{
|
||||
let message = data.message || data.error || getLang('errorOccurred');
|
||||
if(typeof message === 'object') message = Object.values(message).map(x => Array.isArray(x) ? x.join('\n') : x).join('\n');
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
doc = $.extend({}, doc, docData, data.doc);
|
||||
const libID = +doc.lib;
|
||||
const lib = docApp.getLib(libID);
|
||||
if(!lib)
|
||||
{
|
||||
resolve(false);
|
||||
return loadPage($.createLink('doc', 'view', `docID=${doc.id}`));
|
||||
}
|
||||
|
||||
delete doc.title;
|
||||
delete doc.keywords;
|
||||
delete doc.content;
|
||||
resolve(doc);
|
||||
}
|
||||
catch (error)
|
||||
{
|
||||
resolve(false);
|
||||
if(!error.message) return;
|
||||
zui.Modal.alert(error.message);
|
||||
}
|
||||
}).fail(error => {
|
||||
resolve(false);
|
||||
showSaveFailedAlert(error);
|
||||
}).complete(() => {
|
||||
docApp.isSavingDoc = false;
|
||||
docApp.props.fetcher = $.createLink('doc', 'ajaxGetSpaceData', `type=template&spaceID=${docAppData.space}&picks={picks}&libID=${docAppData.lib}`);
|
||||
$(docApp.element).find('[zui-command^="saveDoc"],[zui-command^="saveNewDoc"]').removeAttr('disabled');
|
||||
const {id, acl, users, addedBy} = doc;
|
||||
if(acl == 'private' && !users.includes(currentUser) && addedBy !== currentUser)
|
||||
{
|
||||
if(docApp.hasEditingDoc)
|
||||
{
|
||||
docApp.cancelEditDoc().then(() => {
|
||||
docApp.delete('doc', id);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
docApp.delete('doc', id);
|
||||
}
|
||||
}
|
||||
docApp.load(null, null, null, {noLoading: true, picks: 'doc'});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const customRenders =
|
||||
{
|
||||
home: function()
|
||||
{
|
||||
const homeViewUrl = $.createLink('doc', 'browseTemplate', `libID=0&filterType=all&docID=0&orderBy=&recPerPage=20&pageID=1&mode=home`);
|
||||
return {fetcher: homeViewUrl, clearBeforeLoad: false, className: 'doc-template-home h-full', class: 'h-full col',htmlRender: (element, props) => $(element).morphInner(`<div class="lazy-content doc-template-home h-full">${props.html}</div>`)};
|
||||
},
|
||||
|
||||
/**
|
||||
* 定义 API 文档列表工具栏渲染。
|
||||
* Define the API doc list toolbar render.
|
||||
*/
|
||||
toolbar: function()
|
||||
{
|
||||
if(this.mode === 'list')
|
||||
{
|
||||
const items = [];
|
||||
if(docAppHasPriv('create')) items.push({text: getDocAppLang('createTemplate'), icon: 'plus', btnType: 'primary', command: 'startCreateTemplate'});
|
||||
return {component: 'toolbar', props: {items: items}};
|
||||
}
|
||||
},
|
||||
'sidebar-footer-hint': function()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义文档模板各个视图和 UI 元素的上的操作方法。
|
||||
* Define the operation methods on the views and UI elements of the doc template.
|
||||
*/
|
||||
$.extend(window.docAppActions,
|
||||
{
|
||||
/**
|
||||
* 定义分组的操作按钮。
|
||||
* Define the actions on the type group.
|
||||
*/
|
||||
module: function(info)
|
||||
{
|
||||
const items = [];
|
||||
const module = info.data;
|
||||
const lang = getLang();
|
||||
|
||||
if(docAppHasPriv('addModule')) items.push({text: lang.actions.addSameModule, command: `addModule/${module.root}/${module.parent}`});
|
||||
if(module.grade == 1 && docAppHasPriv('editModule')) items.push({text: lang.actions.addSubModule, command: `addModule/${module.root}/${module.id}`});
|
||||
if(docAppHasPriv('editModule')) items.push({text: lang.actions.editModule, command: `editModule/${module.id}`});
|
||||
if(docAppHasPriv('deleteModule')) items.push({text: lang.actions.deleteModule, command: `deleteModule/${module.id}`});
|
||||
|
||||
if(info.ui === 'sidebar')
|
||||
{
|
||||
return [
|
||||
items.length ? {icon: 'ellipsis-v', caret: false, placement: 'bottom-end', size: 'xs', items: items} : null,
|
||||
];
|
||||
}
|
||||
|
||||
return items;
|
||||
},
|
||||
/**
|
||||
* 定义文档库的操作按钮。
|
||||
* Define the actions of modules.
|
||||
*/
|
||||
lib: function(info)
|
||||
{
|
||||
const lang = getLang();
|
||||
const items = [];
|
||||
const lib = info.data;
|
||||
const libID = lib?.data == undefined ? lib?.id : lib?.data.id;
|
||||
|
||||
/* 获取侧边栏没有模块时的操作按钮。 Get actions when sidebar no module. */
|
||||
if(info.ui === 'sidebar-no-module')
|
||||
{
|
||||
if(!docAppHasPriv('addModule')) return;
|
||||
return [{text: lang.actions.addModule, command: `addModule/${libID}/0/${libID}/child`, icon: 'plus', type: 'primary-pale'}];
|
||||
}
|
||||
|
||||
if(docAppHasPriv('addModule')) items.push({text: lang.actions.addModule, command: `addModule/${libID}/0/${libID}/child`});
|
||||
if(!items.length) return;
|
||||
|
||||
return [{type: 'dropdown', icon: 'cog-outline', square: true, caret: false, placement: 'top-end', items: items}];
|
||||
},
|
||||
/**
|
||||
* 定义文档编辑时的操作按钮。
|
||||
* Define the actions on toolbar of the doc editing page.
|
||||
*/
|
||||
'doc-edit': function(info)
|
||||
{
|
||||
const doc = info.data;
|
||||
if(!doc) return;
|
||||
|
||||
const lang = getLang();
|
||||
const isToolbar = info.ui === 'toolbar';
|
||||
const docApp = this;
|
||||
return [
|
||||
isToolbar ? {hint: docApp.fullscreen ? lang.exitFullscreen : lang.enterFullscreen, icon: docApp.fullscreen ? 'fullscreen-exit' : 'fullscreen', command: 'toggleFullscreen'} : null,
|
||||
(isToolbar && docApp.props.showDocHistory !== false) ? {hint: lang.history, icon: 'history', command: 'toggleViewSideTab/history'} : null,
|
||||
{text: lang.saveDraft, size: 'md', className: 'btn-wide', type: 'secondary', command: 'saveDoc/draft'},
|
||||
{text: lang.release, size: 'md', className: 'btn-wide', type: 'primary', command: 'saveDoc'},
|
||||
{text: lang.cancel, size: 'md', className: 'btn-wide', type: 'primary-outline', command: 'cancelEditDoc'},
|
||||
{text: lang.settings, size: 'md', type: 'ghost', command: `showDocSettingModal/${doc.id}/template/1`, icon: 'cog-outline'},
|
||||
];
|
||||
},
|
||||
/**
|
||||
* 定义模板列表的操作按钮。
|
||||
* Define the actions on the template list.
|
||||
*/
|
||||
'doc-list': function(info)
|
||||
{
|
||||
const lang = getLang();
|
||||
const canCreateDoc = hasPriv('create');
|
||||
|
||||
/* 文档列表没有文档时的按钮。Actions for empty doc list. */
|
||||
if(info.ui === 'doc-list-empty')
|
||||
{
|
||||
return canCreateDoc ? [{icon: 'plus', text: lang.createTemplate, btnType: 'primary', command: 'startCreateTemplate'}] : null;
|
||||
}
|
||||
|
||||
const items = [];
|
||||
if(canCreateDoc) items.push({text: lang.createTemplate, icon: 'plus', btnType: 'primary', command: 'startCreateTemplate'});
|
||||
return items.length ? {component: 'toolbar', props: {items: items}} : null;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 重写文档应用的配置选项方法。
|
||||
* Override the method to set the doc app options.
|
||||
*/
|
||||
window._setDocAppOptions = window.setDocAppOptions; // Save the original method.
|
||||
window.setDocAppOptions = function(_, options) // Override the method.
|
||||
{
|
||||
options = window._setDocAppOptions(_, options);
|
||||
return $.extend(options,
|
||||
{
|
||||
onCreateDoc : handleCreateDoc,
|
||||
onSaveDoc : handleSaveDoc,
|
||||
getTableOptions : getTableOptions,
|
||||
customRenders : $.extend(docAppCustomRenders, customRenders)
|
||||
});
|
||||
};
|
||||
|
||||
/* 扩展文档模板命令定义。 Extend the doc app command definition. */
|
||||
$.extend(window.docAppCommands,
|
||||
{
|
||||
startCreateTemplate: function(_, args)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
const hasModules = docApp.props.hasModules;
|
||||
if(!hasModules) return zui.Modal.alert(getLang('createTypeFirst'));
|
||||
|
||||
const {spaceID, libID, moduleID} = docApp;
|
||||
return showDocBasicModal(args?.[0] ?? 0, 0, true, 'doc').then((formData) => {
|
||||
zui.Editor.loadModule().then(() => {
|
||||
const emptyDoc = zui.Editor.createEmptyDoc();
|
||||
const snapshot = zui.Editor.toSnapshot(emptyDoc);
|
||||
const doc = {contentType: 'doc', status: 'draft', content: JSON.stringify(snapshot)};
|
||||
return submitNewDoc(doc, 0, libID, moduleID, formData, (newDoc) => {
|
||||
docApp.selectDoc(newDoc.id);
|
||||
docApp.startEditDoc(newDoc.id);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
addChapter: function(_, args)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
const {spaceID, libID, moduleID} = docApp;
|
||||
return showDocBasicModal(args[0], 0, false, 'chapter').then((formData) => {
|
||||
const doc = {type: 'chapter', status: 'normal', parent: args[0]};
|
||||
return submitNewDoc(doc, spaceID, libID, moduleID, formData).then(() => {
|
||||
docApp.load(null, null, null, {noLoading: false, picks: 'doc'});
|
||||
if(docBasicModal.current)
|
||||
{
|
||||
docBasicModal.current.destroy();
|
||||
docBasicModal = {};
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
editChapter: function(_, args)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
return showDocBasicModal(docApp.doc.data.parent, args[0], false, 'chapter').then((formData) => {
|
||||
return submitEditDoc(formData);
|
||||
});
|
||||
},
|
||||
deleteDoc: function(_, args)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
const docID = args[0] || docApp.docID;
|
||||
const docInfo = docApp.treeMap.docs.get(docID)
|
||||
const doc = docInfo.data;
|
||||
const isChapter = doc?.type === 'chapter';
|
||||
|
||||
$.ajaxSubmit(
|
||||
{
|
||||
confirm: getLang(isChapter ? (docInfo.docs.length > 0 ? 'confirmDeleteChapterWithSub' : 'confirmDeleteChapter') : (docInfo.docs.length > 0 ? 'confirmDeleteWithSub' : 'confirmDelete')),
|
||||
url: $.createLink('doc', 'deleteTemplate', `docID=${docID}`),
|
||||
load: false,
|
||||
onSuccess: function()
|
||||
{
|
||||
getDocApp().delete('doc', docID);
|
||||
}
|
||||
});
|
||||
},
|
||||
moveDoc: function(_, args)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
const docID = args[0] || docApp.docID;
|
||||
const url = $.createLink('doc', 'moveTemplate', `docID=${docID}`);
|
||||
zui.Modal.open({size: 'sm', url: url});
|
||||
},
|
||||
addModule: function(_, args)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
const scope = args[0];
|
||||
const parentModule = args[1];
|
||||
const url = $.createLink('doc', 'addTemplateType', `scope=${scope}&parentModule=${parentModule}`);
|
||||
zui.Modal.open({size: 'sm', url: url});
|
||||
},
|
||||
editModule: function(_, args)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
const moduleID = args[0] || docApp.moduleID;
|
||||
const url = $.createLink('doc', 'editTemplateType', `moduleID=${moduleID}`);
|
||||
zui.Modal.open({size: 'sm', url: url});
|
||||
},
|
||||
deleteModule: function(_, args)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
const moduleID = args[0] || docApp.moduleID;
|
||||
$.ajaxSubmit(
|
||||
{
|
||||
url: $.createLink('doc', 'deleteTemplateType', `moduleID=${moduleID}`),
|
||||
load: false,
|
||||
onSuccess: function()
|
||||
{
|
||||
getDocApp().delete('module', moduleID);
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 编辑文档模板。
|
||||
* Edit doc template.
|
||||
*/
|
||||
editTemplate: function(_, args)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
const templateID = args[0] || docApp.docID;
|
||||
const url = $.createLink('doc', 'editTemplate', `templateID=${templateID}`);
|
||||
zui.Modal.open({size: 'sm', url: url});
|
||||
},
|
||||
/**
|
||||
* 删除文档模板。
|
||||
* Delete doc template.
|
||||
*/
|
||||
deleteTemplate: function(_, args)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
const lang = getDocAppLang();
|
||||
const templateID = args[0] || docApp.docID;
|
||||
$.ajaxSubmit(
|
||||
{
|
||||
confirm: lang.confirmDelete,
|
||||
url: $.createLink('doc', 'deleteTemplate', `templateID=${templateID}`),
|
||||
load:false,
|
||||
onSunccess: function()
|
||||
{
|
||||
getDocApp().delete('doc', templateID);
|
||||
}
|
||||
})
|
||||
},
|
||||
showDocSettingModal: showDocSettingModal
|
||||
});
|
||||
|
||||
window.clickTemplateCard = function(event, url)
|
||||
{
|
||||
const target = $(event.target);
|
||||
if(target.hasClass('icon') || target.hasClass('dropdown') || target.hasClass('toolbar')) return;
|
||||
|
||||
openUrl(url);
|
||||
}
|
||||
@@ -224,19 +224,43 @@ window.loadLibModules = function(e, docID)
|
||||
const libType = $(e.target.closest('div.form-group')).attr('data-lib-type');
|
||||
const objectID = $("input[name='" + libType + "']").val();
|
||||
|
||||
let docType = $('.radio-primary [name=type]:not(.hidden):checked').val();
|
||||
if(typeof docType == 'undefined') docType = 'doc';
|
||||
if(!docType)
|
||||
{
|
||||
docType = $('.radio-primary [name=type]:not(.hidden):checked').val();
|
||||
if(typeof docType == 'undefined') docType = 'doc';
|
||||
}
|
||||
|
||||
const link = $.createLink('doc', 'ajaxGetModules', 'objectType=' + libType + '&objectID=' + objectID + '&type=' + docType + '&docID=' + docID + '&libID=' + libID);
|
||||
$.get(link, function(data)
|
||||
{
|
||||
data = JSON.parse(data);
|
||||
if(docType == 'docTemplate')
|
||||
{
|
||||
data = data.filter(function(item)
|
||||
{
|
||||
return item.value != 0;
|
||||
});
|
||||
}
|
||||
|
||||
const $modulePicker = $("[name='parent']").zui('picker');
|
||||
$modulePicker.render({items: data.modules});
|
||||
$modulePicker.$.setValue('');
|
||||
});
|
||||
}
|
||||
|
||||
window.loadScopeTypes = function(e)
|
||||
{
|
||||
const libID = e.target.value;
|
||||
const link = $.createLink('doc', 'ajaxGetScopeTypes', 'libID=' + libID);
|
||||
$.get(link, function(data)
|
||||
{
|
||||
data = JSON.parse(data);
|
||||
const $modulePicker = $("[name='module']").zui('picker');
|
||||
$modulePicker.render({items: data});
|
||||
$modulePicker.$.setValue('');
|
||||
});
|
||||
}
|
||||
|
||||
window.toggleWhiteList = function(e)
|
||||
{
|
||||
const acl = e.target.value;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
window.handleClickBatchFormAction = function(action, $row, rowIndex)
|
||||
{
|
||||
if(action == 'delete')
|
||||
{
|
||||
let deleteID = $row.find('td[data-name="id"] input[name^=id]').val();
|
||||
if(deleteID)
|
||||
{
|
||||
deleteID = deleteID.replace('id', '');
|
||||
let link = $.createLink('doc', 'ajaxJudgeCanBeDeleted', 'scopeID=' + deleteID);
|
||||
$.getJSON(link, function(data)
|
||||
{
|
||||
if(data && data.result == 'fail')
|
||||
{
|
||||
zui.Modal.alert(data.message);
|
||||
}
|
||||
else
|
||||
{
|
||||
const $batchForm = $('[data-zui-batchform]').zui('batchForm');
|
||||
$batchForm.deleteRow(rowIndex);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.handleRenderRow = function($row, index, data)
|
||||
{
|
||||
if(data && data.main == '1') $row.find('[data-name="ACTIONS"]').find('[data-type="delete"]').addClass('hidden');
|
||||
}
|
||||
@@ -217,7 +217,6 @@ window.renderCell = function(result, info)
|
||||
if(!info.row.data.build.name) return result;
|
||||
|
||||
result.push({html: info.row.data.build.name});
|
||||
return result;
|
||||
}
|
||||
|
||||
if(info.col.name == 'project')
|
||||
@@ -226,9 +225,61 @@ window.renderCell = function(result, info)
|
||||
if(!info.row.data.projectName) return result;
|
||||
|
||||
result.push({html: `<span title='${info.row.data.projectName}'>${info.row.data.projectName}</span>`});
|
||||
}
|
||||
}
|
||||
|
||||
if(blockType == 'projectRelease')
|
||||
{
|
||||
if(info.col.name == 'name')
|
||||
{
|
||||
if(info.row.data.marker == 1)
|
||||
{
|
||||
result[result.length] = {html: "<icon class='icon icon-flag text-danger' title='" + markerTitle + "'></icon>"};
|
||||
}
|
||||
}
|
||||
|
||||
if(info.col.name == 'build')
|
||||
{
|
||||
if(!info.row.data.buildInfos) info.row.data.buildInfos = info.row.data.builds;
|
||||
|
||||
let result = [];
|
||||
for(key in info.row.data.buildInfos) result.push({html: info.row.data.buildInfos[key].name})
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if(blockType == 'productCase')
|
||||
{
|
||||
if(result)
|
||||
{
|
||||
if(info.col.name == 'caseID' && info.row.data.isScene) result.shift(); // 移除场景ID
|
||||
|
||||
if(info.col.name == 'title')
|
||||
{
|
||||
const data = info.row.data;
|
||||
if(data.color) result[0].props.style = 'color: ' + data.color;
|
||||
if(data.isScene) // 场景
|
||||
{
|
||||
result.shift(); // 移除带链接的场景名称
|
||||
result.push({html: data.title}); // 添加不带链接的场景名称
|
||||
result.unshift({html: '<span class="label gray-300-outline text-gray rounded-full nowrap">' + scene + '</span>'}); // 添加场景标签
|
||||
}
|
||||
else // 用例
|
||||
{
|
||||
if(data.auto == 'auto') result.unshift({html: '<span class="label gray-pale rounded-full nowrap">' + automated + '</span>'}); // 添加自动化标签
|
||||
if(info.row.data.fromCaseID > 0) result.push({html: `[<i class='icon icon-share'></i> #${info.row.data.fromCaseID}]`}); // 添加来源用例
|
||||
}
|
||||
}
|
||||
|
||||
if(info.col.name == 'pri' && info.row.data.isScene) result.shift(); // 移除场景优先级
|
||||
|
||||
if(info.col.name == 'status' && info.row.data.status == 'casechanged') result[0] = {html: '<span style="color:#ff6f42">' + caseChanged + '</span>'};
|
||||
}
|
||||
|
||||
if(info.row.data.lastEditedDate == '0000-00-00 00:00:00') info.row.data.lastEditedDate = '';
|
||||
if(info.row.data.reviewedDate == '0000-00-00') info.row.data.reviewedDate = '';
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
+116
-3
@@ -73,6 +73,74 @@ $lang->doclib->apiNameUnique['product'] = 'In the api library of the same ' . $l
|
||||
$lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $lang->projectCommon . ', ';
|
||||
$lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, ';
|
||||
|
||||
$lang->docTemplate = new stdclass();
|
||||
$lang->docTemplate->id = 'ID';
|
||||
$lang->docTemplate->title = 'Template Title';
|
||||
$lang->docTemplate->frequency = 'Frequency';
|
||||
$lang->docTemplate->type = 'Category';
|
||||
$lang->docTemplate->addedBy = 'Added By';
|
||||
$lang->docTemplate->addedDate = 'Added Date';
|
||||
$lang->docTemplate->editedBy = 'Edited By';
|
||||
$lang->docTemplate->editedDate = 'Edited Date';
|
||||
$lang->docTemplate->views = 'Views';
|
||||
$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?';
|
||||
$lang->docTemplate->scope = 'Scope';
|
||||
$lang->docTemplate->lib = $lang->docTemplate->scope;
|
||||
$lang->docTemplate->module = 'Category';
|
||||
$lang->docTemplate->desc = 'Describe';
|
||||
$lang->docTemplate->parentModule = 'Parent';
|
||||
$lang->docTemplate->typeName = 'Category Name';
|
||||
$lang->docTemplate->parent = 'Level';
|
||||
$lang->docTemplate->addTemplateType = 'Add template category';
|
||||
$lang->docTemplate->editTemplateType = 'Edit template category';
|
||||
$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title';
|
||||
$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.';
|
||||
$lang->docTemplate->errorDeleteType = 'There is document template exists in the current category, it cannot be deleted.';
|
||||
$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? After saving as a draft or publishing, you can no longer switch back to the old editor.';
|
||||
$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.';
|
||||
$lang->docTemplate->leaveEditingConfirm = 'The template is currently being edited. Do you want to leave the editing page?';
|
||||
$lang->docTemplate->searchScopePlaceholder = 'Search Scope';
|
||||
$lang->docTemplate->searchTypePlaceholder = 'Search Category';
|
||||
$lang->docTemplate->moveDocTemplate = 'Move Template';
|
||||
$lang->docTemplate->moveSubTemplate = 'Move Sub Template';
|
||||
$lang->docTemplate->createTypeFirst = 'Please create a template category first.';
|
||||
$lang->docTemplate->editedList = 'Template editor';
|
||||
$lang->docTemplate->content = 'Template Text';
|
||||
$lang->docTemplate->templateDesc = 'Template Desc';
|
||||
$lang->docTemplate->status = 'Template Status';
|
||||
$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.';
|
||||
$lang->docTemplate->previewTip = 'After configuring the parameters, this block will display the corresponding list data according to the filter configuration.';
|
||||
$lang->docTemplate->confirmDeleteChapterWithSub = "After deleting a chapter, the lower level content of the chapter will be hidden. Are you sure you want to delete the chapter?";
|
||||
$lang->docTemplate->confirmDeleteTemplateWithSub = "After deleting the template, the lower level content of the template will be hidden. Are you sure you want to delete this template?";
|
||||
$lang->docTemplate->scopeHasTemplateTips = 'There are templates within this scope. Please remove them before deleting the scope.';
|
||||
$lang->docTemplate->scopeHasModuleTips = 'There are template category data within this scope. Please remove them before deleting the scope.';
|
||||
$lang->docTemplate->needEditable = 'This template is not editable.';
|
||||
|
||||
$lang->docTemplate->create = 'Create Template';
|
||||
$lang->docTemplate->edit = 'Edit Template';
|
||||
$lang->docTemplate->delete = 'Delete Template';
|
||||
|
||||
$lang->docTemplate->more = 'More';
|
||||
$lang->docTemplate->scopeLabel = 'Scope';
|
||||
$lang->docTemplate->noTemplate = 'No Doc Template';
|
||||
$lang->docTemplate->noDesc = 'No Desc';
|
||||
$lang->docTemplate->of = ' of ';
|
||||
$lang->docTemplate->overdue = 'Overdue';
|
||||
|
||||
$lang->docTemplate->addModule = 'Add Template Category';
|
||||
$lang->docTemplate->addSameModule = 'Add Same Template Category';
|
||||
$lang->docTemplate->addSubModule = 'Add Sub Template Category';
|
||||
$lang->docTemplate->editModule = 'Edit Template Category';
|
||||
$lang->docTemplate->deleteModule = 'Delete Template Category';
|
||||
$lang->docTemplate->noModules = 'No Categories';
|
||||
$lang->docTemplate->addSubDocTemplate = 'Add sub template';
|
||||
|
||||
$lang->docTemplate->filterTypes = array();
|
||||
$lang->docTemplate->filterTypes[] = array('all', 'All');
|
||||
$lang->docTemplate->filterTypes[] = array('draft', 'Draft');
|
||||
$lang->docTemplate->filterTypes[] = array('released', 'Released');
|
||||
$lang->docTemplate->filterTypes[] = array('createdByMe', 'Created By Me');
|
||||
|
||||
/* Fields. */
|
||||
$lang->doc->common = 'Dok';
|
||||
$lang->doc->id = 'ID';
|
||||
@@ -137,6 +205,7 @@ $lang->doc->update = 'Update';
|
||||
$lang->doc->nextStep = 'Next';
|
||||
$lang->doc->closed = 'Closed';
|
||||
$lang->doc->saveDraft = 'Save Draft';
|
||||
$lang->doc->template = 'Template';
|
||||
$lang->doc->position = 'Position';
|
||||
$lang->doc->person = 'Person';
|
||||
$lang->doc->team = 'Team';
|
||||
@@ -276,7 +345,7 @@ $lang->doc->deleteChapter = 'Delete chapter';
|
||||
$lang->doc->addSubChapter = 'Add sub chapter';
|
||||
$lang->doc->addSameChapter = 'Add same chapter';
|
||||
$lang->doc->addSubDoc = 'Add sub document';
|
||||
$lang->doc->chapterName = 'Chapter name';
|
||||
$lang->doc->chapterName = 'Name';
|
||||
|
||||
$lang->doc->tips = new stdclass();
|
||||
$lang->doc->tips->noProduct = 'No product, please create first';
|
||||
@@ -293,6 +362,7 @@ $lang->doc->zentaoList['planStory'] = $lang->productplan->shortCommon . $la
|
||||
|
||||
$lang->doc->zentaoList['case'] = $lang->testcase->common;
|
||||
$lang->doc->zentaoList['productCase'] = $lang->productCommon . $lang->testcase->common;
|
||||
$lang->doc->zentaoList['projectCase'] = $lang->projectCommon . $lang->testcase->common;
|
||||
$lang->doc->zentaoList['caselib'] = 'Case Library' . $lang->testcase->common;
|
||||
|
||||
$lang->doc->zentaoList['task'] = $lang->task->common;
|
||||
@@ -304,14 +374,17 @@ $lang->doc->zentaoList['more'] = 'More';
|
||||
$lang->doc->zentaoList['productPlan'] = $lang->productCommon . ' Plan';
|
||||
$lang->doc->zentaoList['productPlanContent'] = $lang->productCommon . ' Plan Content';
|
||||
$lang->doc->zentaoList['productRelease'] = $lang->productCommon . $lang->release->common;
|
||||
$lang->doc->zentaoList['projectRelease'] = $lang->projectCommon . $lang->release->common;
|
||||
$lang->doc->zentaoList['ER'] = $lang->defaultERName;
|
||||
$lang->doc->zentaoList['UR'] = $lang->URCommon;
|
||||
$lang->doc->zentaoList['feedback'] = 'Feedback';
|
||||
$lang->doc->zentaoList['ticket'] = 'Ticket';
|
||||
$lang->doc->zentaoList['gantt'] = 'Gantt Chart';
|
||||
|
||||
$lang->doc->zentaoAction = array();
|
||||
$lang->doc->zentaoAction['set'] = 'Setting';
|
||||
$lang->doc->zentaoAction['delete'] = 'Delete';
|
||||
$lang->doc->zentaoAction['set'] = 'Setting';
|
||||
$lang->doc->zentaoAction['delete'] = 'Delete';
|
||||
$lang->doc->zentaoAction['setParams'] = 'Set Parameters';
|
||||
|
||||
$lang->doc->uploadFormatList = array();
|
||||
$lang->doc->uploadFormatList['separateDocs'] = 'Save files as different document';
|
||||
@@ -348,6 +421,9 @@ $lang->doc->statusList['draft'] = "Draft";
|
||||
$lang->doc->aclList['open'] = "Public (Access with library permissions)";
|
||||
$lang->doc->aclList['private'] = "Private (Only creators and whitelist users can access)";
|
||||
|
||||
$lang->doc->aclListA['open'] = "Public (Everyone can access it, with permission to edit document templates for access and maintenance.)";
|
||||
$lang->doc->aclListA['private'] = "Private (Only creators can edit and use it)";
|
||||
|
||||
$lang->doc->selectSpace = 'Select Space';
|
||||
$lang->doc->space = 'Space';
|
||||
$lang->doc->spaceList['mine'] = 'My Space';
|
||||
@@ -454,6 +530,7 @@ $lang->doc->docConvertComment = "This document has been converted to t
|
||||
$lang->doc->previewNotAvailable = 'Preview function is not available. Please visit the Kanban board to view the document %s.';
|
||||
$lang->doc->hocuspocusConnect = 'The collaborative editing service is connected.';
|
||||
$lang->doc->hocuspocusDisconnect = 'The collaborative editing service is disconnected. Edits will be synchronized after reconnection.';
|
||||
$lang->doc->docTemplateConvertComment = 'The template has been converted to the new editor format. Switch to version %s to view the template before conversion.';
|
||||
|
||||
$lang->doc->noticeAcl['lib']['product']['default'] = "Users who can access the selected {$lang->productCommon} can access it.";
|
||||
$lang->doc->noticeAcl['lib']['product']['custom'] = "Users who can access the selected {$lang->productCommon} or users in the whiltelist can access it.";
|
||||
@@ -523,6 +600,18 @@ $lang->doc->projectFilterTypes[] = array('mine', 'Involved');
|
||||
|
||||
$lang->doc->spaceFilterTypes[] = array('all', 'All');
|
||||
|
||||
$lang->doc->manageScope = 'Manage Scope';
|
||||
$lang->doc->browseTemplate = 'Template Square';
|
||||
$lang->doc->createTemplate = 'Create Document Template';
|
||||
$lang->doc->editTemplate = 'Edit Document Template';
|
||||
$lang->doc->moveTemplate = 'Move Document Template';
|
||||
$lang->doc->deleteTemplate = 'Delete Document Template';
|
||||
$lang->doc->viewTemplate = 'View Document Template';
|
||||
$lang->doc->addTemplateType = 'Create Category';
|
||||
$lang->doc->editTemplateType = 'Edit Category';
|
||||
$lang->doc->deleteTemplateType = 'Delete Category';
|
||||
$lang->doc->sortTemplate = 'Sort';
|
||||
|
||||
$lang->doc->docLang = new stdClass();
|
||||
$lang->doc->docLang->cancel = $lang->cancel;
|
||||
$lang->doc->docLang->export = $lang->export;
|
||||
@@ -566,6 +655,7 @@ $lang->doc->docLang->moveTo = $lang->doc->moveTo;
|
||||
$lang->doc->docLang->moveLib = $lang->doc->moveLibAction;
|
||||
$lang->doc->docLang->moduleName = $lang->doc->catalogName;
|
||||
$lang->doc->docLang->saveDraft = $lang->doc->saveDraft;
|
||||
$lang->doc->docLang->template = $lang->doc->template;
|
||||
$lang->doc->docLang->release = $lang->doc->release;
|
||||
$lang->doc->docLang->batchMove = $lang->doc->batchMove;
|
||||
$lang->doc->docLang->filterTypes = $lang->doc->filterTypes;
|
||||
@@ -689,3 +779,26 @@ $lang->doc->docLang->editing = 'Editing';
|
||||
$lang->doc->docLang->restoreVersionHint = 'Restore to version';
|
||||
$lang->doc->docLang->restoreVersion = 'Restore';
|
||||
$lang->doc->docLang->restoreVersionConfirm = 'This will create a new version using the content of version {version}. Are you sure you want to continue?';
|
||||
|
||||
$lang->docTemplate->types = array();
|
||||
$lang->docTemplate->types['plan'] = 'Plan';
|
||||
$lang->docTemplate->types['story'] = 'Story';
|
||||
$lang->docTemplate->types['design'] = 'Design';
|
||||
$lang->docTemplate->types['dev'] = 'Development';
|
||||
$lang->docTemplate->types['test'] = 'Test';
|
||||
$lang->docTemplate->types['desc'] = 'Description';
|
||||
$lang->docTemplate->types['other'] = 'Other';
|
||||
|
||||
$lang->docTemplate->builtInScopes = array();
|
||||
$lang->docTemplate->builtInScopes['rnd'] = array();
|
||||
$lang->docTemplate->builtInScopes['or'] = array();
|
||||
$lang->docTemplate->builtInScopes['lite'] = array();
|
||||
$lang->docTemplate->builtInScopes['rnd']['product'] = 'Product';
|
||||
$lang->docTemplate->builtInScopes['rnd']['project'] = 'Project';
|
||||
$lang->docTemplate->builtInScopes['rnd']['execution'] = 'Execution';
|
||||
$lang->docTemplate->builtInScopes['rnd']['personal'] = 'Personal';
|
||||
$lang->docTemplate->builtInScopes['or']['market'] = 'Market';
|
||||
$lang->docTemplate->builtInScopes['or']['product'] = 'Product';
|
||||
$lang->docTemplate->builtInScopes['or']['personal'] = 'Personal';
|
||||
$lang->docTemplate->builtInScopes['lite']['project'] = 'Project';
|
||||
$lang->docTemplate->builtInScopes['lite']['personal'] = 'Personal';
|
||||
|
||||
+116
-3
@@ -73,6 +73,74 @@ $lang->doclib->apiNameUnique['product'] = 'In the api library of the same ' . $l
|
||||
$lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $lang->projectCommon . ', ';
|
||||
$lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, ';
|
||||
|
||||
$lang->docTemplate = new stdclass();
|
||||
$lang->docTemplate->id = 'ID';
|
||||
$lang->docTemplate->title = 'Template Title';
|
||||
$lang->docTemplate->frequency = 'Frequency';
|
||||
$lang->docTemplate->type = 'Category';
|
||||
$lang->docTemplate->addedBy = 'Added By';
|
||||
$lang->docTemplate->addedDate = 'Added Date';
|
||||
$lang->docTemplate->editedBy = 'Edited By';
|
||||
$lang->docTemplate->editedDate = 'Edited Date';
|
||||
$lang->docTemplate->views = 'Views';
|
||||
$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?';
|
||||
$lang->docTemplate->scope = 'Scope';
|
||||
$lang->docTemplate->lib = $lang->docTemplate->scope;
|
||||
$lang->docTemplate->module = 'Category';
|
||||
$lang->docTemplate->desc = 'Describe';
|
||||
$lang->docTemplate->parentModule = 'Parent';
|
||||
$lang->docTemplate->typeName = 'Category Name';
|
||||
$lang->docTemplate->parent = 'Level';
|
||||
$lang->docTemplate->addTemplateType = 'Add template category';
|
||||
$lang->docTemplate->editTemplateType = 'Edit template category';
|
||||
$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title';
|
||||
$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.';
|
||||
$lang->docTemplate->errorDeleteType = 'There is document template exists in the current category, it cannot be deleted.';
|
||||
$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? After saving as a draft or publishing, you can no longer switch back to the old editor.';
|
||||
$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.';
|
||||
$lang->docTemplate->leaveEditingConfirm = 'The template is currently being edited. Do you want to leave the editing page?';
|
||||
$lang->docTemplate->searchScopePlaceholder = 'Search Scope';
|
||||
$lang->docTemplate->searchTypePlaceholder = 'Search Category';
|
||||
$lang->docTemplate->moveDocTemplate = 'Move Template';
|
||||
$lang->docTemplate->moveSubTemplate = 'Move Sub Template';
|
||||
$lang->docTemplate->createTypeFirst = 'Please create a template category first.';
|
||||
$lang->docTemplate->editedList = 'Template editor';
|
||||
$lang->docTemplate->content = 'Template Text';
|
||||
$lang->docTemplate->templateDesc = 'Template Desc';
|
||||
$lang->docTemplate->status = 'Template Status';
|
||||
$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.';
|
||||
$lang->docTemplate->previewTip = 'After configuring the parameters, this block will display the corresponding list data according to the filter configuration.';
|
||||
$lang->docTemplate->confirmDeleteChapterWithSub = "After deleting a chapter, the lower level content of the chapter will be hidden. Are you sure you want to delete the chapter?";
|
||||
$lang->docTemplate->confirmDeleteTemplateWithSub = "After deleting the template, the lower level content of the template will be hidden. Are you sure you want to delete this template?";
|
||||
$lang->docTemplate->scopeHasTemplateTips = 'There are templates within this scope. Please remove them before deleting the scope.';
|
||||
$lang->docTemplate->scopeHasModuleTips = 'There are template category data within this scope. Please remove them before deleting the scope.';
|
||||
$lang->docTemplate->needEditable = 'This template is not editable.';
|
||||
|
||||
$lang->docTemplate->create = 'Create Template';
|
||||
$lang->docTemplate->edit = 'Edit Template';
|
||||
$lang->docTemplate->delete = 'Delete Template';
|
||||
|
||||
$lang->docTemplate->more = 'More';
|
||||
$lang->docTemplate->scopeLabel = 'Scope';
|
||||
$lang->docTemplate->noTemplate = 'No Doc Template';
|
||||
$lang->docTemplate->noDesc = 'No Desc';
|
||||
$lang->docTemplate->of = ' of ';
|
||||
$lang->docTemplate->overdue = 'Overdue';
|
||||
|
||||
$lang->docTemplate->addModule = 'Add Template Category';
|
||||
$lang->docTemplate->addSameModule = 'Add Same Template Category';
|
||||
$lang->docTemplate->addSubModule = 'Add Sub Template Category';
|
||||
$lang->docTemplate->editModule = 'Edit Template Category';
|
||||
$lang->docTemplate->deleteModule = 'Delete Template Category';
|
||||
$lang->docTemplate->noModules = 'No Categories';
|
||||
$lang->docTemplate->addSubDocTemplate = 'Add sub template';
|
||||
|
||||
$lang->docTemplate->filterTypes = array();
|
||||
$lang->docTemplate->filterTypes[] = array('all', 'All');
|
||||
$lang->docTemplate->filterTypes[] = array('draft', 'Draft');
|
||||
$lang->docTemplate->filterTypes[] = array('released', 'Released');
|
||||
$lang->docTemplate->filterTypes[] = array('createdByMe', 'Created By Me');
|
||||
|
||||
/* Fields. */
|
||||
$lang->doc->common = 'Document';
|
||||
$lang->doc->id = 'ID';
|
||||
@@ -137,6 +205,7 @@ $lang->doc->update = 'Update';
|
||||
$lang->doc->nextStep = 'Next';
|
||||
$lang->doc->closed = 'Closed';
|
||||
$lang->doc->saveDraft = 'Save Draft';
|
||||
$lang->doc->template = 'Template';
|
||||
$lang->doc->position = 'Position';
|
||||
$lang->doc->person = 'Person';
|
||||
$lang->doc->team = 'Team';
|
||||
@@ -276,7 +345,7 @@ $lang->doc->deleteChapter = 'Delete chapter';
|
||||
$lang->doc->addSubChapter = 'Add sub chapter';
|
||||
$lang->doc->addSameChapter = 'Add same chapter';
|
||||
$lang->doc->addSubDoc = 'Add sub document';
|
||||
$lang->doc->chapterName = 'Chapter name';
|
||||
$lang->doc->chapterName = 'Name';
|
||||
|
||||
$lang->doc->tips = new stdclass();
|
||||
$lang->doc->tips->noProduct = 'No product, please create first';
|
||||
@@ -293,6 +362,7 @@ $lang->doc->zentaoList['planStory'] = $lang->productplan->shortCommon . $la
|
||||
|
||||
$lang->doc->zentaoList['case'] = $lang->testcase->common;
|
||||
$lang->doc->zentaoList['productCase'] = $lang->productCommon . $lang->testcase->common;
|
||||
$lang->doc->zentaoList['projectCase'] = $lang->projectCommon . $lang->testcase->common;
|
||||
$lang->doc->zentaoList['caselib'] = 'Case Library' . $lang->testcase->common;
|
||||
|
||||
$lang->doc->zentaoList['task'] = $lang->task->common;
|
||||
@@ -304,14 +374,17 @@ $lang->doc->zentaoList['more'] = 'More';
|
||||
$lang->doc->zentaoList['productPlan'] = $lang->productCommon . ' Plan';
|
||||
$lang->doc->zentaoList['productPlanContent'] = $lang->productCommon . ' Plan Content';
|
||||
$lang->doc->zentaoList['productRelease'] = $lang->productCommon . $lang->release->common;
|
||||
$lang->doc->zentaoList['projectRelease'] = $lang->projectCommon . $lang->release->common;
|
||||
$lang->doc->zentaoList['ER'] = $lang->defaultERName;
|
||||
$lang->doc->zentaoList['UR'] = $lang->URCommon;
|
||||
$lang->doc->zentaoList['feedback'] = 'Feedback';
|
||||
$lang->doc->zentaoList['ticket'] = 'Ticket';
|
||||
$lang->doc->zentaoList['gantt'] = 'Gantt Chart';
|
||||
|
||||
$lang->doc->zentaoAction = array();
|
||||
$lang->doc->zentaoAction['set'] = 'Setting';
|
||||
$lang->doc->zentaoAction['delete'] = 'Delete';
|
||||
$lang->doc->zentaoAction['set'] = 'Setting';
|
||||
$lang->doc->zentaoAction['delete'] = 'Delete';
|
||||
$lang->doc->zentaoAction['setParams'] = 'Set Parameters';
|
||||
|
||||
$lang->doc->uploadFormatList = array();
|
||||
$lang->doc->uploadFormatList['separateDocs'] = 'Save files as different document';
|
||||
@@ -348,6 +421,9 @@ $lang->doc->statusList['draft'] = "Draft";
|
||||
$lang->doc->aclList['open'] = "Public (Access with library permissions)";
|
||||
$lang->doc->aclList['private'] = "Private (Only creators and whitelist users can access)";
|
||||
|
||||
$lang->doc->aclListA['open'] = "Public (Everyone can access it, with permission to edit document templates for access and maintenance)";
|
||||
$lang->doc->aclListA['private'] = "Private (Only creators can edit and use it)";
|
||||
|
||||
$lang->doc->selectSpace = 'Select Space';
|
||||
$lang->doc->space = 'Space';
|
||||
$lang->doc->spaceList['mine'] = 'My Space';
|
||||
@@ -454,6 +530,7 @@ $lang->doc->docConvertComment = "This document has been converted to t
|
||||
$lang->doc->previewNotAvailable = 'Preview function is not available. Please visit the Kanban board to view the document %s.';
|
||||
$lang->doc->hocuspocusConnect = 'The collaborative editing service is connected.';
|
||||
$lang->doc->hocuspocusDisconnect = 'The collaborative editing service is disconnected. Edits will be synchronized after reconnection.';
|
||||
$lang->doc->docTemplateConvertComment = 'The template has been converted to the new editor format. Switch to version %s to view the template before conversion.';
|
||||
|
||||
$lang->doc->noticeAcl['lib']['product']['default'] = "Users who can access the selected {$lang->productCommon} can access it.";
|
||||
$lang->doc->noticeAcl['lib']['product']['custom'] = "Users who can access the selected {$lang->productCommon} or users in the whiltelist can access it.";
|
||||
@@ -523,6 +600,18 @@ $lang->doc->projectFilterTypes[] = array('mine', 'Involved');
|
||||
|
||||
$lang->doc->spaceFilterTypes[] = array('all', 'All');
|
||||
|
||||
$lang->doc->manageScope = 'Manage Scope';
|
||||
$lang->doc->browseTemplate = 'Template Square';
|
||||
$lang->doc->createTemplate = 'Create Document Template';
|
||||
$lang->doc->editTemplate = 'Edit Document Template';
|
||||
$lang->doc->moveTemplate = 'Move Document Template';
|
||||
$lang->doc->deleteTemplate = 'Delete Document Template';
|
||||
$lang->doc->viewTemplate = 'View Document Template';
|
||||
$lang->doc->addTemplateType = 'Create Category';
|
||||
$lang->doc->editTemplateType = 'Edit Category';
|
||||
$lang->doc->deleteTemplateType = 'Delete Category';
|
||||
$lang->doc->sortTemplate = 'Sort';
|
||||
|
||||
$lang->doc->docLang = new stdClass();
|
||||
$lang->doc->docLang->cancel = $lang->cancel;
|
||||
$lang->doc->docLang->export = $lang->export;
|
||||
@@ -566,6 +655,7 @@ $lang->doc->docLang->moveTo = $lang->doc->moveTo;
|
||||
$lang->doc->docLang->moveLib = $lang->doc->moveLibAction;
|
||||
$lang->doc->docLang->moduleName = $lang->doc->catalogName;
|
||||
$lang->doc->docLang->saveDraft = $lang->doc->saveDraft;
|
||||
$lang->doc->docLang->template = $lang->doc->template;
|
||||
$lang->doc->docLang->release = $lang->doc->release;
|
||||
$lang->doc->docLang->batchMove = $lang->doc->batchMove;
|
||||
$lang->doc->docLang->filterTypes = $lang->doc->filterTypes;
|
||||
@@ -689,3 +779,26 @@ $lang->doc->docLang->editing = 'Editing';
|
||||
$lang->doc->docLang->restoreVersionHint = 'Restore to version';
|
||||
$lang->doc->docLang->restoreVersion = 'Restore';
|
||||
$lang->doc->docLang->restoreVersionConfirm = 'This will create a new version using the content of version {version}. Are you sure you want to continue?';
|
||||
|
||||
$lang->docTemplate->types = array();
|
||||
$lang->docTemplate->types['plan'] = 'Plan';
|
||||
$lang->docTemplate->types['story'] = 'Story';
|
||||
$lang->docTemplate->types['design'] = 'Design';
|
||||
$lang->docTemplate->types['dev'] = 'Development';
|
||||
$lang->docTemplate->types['test'] = 'Test';
|
||||
$lang->docTemplate->types['desc'] = 'Description';
|
||||
$lang->docTemplate->types['other'] = 'Other';
|
||||
|
||||
$lang->docTemplate->builtInScopes = array();
|
||||
$lang->docTemplate->builtInScopes['rnd'] = array();
|
||||
$lang->docTemplate->builtInScopes['or'] = array();
|
||||
$lang->docTemplate->builtInScopes['lite'] = array();
|
||||
$lang->docTemplate->builtInScopes['rnd']['product'] = 'Product';
|
||||
$lang->docTemplate->builtInScopes['rnd']['project'] = 'Project';
|
||||
$lang->docTemplate->builtInScopes['rnd']['execution'] = 'Execution';
|
||||
$lang->docTemplate->builtInScopes['rnd']['personal'] = 'Personal';
|
||||
$lang->docTemplate->builtInScopes['or']['market'] = 'Market';
|
||||
$lang->docTemplate->builtInScopes['or']['product'] = 'Product';
|
||||
$lang->docTemplate->builtInScopes['or']['personal'] = 'Personal';
|
||||
$lang->docTemplate->builtInScopes['lite']['project'] = 'Project';
|
||||
$lang->docTemplate->builtInScopes['lite']['personal'] = 'Personal';
|
||||
|
||||
+116
-3
@@ -73,6 +73,74 @@ $lang->doclib->apiNameUnique['product'] = 'In the api library of the same ' . $l
|
||||
$lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $lang->projectCommon . ', ';
|
||||
$lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, ';
|
||||
|
||||
$lang->docTemplate = new stdclass();
|
||||
$lang->docTemplate->id = 'ID';
|
||||
$lang->docTemplate->title = 'Template Title';
|
||||
$lang->docTemplate->frequency = 'Frequency';
|
||||
$lang->docTemplate->type = 'Category';
|
||||
$lang->docTemplate->addedBy = 'Added By';
|
||||
$lang->docTemplate->addedDate = 'Added Date';
|
||||
$lang->docTemplate->editedBy = 'Edited By';
|
||||
$lang->docTemplate->editedDate = 'Edited Date';
|
||||
$lang->docTemplate->views = 'Views';
|
||||
$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?';
|
||||
$lang->docTemplate->scope = 'Scope';
|
||||
$lang->docTemplate->lib = $lang->docTemplate->scope;
|
||||
$lang->docTemplate->module = 'Category';
|
||||
$lang->docTemplate->desc = 'Describe';
|
||||
$lang->docTemplate->parentModule = 'Parent';
|
||||
$lang->docTemplate->typeName = 'Category Name';
|
||||
$lang->docTemplate->parent = 'Level';
|
||||
$lang->docTemplate->addTemplateType = 'Add template category';
|
||||
$lang->docTemplate->editTemplateType = 'Edit template category';
|
||||
$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title';
|
||||
$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.';
|
||||
$lang->docTemplate->errorDeleteType = 'There is document template exists in the current category, it cannot be deleted.';
|
||||
$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? After saving as a draft or publishing, you can no longer switch back to the old editor.';
|
||||
$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.';
|
||||
$lang->docTemplate->leaveEditingConfirm = 'The template is currently being edited. Do you want to leave the editing page?';
|
||||
$lang->docTemplate->searchScopePlaceholder = 'Search Scope';
|
||||
$lang->docTemplate->searchTypePlaceholder = 'Search Category';
|
||||
$lang->docTemplate->moveDocTemplate = 'Move Template';
|
||||
$lang->docTemplate->moveSubTemplate = 'Move Sub Template';
|
||||
$lang->docTemplate->createTypeFirst = 'Please create a template category first.';
|
||||
$lang->docTemplate->editedList = 'Template editor';
|
||||
$lang->docTemplate->content = 'Template Text';
|
||||
$lang->docTemplate->templateDesc = 'Template Desc';
|
||||
$lang->docTemplate->status = 'Template Status';
|
||||
$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.';
|
||||
$lang->docTemplate->previewTip = 'After configuring the parameters, this block will display the corresponding list data according to the filter configuration.';
|
||||
$lang->docTemplate->confirmDeleteChapterWithSub = "After deleting a chapter, the lower level content of the chapter will be hidden. Are you sure you want to delete the chapter?";
|
||||
$lang->docTemplate->confirmDeleteTemplateWithSub = "After deleting the template, the lower level content of the template will be hidden. Are you sure you want to delete this template?";
|
||||
$lang->docTemplate->scopeHasTemplateTips = 'There are templates within this scope. Please remove them before deleting the scope.';
|
||||
$lang->docTemplate->scopeHasModuleTips = 'There are template category data within this scope. Please remove them before deleting the scope.';
|
||||
$lang->docTemplate->needEditable = 'This template is not editable.';
|
||||
|
||||
$lang->docTemplate->create = 'Create Template';
|
||||
$lang->docTemplate->edit = 'Edit Template';
|
||||
$lang->docTemplate->delete = 'Delete Template';
|
||||
|
||||
$lang->docTemplate->more = 'More';
|
||||
$lang->docTemplate->scopeLabel = 'Scope';
|
||||
$lang->docTemplate->noTemplate = 'No Doc Template';
|
||||
$lang->docTemplate->noDesc = 'No Desc';
|
||||
$lang->docTemplate->of = ' of ';
|
||||
$lang->docTemplate->overdue = 'Overdue';
|
||||
|
||||
$lang->docTemplate->addModule = 'Add Template Category';
|
||||
$lang->docTemplate->addSameModule = 'Add Same Template Category';
|
||||
$lang->docTemplate->addSubModule = 'Add Sub Template Category';
|
||||
$lang->docTemplate->editModule = 'Edit Template Category';
|
||||
$lang->docTemplate->deleteModule = 'Delete Template Category';
|
||||
$lang->docTemplate->noModules = 'No Categories';
|
||||
$lang->docTemplate->addSubDocTemplate = 'Add sub template';
|
||||
|
||||
$lang->docTemplate->filterTypes = array();
|
||||
$lang->docTemplate->filterTypes[] = array('all', 'All');
|
||||
$lang->docTemplate->filterTypes[] = array('draft', 'Draft');
|
||||
$lang->docTemplate->filterTypes[] = array('released', 'Released');
|
||||
$lang->docTemplate->filterTypes[] = array('createdByMe', 'Created By Me');
|
||||
|
||||
/* Fields. */
|
||||
$lang->doc->common = 'Gestion Documentaire';
|
||||
$lang->doc->id = 'ID';
|
||||
@@ -137,6 +205,7 @@ $lang->doc->update = 'Update';
|
||||
$lang->doc->nextStep = 'Next';
|
||||
$lang->doc->closed = 'Closed';
|
||||
$lang->doc->saveDraft = 'Save Draft';
|
||||
$lang->doc->template = 'Template';
|
||||
$lang->doc->position = 'Position';
|
||||
$lang->doc->person = 'Person';
|
||||
$lang->doc->team = 'Team';
|
||||
@@ -276,7 +345,7 @@ $lang->doc->deleteChapter = 'Delete chapter';
|
||||
$lang->doc->addSubChapter = 'Add sub chapter';
|
||||
$lang->doc->addSameChapter = 'Add same chapter';
|
||||
$lang->doc->addSubDoc = 'Add sub document';
|
||||
$lang->doc->chapterName = 'Chapter name';
|
||||
$lang->doc->chapterName = 'Name';
|
||||
|
||||
$lang->doc->tips = new stdclass();
|
||||
$lang->doc->tips->noProduct = 'No product, please create first';
|
||||
@@ -293,6 +362,7 @@ $lang->doc->zentaoList['planStory'] = $lang->productplan->shortCommon . $la
|
||||
|
||||
$lang->doc->zentaoList['case'] = $lang->testcase->common;
|
||||
$lang->doc->zentaoList['productCase'] = $lang->productCommon . $lang->testcase->common;
|
||||
$lang->doc->zentaoList['projectCase'] = $lang->projectCommon . $lang->testcase->common;
|
||||
$lang->doc->zentaoList['caselib'] = 'Case Library' . $lang->testcase->common;
|
||||
|
||||
$lang->doc->zentaoList['task'] = $lang->task->common;
|
||||
@@ -304,14 +374,17 @@ $lang->doc->zentaoList['more'] = 'More';
|
||||
$lang->doc->zentaoList['productPlan'] = $lang->productCommon . ' Plan';
|
||||
$lang->doc->zentaoList['productPlanContent'] = $lang->productCommon . ' Plan Content';
|
||||
$lang->doc->zentaoList['productRelease'] = $lang->productCommon . $lang->release->common;
|
||||
$lang->doc->zentaoList['projectRelease'] = $lang->projectCommon . $lang->release->common;
|
||||
$lang->doc->zentaoList['ER'] = $lang->defaultERName;
|
||||
$lang->doc->zentaoList['UR'] = $lang->URCommon;
|
||||
$lang->doc->zentaoList['feedback'] = 'Feedback';
|
||||
$lang->doc->zentaoList['ticket'] = 'Ticket';
|
||||
$lang->doc->zentaoList['gantt'] = 'Gantt Chart';
|
||||
|
||||
$lang->doc->zentaoAction = array();
|
||||
$lang->doc->zentaoAction['set'] = 'Setting';
|
||||
$lang->doc->zentaoAction['delete'] = 'Delete';
|
||||
$lang->doc->zentaoAction['set'] = 'Setting';
|
||||
$lang->doc->zentaoAction['delete'] = 'Delete';
|
||||
$lang->doc->zentaoAction['setParams'] = 'Set Parameters';
|
||||
|
||||
$lang->doc->uploadFormatList = array();
|
||||
$lang->doc->uploadFormatList['separateDocs'] = 'Save files as different document';
|
||||
@@ -348,6 +421,9 @@ $lang->doc->statusList['draft'] = "Draft";
|
||||
$lang->doc->aclList['open'] = "Public (Access with library permissions)";
|
||||
$lang->doc->aclList['private'] = "Private (Only creators and whitelist users can access)";
|
||||
|
||||
$lang->doc->aclListA['open'] = "Public (Everyone can access it, with permission to edit document templates for access and maintenance)";
|
||||
$lang->doc->aclListA['private'] = "Private (Only creators can edit and use it)";
|
||||
|
||||
$lang->doc->selectSpace = 'Select Space';
|
||||
$lang->doc->space = 'Space';
|
||||
$lang->doc->spaceList['mine'] = 'My Space';
|
||||
@@ -454,6 +530,7 @@ $lang->doc->docConvertComment = "This document has been converted to t
|
||||
$lang->doc->previewNotAvailable = 'Preview function is not available. Please visit the Kanban board to view the document %s.';
|
||||
$lang->doc->hocuspocusConnect = 'The collaborative editing service is connected.';
|
||||
$lang->doc->hocuspocusDisconnect = 'The collaborative editing service is disconnected. Edits will be synchronized after reconnection.';
|
||||
$lang->doc->docTemplateConvertComment = 'The template has been converted to the new editor format. Switch to version %s to view the template before conversion.';
|
||||
|
||||
$lang->doc->noticeAcl['lib']['product']['default'] = "Users who can access the selected {$lang->productCommon} can access it.";
|
||||
$lang->doc->noticeAcl['lib']['product']['custom'] = "Users who can access the selected {$lang->productCommon} or users in the whiltelist can access it.";
|
||||
@@ -523,6 +600,18 @@ $lang->doc->projectFilterTypes[] = array('mine', 'Involved');
|
||||
|
||||
$lang->doc->spaceFilterTypes[] = array('all', 'All');
|
||||
|
||||
$lang->doc->manageScope = 'Manage Scope';
|
||||
$lang->doc->browseTemplate = 'Template Square';
|
||||
$lang->doc->createTemplate = 'Create Document Template';
|
||||
$lang->doc->editTemplate = 'Edit Document Template';
|
||||
$lang->doc->moveTemplate = 'Move Document Template';
|
||||
$lang->doc->deleteTemplate = 'Delete Document Template';
|
||||
$lang->doc->viewTemplate = 'View Document Template';
|
||||
$lang->doc->addTemplateType = 'Create Category';
|
||||
$lang->doc->editTemplateType = 'Edit Category';
|
||||
$lang->doc->deleteTemplateType = 'Delete Category';
|
||||
$lang->doc->sortTemplate = 'Sort';
|
||||
|
||||
$lang->doc->docLang = new stdClass();
|
||||
$lang->doc->docLang->cancel = $lang->cancel;
|
||||
$lang->doc->docLang->export = $lang->export;
|
||||
@@ -566,6 +655,7 @@ $lang->doc->docLang->moveTo = $lang->doc->moveTo;
|
||||
$lang->doc->docLang->moveLib = $lang->doc->moveLibAction;
|
||||
$lang->doc->docLang->moduleName = $lang->doc->catalogName;
|
||||
$lang->doc->docLang->saveDraft = $lang->doc->saveDraft;
|
||||
$lang->doc->docLang->template = $lang->doc->template;
|
||||
$lang->doc->docLang->release = $lang->doc->release;
|
||||
$lang->doc->docLang->batchMove = $lang->doc->batchMove;
|
||||
$lang->doc->docLang->filterTypes = $lang->doc->filterTypes;
|
||||
@@ -689,3 +779,26 @@ $lang->doc->docLang->editing = 'Editing';
|
||||
$lang->doc->docLang->restoreVersionHint = 'Restore to version';
|
||||
$lang->doc->docLang->restoreVersion = 'Restore';
|
||||
$lang->doc->docLang->restoreVersionConfirm = 'This will create a new version using the content of version {version}. Are you sure you want to continue?';
|
||||
|
||||
$lang->docTemplate->types = array();
|
||||
$lang->docTemplate->types['plan'] = 'Plan';
|
||||
$lang->docTemplate->types['story'] = 'Story';
|
||||
$lang->docTemplate->types['design'] = 'Design';
|
||||
$lang->docTemplate->types['dev'] = 'Development';
|
||||
$lang->docTemplate->types['test'] = 'Test';
|
||||
$lang->docTemplate->types['desc'] = 'Description';
|
||||
$lang->docTemplate->types['other'] = 'Other';
|
||||
|
||||
$lang->docTemplate->builtInScopes = array();
|
||||
$lang->docTemplate->builtInScopes['rnd'] = array();
|
||||
$lang->docTemplate->builtInScopes['or'] = array();
|
||||
$lang->docTemplate->builtInScopes['lite'] = array();
|
||||
$lang->docTemplate->builtInScopes['rnd']['product'] = 'Product';
|
||||
$lang->docTemplate->builtInScopes['rnd']['project'] = 'Project';
|
||||
$lang->docTemplate->builtInScopes['rnd']['execution'] = 'Execution';
|
||||
$lang->docTemplate->builtInScopes['rnd']['personal'] = 'Personal';
|
||||
$lang->docTemplate->builtInScopes['or']['market'] = 'Market';
|
||||
$lang->docTemplate->builtInScopes['or']['product'] = 'Product';
|
||||
$lang->docTemplate->builtInScopes['or']['personal'] = 'Personal';
|
||||
$lang->docTemplate->builtInScopes['lite']['project'] = 'Project';
|
||||
$lang->docTemplate->builtInScopes['lite']['personal'] = 'Personal';
|
||||
|
||||
+115
-2
@@ -73,6 +73,74 @@ $lang->doclib->apiNameUnique['product'] = '同一' . $lang->productCommon . '下
|
||||
$lang->doclib->apiNameUnique['project'] = '同一' . $lang->projectCommon . '下的接口库中';
|
||||
$lang->doclib->apiNameUnique['nolink'] = '独立接口库中';
|
||||
|
||||
$lang->docTemplate = new stdclass();
|
||||
$lang->docTemplate->id = '编号';
|
||||
$lang->docTemplate->title = '模板标题';
|
||||
$lang->docTemplate->frequency = '频率';
|
||||
$lang->docTemplate->type = '分类';
|
||||
$lang->docTemplate->addedBy = '创建者';
|
||||
$lang->docTemplate->addedDate = '创建日期';
|
||||
$lang->docTemplate->editedBy = '修改者';
|
||||
$lang->docTemplate->editedDate = '修改日期';
|
||||
$lang->docTemplate->views = '阅读次数';
|
||||
$lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?';
|
||||
$lang->docTemplate->scope = '所属范围';
|
||||
$lang->docTemplate->lib = $lang->docTemplate->scope;
|
||||
$lang->docTemplate->module = '模板分类';
|
||||
$lang->docTemplate->desc = '描述';
|
||||
$lang->docTemplate->parentModule = '上级分类';
|
||||
$lang->docTemplate->typeName = '分类名称';
|
||||
$lang->docTemplate->parent = '所属层级';
|
||||
$lang->docTemplate->addTemplateType = '添加模板分类';
|
||||
$lang->docTemplate->editTemplateType = '编辑模板分类';
|
||||
$lang->docTemplate->docTitlePlaceholder = '请输入文档模板标题';
|
||||
$lang->docTemplate->docTitleRequired = '文档模板标题不能为空。';
|
||||
$lang->docTemplate->errorDeleteType = '当前分类存在文档模板,不可删除';
|
||||
$lang->docTemplate->convertToNewDocConfirm = '全新文档格式使用现代化块级编辑器,带来全新的文档功能体验。确定要将此文档模板转换为新文档格式吗?存为草稿或者发布后,不能再切换回旧编辑器。';
|
||||
$lang->docTemplate->oldDocEditingTip = '此文档模板为旧版本编辑器创建,已启用新版编辑器编辑,保存后将转换为新版文档模板';
|
||||
$lang->docTemplate->leaveEditingConfirm = '文档模板编辑中,确定离开吗?';
|
||||
$lang->docTemplate->searchScopePlaceholder = '搜索范围';
|
||||
$lang->docTemplate->searchTypePlaceholder = '搜索分类';
|
||||
$lang->docTemplate->moveDocTemplate = '移动文档模板';
|
||||
$lang->docTemplate->moveSubTemplate = '移动子文档模板';
|
||||
$lang->docTemplate->createTypeFirst = '请先创建文档模板分类。';
|
||||
$lang->docTemplate->editedList = '模板编辑者';
|
||||
$lang->docTemplate->content = '模板内容';
|
||||
$lang->docTemplate->templateDesc = '模板描述';
|
||||
$lang->docTemplate->status = '模板状态';
|
||||
$lang->docTemplate->emptyTip = '此参数与筛选条件下,暂无符合条件系统数据。';
|
||||
$lang->docTemplate->previewTip = '配置参数后,此区块会根据筛选器的配置展示相应的列表数据。';
|
||||
$lang->docTemplate->confirmDeleteChapterWithSub = "删除章节后,章节下层级内容将一并隐藏,确定要删除该章节吗?";
|
||||
$lang->docTemplate->confirmDeleteTemplateWithSub = "删除文档模板后,文档模板下层级内容将一并隐藏,确定要删除该文档模板吗?";
|
||||
$lang->docTemplate->scopeHasTemplateTips = '该范围下有文档模板,请移除后再删除范围。';
|
||||
$lang->docTemplate->scopeHasModuleTips = '该范围下有模板分类数据,请移除后再删除范围。';
|
||||
$lang->docTemplate->needEditable = '您没有当前文档模板的编辑权限。';
|
||||
|
||||
$lang->docTemplate->more = '更多';
|
||||
$lang->docTemplate->scopeLabel = '范围';
|
||||
$lang->docTemplate->noTemplate = '没有文档模板';
|
||||
$lang->docTemplate->noDesc = '暂时没有描述';
|
||||
$lang->docTemplate->of = '的';
|
||||
$lang->docTemplate->overdue = '已过期';
|
||||
|
||||
$lang->docTemplate->create = '创建模板';
|
||||
$lang->docTemplate->edit = '编辑文档模板';
|
||||
$lang->docTemplate->delete = '删除文档模板';
|
||||
|
||||
$lang->docTemplate->addModule = '添加分类';
|
||||
$lang->docTemplate->addSameModule = '添加同级分类';
|
||||
$lang->docTemplate->addSubModule = '添加子分类';
|
||||
$lang->docTemplate->editModule = '编辑分类';
|
||||
$lang->docTemplate->deleteModule = '删除分类';
|
||||
$lang->docTemplate->noModules = '没有文档模板分类';
|
||||
$lang->docTemplate->addSubDocTemplate = '添加子文档模板';
|
||||
|
||||
$lang->docTemplate->filterTypes = array();
|
||||
$lang->docTemplate->filterTypes[] = array('all', '全部');
|
||||
$lang->docTemplate->filterTypes[] = array('draft', '草稿');
|
||||
$lang->docTemplate->filterTypes[] = array('released', '已发布');
|
||||
$lang->docTemplate->filterTypes[] = array('createdByMe', '我创建的');
|
||||
|
||||
/* 字段列表。*/
|
||||
$lang->doc->common = '文档';
|
||||
$lang->doc->id = 'ID';
|
||||
@@ -137,6 +205,7 @@ $lang->doc->update = '更新';
|
||||
$lang->doc->nextStep = '下一步';
|
||||
$lang->doc->closed = '已关闭';
|
||||
$lang->doc->saveDraft = '存为草稿';
|
||||
$lang->doc->template = '模板';
|
||||
$lang->doc->position = '所在位置';
|
||||
$lang->doc->person = '个人';
|
||||
$lang->doc->team = '团队';
|
||||
@@ -293,6 +362,7 @@ $lang->doc->zentaoList['planStory'] = $lang->productplan->shortCommon . $la
|
||||
|
||||
$lang->doc->zentaoList['case'] = $lang->testcase->common;
|
||||
$lang->doc->zentaoList['productCase'] = $lang->productCommon . $lang->testcase->common;
|
||||
$lang->doc->zentaoList['projectCase'] = $lang->projectCommon . $lang->testcase->common;
|
||||
$lang->doc->zentaoList['caselib'] = '用例库' . $lang->testcase->common;
|
||||
|
||||
$lang->doc->zentaoList['task'] = $lang->task->common;
|
||||
@@ -304,14 +374,17 @@ $lang->doc->zentaoList['more'] = '更多';
|
||||
$lang->doc->zentaoList['productPlan'] = $lang->productCommon . '下计划';
|
||||
$lang->doc->zentaoList['productPlanContent'] = $lang->productCommon . '计划下的内容';
|
||||
$lang->doc->zentaoList['productRelease'] = $lang->productCommon . $lang->release->common;
|
||||
$lang->doc->zentaoList['projectRelease'] = $lang->projectCommon . $lang->release->common;
|
||||
$lang->doc->zentaoList['ER'] = $lang->defaultERName;
|
||||
$lang->doc->zentaoList['UR'] = $lang->URCommon;
|
||||
$lang->doc->zentaoList['feedback'] = '反馈';
|
||||
$lang->doc->zentaoList['ticket'] = '工单';
|
||||
$lang->doc->zentaoList['gantt'] = '甘特图';
|
||||
|
||||
$lang->doc->zentaoAction = array();
|
||||
$lang->doc->zentaoAction['set'] = '设置';
|
||||
$lang->doc->zentaoAction['delete'] = '删除';
|
||||
$lang->doc->zentaoAction['set'] = '设置';
|
||||
$lang->doc->zentaoAction['delete'] = '删除';
|
||||
$lang->doc->zentaoAction['setParams'] = '配置参数';
|
||||
|
||||
$lang->doc->uploadFormatList = array();
|
||||
$lang->doc->uploadFormatList['separateDocs'] = '每个文件存为不同文档';
|
||||
@@ -348,6 +421,9 @@ $lang->doc->statusList['draft'] = "草稿";
|
||||
$lang->doc->aclList['open'] = "公开(所有人都可查看和编辑)";
|
||||
$lang->doc->aclList['private'] = "私有(仅特定人员可查看和编辑)";
|
||||
|
||||
$lang->doc->aclListA['open'] = "公开(所有人均可访问,有编辑文档模板权限可访问并维护)";
|
||||
$lang->doc->aclListA['private'] = "私有(仅创建者自己可以编辑、使用)";
|
||||
|
||||
$lang->doc->selectSpace = '选择空间';
|
||||
$lang->doc->space = '所属空间';
|
||||
$lang->doc->spaceList['mine'] = '我的空间';
|
||||
@@ -454,6 +530,7 @@ $lang->doc->docConvertComment = "文档已经转换为新编辑器格
|
||||
$lang->doc->previewNotAvailable = '预览功能暂不可用,请访问禅道查看文档 %s。';
|
||||
$lang->doc->hocuspocusConnect = '协作编辑服务已连接。';
|
||||
$lang->doc->hocuspocusDisconnect = '协作编辑服务已断开,编辑内容将在重新连接后同步。';
|
||||
$lang->doc->docTemplateConvertComment = "文档模板已经转换为新编辑器格式,切换版本 %s 来查看转换前的文档模板。";
|
||||
|
||||
$lang->doc->noticeAcl['lib']['product']['default'] = "有所选{$lang->productCommon}访问权限的用户可以访问。";
|
||||
$lang->doc->noticeAcl['lib']['product']['custom'] = "有所选{$lang->productCommon}访问权限或白名单里的用户可以访问。";
|
||||
@@ -523,6 +600,18 @@ $lang->doc->projectFilterTypes[] = array('mine', '我参与的');
|
||||
|
||||
$lang->doc->spaceFilterTypes[] = array('all', '全部');
|
||||
|
||||
$lang->doc->manageScope = '维护范围';
|
||||
$lang->doc->browseTemplate = '模板广场';
|
||||
$lang->doc->createTemplate = '创建文档模板';
|
||||
$lang->doc->editTemplate = '编辑文档模板';
|
||||
$lang->doc->moveTemplate = '移动文档模板';
|
||||
$lang->doc->deleteTemplate = '删除文档模板';
|
||||
$lang->doc->viewTemplate = '文档模板详情';
|
||||
$lang->doc->addTemplateType = '添加模板分类';
|
||||
$lang->doc->editTemplateType = '编辑模板分类';
|
||||
$lang->doc->deleteTemplateType = '删除模板分类';
|
||||
$lang->doc->sortTemplate = '排序';
|
||||
|
||||
$lang->doc->docLang = new stdClass();
|
||||
$lang->doc->docLang->cancel = $lang->cancel;
|
||||
$lang->doc->docLang->export = $lang->export;
|
||||
@@ -566,6 +655,7 @@ $lang->doc->docLang->moveTo = $lang->doc->moveTo;
|
||||
$lang->doc->docLang->moveLib = $lang->doc->moveLibAction;
|
||||
$lang->doc->docLang->moduleName = $lang->doc->catalogName;
|
||||
$lang->doc->docLang->saveDraft = $lang->doc->saveDraft;
|
||||
$lang->doc->docLang->template = $lang->doc->template;
|
||||
$lang->doc->docLang->release = $lang->doc->release;
|
||||
$lang->doc->docLang->batchMove = $lang->doc->batchMove;
|
||||
$lang->doc->docLang->filterTypes = $lang->doc->filterTypes;
|
||||
@@ -689,3 +779,26 @@ $lang->doc->docLang->editing = '正在编辑';
|
||||
$lang->doc->docLang->restoreVersionHint = '恢复到版本';
|
||||
$lang->doc->docLang->restoreVersion = '恢复';
|
||||
$lang->doc->docLang->restoreVersionConfirm = '这将使用文档版本 {version} 的内容创建一个新的版本,确定要继续吗?';
|
||||
|
||||
$lang->docTemplate->types = array();
|
||||
$lang->docTemplate->types['plan'] = '计划';
|
||||
$lang->docTemplate->types['story'] = '需求';
|
||||
$lang->docTemplate->types['design'] = '设计';
|
||||
$lang->docTemplate->types['dev'] = '开发';
|
||||
$lang->docTemplate->types['test'] = '测试';
|
||||
$lang->docTemplate->types['desc'] = '说明';
|
||||
$lang->docTemplate->types['other'] = '其他';
|
||||
|
||||
$lang->docTemplate->builtInScopes = array();
|
||||
$lang->docTemplate->builtInScopes['rnd'] = array();
|
||||
$lang->docTemplate->builtInScopes['or'] = array();
|
||||
$lang->docTemplate->builtInScopes['lite'] = array();
|
||||
$lang->docTemplate->builtInScopes['rnd']['product'] = '产品';
|
||||
$lang->docTemplate->builtInScopes['rnd']['project'] = '项目';
|
||||
$lang->docTemplate->builtInScopes['rnd']['execution'] = '执行';
|
||||
$lang->docTemplate->builtInScopes['rnd']['personal'] = '个人';
|
||||
$lang->docTemplate->builtInScopes['or']['market'] = '市场';
|
||||
$lang->docTemplate->builtInScopes['or']['product'] = '产品';
|
||||
$lang->docTemplate->builtInScopes['or']['personal'] = '个人';
|
||||
$lang->docTemplate->builtInScopes['lite']['project'] = '项目';
|
||||
$lang->docTemplate->builtInScopes['lite']['personal'] = '个人';
|
||||
|
||||
+664
-50
@@ -652,6 +652,35 @@ class docModel extends model
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文档模板列表。
|
||||
* Get document template list.
|
||||
*
|
||||
* @param int $libID
|
||||
* @param string $type
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @param string $searchName
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getDocTemplateList(int $libID = 0, string $type = 'all', string $orderBy = 'id_desc', object $pager = null, string $searchName = ''): array
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_DOC)
|
||||
->where('templateType')->ne('')
|
||||
->andWhere('builtIn')->eq('0')
|
||||
->andWhere('vision')->eq($this->config->vision)
|
||||
->beginIF(!$this->app->user->admin)->andWhere("(`status` = 'normal' or (`status` = 'draft' and `addedBy`='{$this->app->user->account}'))")->fi()
|
||||
->beginIF($libID)->andWhere('lib')->eq($libID)->fi()
|
||||
->beginIF($type == 'draft')->andWhere('status')->eq('draft')->fi()
|
||||
->beginIF($type == 'released')->andWhere('status')->eq('normal')->fi()
|
||||
->beginIF($type == 'createdByMe')->andWhere('addedBy')->eq($this->app->user->account)->fi()
|
||||
->beginIF($searchName)->andWhere('title')->like("%{$searchName}%")->fi()
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->fetchAll('', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过文档ID获取文档所属产品、项目、执行。
|
||||
* Get projects, executions and products by docIdList.
|
||||
@@ -738,18 +767,19 @@ class docModel extends model
|
||||
* @param array $libs
|
||||
* @param string $spaceType
|
||||
* @param int $excludeID
|
||||
* @param bool $queryTemplate
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getDocsOfLibs(array $libs, string $spaceType, int $excludeID = 0): array
|
||||
public function getDocsOfLibs(array $libs, string $spaceType, int $excludeID = 0, $queryTemplate = false): array
|
||||
{
|
||||
$docs = $this->dao->select('t1.*')->from(TABLE_DOC)->alias('t1')
|
||||
->leftJoin(TABLE_MODULE)->alias('t2')->on('t1.module=t2.id')
|
||||
->where('t1.lib')->in($libs)
|
||||
->andWhere('t1.vision')->eq($this->config->vision)
|
||||
->andWhere('t1.templateType')->eq('')
|
||||
->beginIF(!$queryTemplate)->andWhere('t1.templateType')->eq('')->andWhere('t2.type')->eq('doc')->fi()
|
||||
->beginIF($queryTemplate)->andWhere('t1.templateType')->ne('')->andWhere('t1.builtIn')->eq('0')->andWhere('t2.type')->eq('docTemplate')->fi()
|
||||
->andWhere("(t1.status = 'normal' or (t1.status = 'draft' and t1.addedBy='{$this->app->user->account}'))")
|
||||
->andWhere('t2.type')->eq('doc')
|
||||
->andWhere('t2.deleted')->eq('0')
|
||||
->beginIF(!empty($excludeID))->andWhere("NOT FIND_IN_SET('{$excludeID}', t1.`path`)")->andWhere('t1.id')->ne($excludeID)->fi()
|
||||
->orderBy('t1.`order` asc, t1.id asc')
|
||||
@@ -758,7 +788,8 @@ class docModel extends model
|
||||
$rootDocs = $this->dao->select('*')->from(TABLE_DOC)
|
||||
->where('lib')->in($libs)
|
||||
->andWhere('vision')->eq($this->config->vision)
|
||||
->andWhere('templateType')->eq('')
|
||||
->beginIF(!$queryTemplate)->andWhere('templateType')->eq('')->fi()
|
||||
->beginIF($queryTemplate)->andWhere('templateType')->ne('')->andWhere('builtIn')->eq('0')->fi()
|
||||
->andWhere("(status = 'normal' or (status = 'draft' and addedBy='{$this->app->user->account}'))")
|
||||
->andWhere('module')->in(array('0', ''))
|
||||
->beginIF(!empty($excludeID))->andWhere("NOT FIND_IN_SET('{$excludeID}', `path`)")->andWhere('id')->ne($excludeID)->fi()
|
||||
@@ -846,13 +877,14 @@ class docModel extends model
|
||||
$doc->editable = false;
|
||||
|
||||
$isOpen = $doc->acl == 'open';
|
||||
$isAuthorOrAdmin = $doc->acl == 'private' && ($doc->addedBy == $currentAccount || ($this->app->user->admin && $spaceType !== 'mine'));
|
||||
$isAuthorOrAdmin = $doc->addedBy == $currentAccount || ($this->app->user->admin && $spaceType !== 'mine');
|
||||
$isInReadUsers = strpos(",$doc->readUsers,", ",$currentAccount,") !== false;
|
||||
$isInEditUsers = strpos(",$doc->users,", ",$currentAccount,") !== false;
|
||||
if($isOpen || $isAuthorOrAdmin || $isInReadUsers || $isInEditUsers)
|
||||
{
|
||||
$doc->editable = $isOpen || $isAuthorOrAdmin || $isInEditUsers;
|
||||
$doc->readable = $isOpen || $isAuthorOrAdmin || $isInReadUsers || $doc->editable;
|
||||
if($spaceType == 'template') $doc->editable = ($isOpen && common::hasPriv('doc', 'editTemplate')) || $isAuthorOrAdmin || $isInEditUsers;
|
||||
}
|
||||
elseif(!empty($doc->groups) || !empty($doc->readGroups))
|
||||
{
|
||||
@@ -1119,19 +1151,6 @@ class docModel extends model
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文档草稿。
|
||||
* Get doc draft.
|
||||
*
|
||||
* @param int $docID 文档ID
|
||||
* @access public
|
||||
* @return ?object
|
||||
*/
|
||||
public function getDraft(int $docID): ?object
|
||||
{
|
||||
return $this->getContent($docID, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理文档数据。
|
||||
* Process doc data.
|
||||
@@ -1180,8 +1199,23 @@ class docModel extends model
|
||||
$doc->productName = $doc->executionName = $doc->moduleName = '';
|
||||
if($doc->product) $doc->productName = $this->dao->findByID($doc->product)->from(TABLE_PRODUCT)->fetch('name');
|
||||
if($doc->execution) $doc->executionName = $this->dao->findByID($doc->execution)->from(TABLE_EXECUTION)->fetch('name');
|
||||
if($doc->module) $doc->moduleName = $this->dao->findByID($doc->module)->from(TABLE_MODULE)->fetch('name');
|
||||
if(!$doc->module && $doc->type == 'article' && $doc->parent) $doc->moduleName = $this->dao->findByID($doc->parent)->from(TABLE_DOC)->fetch('title');
|
||||
if($doc->module)
|
||||
{
|
||||
if($doc->type == 'article' && $doc->parent)
|
||||
{
|
||||
$doc->moduleName = $this->dao->findByID($doc->parent)->from(TABLE_DOC)->fetch('title');
|
||||
}
|
||||
elseif(!empty($doc->templateType))
|
||||
{
|
||||
$modules = $this->getTemplateModules();
|
||||
$modules = array_column($modules, 'fullName', 'id');
|
||||
$doc->moduleName = zget($modules, $doc->module);
|
||||
}
|
||||
else
|
||||
{
|
||||
$doc->moduleName = $this->dao->findByID($doc->module)->from(TABLE_MODULE)->fetch('name');
|
||||
}
|
||||
}
|
||||
|
||||
return $doc;
|
||||
}
|
||||
@@ -1545,12 +1579,16 @@ class docModel extends model
|
||||
if(empty($doc->lib) && strpos((string)$doc->module, '_') !== false) list($doc->lib, $doc->module) = explode('_', $doc->module);
|
||||
if(empty($doc->lib)) return dao::$errors['lib'] = sprintf($this->lang->error->notempty, $this->lang->doc->lib);
|
||||
|
||||
$isDoc = empty($doc->templateType);
|
||||
$isDraft = $doc->status == 'draft';
|
||||
$lib = $this->getLibByID($doc->lib);
|
||||
if($doc->contentType != 'doc') $doc = $this->loadModel('file')->processImgURL($doc, $this->config->doc->editor->create['id'], (string)$this->post->uid);
|
||||
$doc->product = $lib->product;
|
||||
$doc->project = $lib->project;
|
||||
$doc->execution = $lib->execution;
|
||||
if($isDoc)
|
||||
{
|
||||
$doc->product = $lib->product;
|
||||
$doc->project = $lib->project;
|
||||
$doc->execution = $lib->execution;
|
||||
}
|
||||
|
||||
$docContent = new stdclass();
|
||||
$docContent->title = $doc->title;
|
||||
@@ -1567,7 +1605,7 @@ class docModel extends model
|
||||
unset($doc->contentType);
|
||||
unset($doc->rawContent);
|
||||
|
||||
$requiredFields = $isDraft ? 'title' : $this->config->doc->create->requiredFields;
|
||||
$requiredFields = $isDraft ? 'title' : ($isDoc ? $this->config->doc->create->requiredFields : $this->config->doc->createTemplate->requiredFields);
|
||||
if(strpos("url|word|ppt|excel", $doc->type) !== false) $requiredFields = trim(str_replace(",content,", ",", ",{$requiredFields},"), ',');
|
||||
|
||||
$checkContent = strpos(",$requiredFields,", ',content,') !== false;
|
||||
@@ -1601,11 +1639,11 @@ class docModel extends model
|
||||
$files = $this->file->saveUpload('doc', $docID);
|
||||
|
||||
$docContent->doc = $docID;
|
||||
$docContent->files = join(',', array_keys($files));
|
||||
$docContent->files = implode(',', array_keys($files));
|
||||
if(!empty($doc->template)) $docContent->rawContent = $this->loadExtension('zentaomax')->getTemplateContent((int)$doc->template, $docID);
|
||||
$this->dao->insert(TABLE_DOCCONTENT)->data($docContent)->exec();
|
||||
|
||||
$this->loadModel('score')->create('doc', 'create', $docID);
|
||||
|
||||
$this->loadModel('score')->create('doc', $isDoc ? 'create' : 'createTemplate', $docID);
|
||||
return array('status' => 'new', 'id' => $docID, 'files' => $files, 'docType' => $doc->type, 'libID' => $doc->lib);
|
||||
}
|
||||
|
||||
@@ -1623,7 +1661,7 @@ class docModel extends model
|
||||
public function saveDocContent(int $docID, object $docData, int $version, array $files = array()): object
|
||||
{
|
||||
/* 获取文档草稿作为要更新的内容。 */
|
||||
$docContent = $this->getContent($docID, 0);
|
||||
$docContent = $this->getContent($docID, $version);
|
||||
if(!$docContent) $docContent = new stdClass();
|
||||
|
||||
$docContent->editedBy = $docData->editedBy;
|
||||
@@ -1678,37 +1716,32 @@ class docModel extends model
|
||||
$files = $this->loadModel('file')->saveUpload('doc', $docID);
|
||||
if(dao::isError()) return false;
|
||||
|
||||
$oldDoc = $this->getByID($docID);
|
||||
$changes = common::createChanges($oldDoc, $doc);
|
||||
$oldRawContent = isset($oldDoc->rawContent) ? $oldDoc->rawContent : '';
|
||||
$newRawContent = isset($doc->rawContent) ? $doc->rawContent : '';
|
||||
$onlyRawChanged = $oldRawContent != $newRawContent;
|
||||
$isDraft = $doc->status == 'draft';
|
||||
$version = $isDraft ? 0 : ($oldDoc->version + 1);
|
||||
$changed = $files || $onlyRawChanged || (!$isDraft && $oldDoc->version == 0);
|
||||
$oldDoc = $this->getByID($docID);
|
||||
$changes = common::createChanges($oldDoc, $doc);
|
||||
$oldRawContent = isset($oldDoc->rawContent) ? $oldDoc->rawContent : '';
|
||||
$newRawContent = isset($doc->rawContent) ? $doc->rawContent : '';
|
||||
$onlyRawChanged = $oldRawContent != $newRawContent;
|
||||
$isDraft = $doc->status == 'draft';
|
||||
$version = $isDraft ? $oldDoc->version : ($oldDoc->version + 1);
|
||||
$changed = $files || $onlyRawChanged || (!$isDraft && $oldDoc->status == 'draft');
|
||||
$basicInfoChanged = false;
|
||||
foreach($changes as $change)
|
||||
{
|
||||
if(in_array($change['field'], array('module', 'lib', 'acl', 'groups', 'users'))) $basicInfoChanged = true;
|
||||
if($change['field'] == 'content' || $change['field'] == 'title' || $change['field'] == 'rawContent') $changed = true;
|
||||
if($change['field'] == 'content')
|
||||
{
|
||||
$onlyRawChanged = false;
|
||||
break;
|
||||
}
|
||||
if($change['field'] == 'content') $onlyRawChanged = false;
|
||||
}
|
||||
if($onlyRawChanged) $changes[] = array('field' => 'content', 'old' => $oldDoc->content, 'new' => $doc->content);
|
||||
if($changed) $this->saveDocContent($docID, $doc, $version, array_merge(array_keys($files), array_keys($oldDoc->files)));
|
||||
else $version = $oldDoc->version;
|
||||
if(dao::isError()) return false;
|
||||
|
||||
unset($doc->contentType);
|
||||
unset($doc->rawContent);
|
||||
unset($doc->fromVersion);
|
||||
$doc->version = max($version, $oldDoc->version);
|
||||
$doc->draft = $isDraft ? $doc->content : '';
|
||||
$doc->content = $doc->title;
|
||||
if(empty($doc->status)) $doc->status = $isDraft ? $oldDoc->status : 'normal';
|
||||
|
||||
if($doc->parent != $oldDoc->parent)
|
||||
if(isset($doc->parent) && $doc->parent != $oldDoc->parent)
|
||||
{
|
||||
$path = ",{$docID}";
|
||||
if($doc->parent)
|
||||
@@ -1720,7 +1753,7 @@ class docModel extends model
|
||||
$doc->path = $path;
|
||||
}
|
||||
|
||||
$this->dao->update(TABLE_DOC)->data($doc, 'content')
|
||||
$this->dao->update(TABLE_DOC)->data($doc, 'content,contentType,rawContent,fromVersion')
|
||||
->autoCheck()
|
||||
->batchCheck($requiredFields, 'notempty')
|
||||
->where('id')->eq($docID)
|
||||
@@ -1728,6 +1761,24 @@ class docModel extends model
|
||||
|
||||
if(dao::isError()) return false;
|
||||
if($files) $this->file->updateObjectID($this->post->uid, $docID, 'doc');
|
||||
|
||||
/* 如果修改了父模板,子模板也同步更新相关信息。*/
|
||||
/* If the parent template is modified, the child template will also update the relevant information synchronously. */
|
||||
if(!empty($oldDoc->templateType) && empty($doc->parent) && $basicInfoChanged)
|
||||
{
|
||||
$this->dao->update(TABLE_DOC)
|
||||
->set('module')->eq($doc->module)
|
||||
->set('lib')->eq($doc->lib)
|
||||
->set('acl')->eq($doc->acl)
|
||||
->where("FIND_IN_SET('{$docID}', `path`)")
|
||||
->exec();
|
||||
}
|
||||
|
||||
if(in_array($oldDoc->contentType, array('html', 'attachment', 'markdown')) && !in_array($doc->contentType, array('html', 'attachment', 'markdown')))
|
||||
{
|
||||
$objectType = !empty($doc->templateType) ? 'doctemplate' : 'doc';
|
||||
$this->loadModel('action')->create($objectType, $docID, 'convertToNewDoc');
|
||||
}
|
||||
return array('changes' => $changes, 'files' => array_keys($files));
|
||||
}
|
||||
|
||||
@@ -1944,9 +1995,12 @@ class docModel extends model
|
||||
if($doc->status == 'draft' && $doc->addedBy != $this->app->user->account) return false;
|
||||
if($doc->status == 'normal' && $this->app->user->admin) return true;
|
||||
|
||||
static $libs = array();
|
||||
if(!isset($libs[$doc->lib])) $libs[$doc->lib] = $this->getLibByID((int)$doc->lib);
|
||||
if(!$this->checkPrivLib($libs[$doc->lib], '', (string)$doc->id)) return false;
|
||||
if(empty($doc->templateType))
|
||||
{
|
||||
static $libs = array();
|
||||
if(!isset($libs[$doc->lib])) $libs[$doc->lib] = $this->getLibByID((int)$doc->lib);
|
||||
if(!$this->checkPrivLib($libs[$doc->lib], '', (string)$doc->id)) return false;
|
||||
}
|
||||
|
||||
if(in_array($doc->acl, array('open', 'public'))) return true;
|
||||
|
||||
@@ -2059,6 +2113,7 @@ class docModel extends model
|
||||
|
||||
$docs = $this->dao->select("`id`,`addedBy`,`type`,`lib`,`acl`,`users`,`readUsers`,`groups`,`readGroups`,`status`,`path`,`deleted`")->from(TABLE_DOC)
|
||||
->where('lib')->in($libIDList)
|
||||
->andWhere('builtIn')->eq('0')
|
||||
->andWhere('type')->ne('chapter')
|
||||
->fetchAll();
|
||||
|
||||
@@ -2291,6 +2346,7 @@ class docModel extends model
|
||||
->where('lib')->in($idList)
|
||||
->andWhere('type')->ne('chapter')
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('builtIn')->eq('0')
|
||||
->andWhere('module')->eq('0')
|
||||
->fetchAll();
|
||||
$docs = $this->docTao->filterDeletedDocs($docs);
|
||||
@@ -2725,6 +2781,7 @@ class docModel extends model
|
||||
$statistic->totalDocs = $this->dao->select('COUNT(1) AS count')->from(TABLE_DOC)
|
||||
->where('deleted')->eq('0')
|
||||
->andWhere('type')->in($this->config->doc->docTypes)
|
||||
->andWhere('templateType')->eq('')
|
||||
->andWhere('vision')->eq($this->config->vision)
|
||||
->fetch('count');
|
||||
|
||||
@@ -2753,6 +2810,7 @@ class docModel extends model
|
||||
$myStatistic = $this->dao->select("COUNT(1) AS myDocs, SUM(views) as docViews, SUM(collects) as docCollects")->from(TABLE_DOC)
|
||||
->where('addedBy')->eq($this->app->user->account)
|
||||
->andWhere('type')->in($this->config->doc->docTypes)
|
||||
->andWhere('templateType')->eq('')
|
||||
->andWhere('deleted')->eq(0)
|
||||
->andWhere('vision')->eq($this->config->vision)
|
||||
->andWhere('lib')->ne('')
|
||||
@@ -2967,10 +3025,11 @@ class docModel extends model
|
||||
public function getDocsBySearch(string $type, int $objectID, int $libID, int $queryID, string $orderBy = 'id_desc', object $pager = null): array
|
||||
{
|
||||
$query = $this->buildQuery($type, $queryID);
|
||||
$libs = $this->getLibsByObject($type, $objectID);
|
||||
$libs = $this->getLibsByObject($type, $objectID, $libID);
|
||||
$docIdList = $this->getPrivDocs(array_keys($libs));
|
||||
$docs = $this->dao->select('*')->from(TABLE_DOC)
|
||||
->where('deleted')->eq(0)
|
||||
->andWhere('builtIn')->eq('0')
|
||||
->andWhere($query)
|
||||
->andWhere('lib')->in(array_keys($libs))
|
||||
->andWhere('vision')->eq($this->config->vision)
|
||||
@@ -3878,6 +3937,358 @@ class docModel extends model
|
||||
return !empty($docID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建模板类型数据。
|
||||
* Build data of template type module.
|
||||
*
|
||||
* @param int $scope
|
||||
* @param int $parent
|
||||
* @param string $name
|
||||
* @param string $code
|
||||
* @param int $grade
|
||||
* @param string $path
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function buildTemplateModule($scope, $parent, $name, $code, $grade = 1, $path = '')
|
||||
{
|
||||
$module = new stdclass();
|
||||
$module->type = 'docTemplate';
|
||||
$module->root = $scope;
|
||||
$module->parent = $parent;
|
||||
$module->name = $name;
|
||||
$module->short = $code;
|
||||
$module->grade = $grade;
|
||||
$module->path = $path;
|
||||
|
||||
return $module;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文档模板是否已升级。
|
||||
* Check if doc template has been upgraded
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function checkIsTemplateUpgraded()
|
||||
{
|
||||
$templateModule = $this->dao->select('1')->from(TABLE_MODULE)->where('type')->eq('docTemplate')->fetch();
|
||||
return !empty($templateModule);
|
||||
}
|
||||
|
||||
/**
|
||||
* 升级模板类型数据。
|
||||
* Upgrade document template types.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function upgradeTemplateTypes()
|
||||
{
|
||||
$currentLang = $this->app->getClientLang();
|
||||
$conditions = "`module` = 'baseline' AND `section` = 'objectList' AND `vision` = '{$this->config->vision}'";
|
||||
$templateTypes = $this->dao->select('`key`, `value`')->from(TABLE_LANG)->where($conditions)->andWhere('lang')->eq($currentLang)->fetchPairs();
|
||||
if(empty($templateTypes)) $templateTypes = $this->dao->select('`key`, `value`')->from(TABLE_LANG)->where($conditions)->andWhere('lang')->eq('all')->fetchPairs();
|
||||
|
||||
if(empty($templateTypes))
|
||||
{
|
||||
$this->app->loadLang('baseline');
|
||||
$templateTypes = $this->lang->baseline->objectList;
|
||||
}
|
||||
|
||||
$usedTemplateTypes = $this->dao->select('`key`, `value`')->from(TABLE_LANG)->alias('t1')
|
||||
->leftJoin(TABLE_DOC)->alias('t2')->on('t1.key = t2.templateType')
|
||||
->where('t1.module')->eq('baseline')
|
||||
->andWhere('t1.section')->eq('objectList')
|
||||
->andWhere('t1.lang', true)->ne($currentLang)
|
||||
->orWhere('t1.vision')->ne($this->config->vision)
|
||||
->markRight(1)
|
||||
->andWhere('t1.key')->notin(array_keys($templateTypes))
|
||||
->andWhere('t2.templateType')->ne('')
|
||||
->andWhere('t2.lib')->eq('')
|
||||
->andWhere('t2.module')->eq('')
|
||||
->andWhere('t2.deleted')->eq(0)
|
||||
->fetchPairs();
|
||||
|
||||
$oldTemplateTypes = array_filter(arrayUnion($templateTypes, $usedTemplateTypes));
|
||||
|
||||
if(empty($oldTemplateTypes)) return true;
|
||||
|
||||
$this->loadModel('setting');
|
||||
foreach(array('rnd', 'or') as $vision)
|
||||
{
|
||||
$scopeMaps = $this->setting->getItem("vision={$vision}&owner=system&module=doc&key=builtInScopeMaps");
|
||||
$scopeMaps = json_decode($scopeMaps, true);
|
||||
$scopeID = $vision == 'rnd' ? zget($scopeMaps, 'project', 0) : zget($scopeMaps, 'product', 0);
|
||||
if(!$scopeID) continue;
|
||||
|
||||
$parentTypes = array();
|
||||
foreach($this->lang->docTemplate->types as $key => $value)
|
||||
{
|
||||
$module = $this->buildTemplateModule($scopeID, 0, $value, $key, 1);
|
||||
$this->dao->insert(TABLE_MODULE)->data($module)->exec();
|
||||
if(dao::isError()) return false;
|
||||
|
||||
$moduleID = $this->dao->lastInsertID();
|
||||
$this->dao->update(TABLE_MODULE)->set('path')->eq(",{$moduleID},")->where('id')->eq($moduleID)->exec();
|
||||
|
||||
$parentTypes[$key] = $moduleID;
|
||||
}
|
||||
|
||||
foreach($oldTemplateTypes as $key => $value)
|
||||
{
|
||||
$parentKey = zget($this->config->doc->templateTypeParents, $key, 'other');
|
||||
$parentID = $parentTypes[$parentKey];
|
||||
|
||||
$module = $this->buildTemplateModule($scopeID, $parentID, $value, $key, 2);
|
||||
$this->dao->insert(TABLE_MODULE)->data($module)->exec();
|
||||
if(dao::isError()) return false;
|
||||
|
||||
$moduleID = $this->dao->lastInsertID();
|
||||
$this->dao->update(TABLE_MODULE)->set('path')->eq(",{$parentID},{$moduleID},")->where('id')->eq($moduleID)->exec();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加内置的模板范围。
|
||||
* Add built in scopes.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function addBuiltInScopes()
|
||||
{
|
||||
$builtInScopes = $this->dao->select('*')->from(TABLE_DOCLIB)->where('type')->eq('template')->andWhere('main')->eq('1')->fetchAll();
|
||||
if(!empty($builtInScopes)) return;
|
||||
|
||||
$this->loadModel('setting');
|
||||
$scope = new stdClass();
|
||||
$scope->type = 'template';
|
||||
$scope->main = '1';
|
||||
$scope->addedBy = 'system';
|
||||
$scope->addedDate = helper::now();
|
||||
foreach($this->lang->docTemplate->builtInScopes as $vision => $scopeList)
|
||||
{
|
||||
$scopeMaps = array();
|
||||
$scope->vision = $vision;
|
||||
foreach($scopeList as $scopeKey => $scopeName)
|
||||
{
|
||||
if(empty($scopeName)) continue;
|
||||
|
||||
$scope->name = $scopeName;
|
||||
$this->dao->insert(TABLE_DOCLIB)->data($scope)->exec();
|
||||
|
||||
$scopeID = $this->dao->lastInsertID();
|
||||
$scopeMaps[$scopeKey] = $scopeID;
|
||||
}
|
||||
if(!empty($scopeMaps)) $this->setting->setItem("system.doc.builtInScopeMaps@{$vision}", json_encode($scopeMaps));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 升级文档模板的范围和类型。
|
||||
* Upgrade lib and module of template.
|
||||
*
|
||||
* @param array $templateIdList
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function upgradeTemplateLibAndModule(array $templateIdList = array())
|
||||
{
|
||||
$templateList = $this->dao->select('*')->from(TABLE_DOC)->where('id')->in($templateIdList)->fetchAll('id');
|
||||
if(empty($templateList)) return true;
|
||||
|
||||
$this->loadModel('setting');
|
||||
$rndScopeMaps = $this->setting->getItem('vision=rnd&owner=system&module=doc&key=builtInScopeMaps');
|
||||
$orScopeMaps = $this->setting->getItem('vision=or&owner=system&module=doc&key=builtInScopeMaps');
|
||||
$rndScopeMaps = json_decode($rndScopeMaps, true);
|
||||
$orScopeMaps = json_decode($orScopeMaps, true);
|
||||
$moduleGroup = $this->dao->select('root,short,id')->from(TABLE_MODULE)->where('deleted')->eq('0')->andWhere('root')->in(array($rndScopeMaps['project'], $orScopeMaps['product']))->fetchGroup('root', 'short');
|
||||
foreach($templateList as $id => $template)
|
||||
{
|
||||
$templateVision = $template->vision;
|
||||
$templateType = $template->templateType;
|
||||
$templateScopeID = $templateVision == 'or' ? zget($orScopeMaps, 'product', 0) : zget($rndScopeMaps, 'project', 0);
|
||||
$template->lib = $templateScopeID;
|
||||
$template->module = $moduleGroup[$templateScopeID][$templateType]->id;
|
||||
$template->assignedDate = helper::isZeroDate($template->assignedDate) ? null : $template->assignedDate;
|
||||
$template->approvedDate = helper::isZeroDate($template->approvedDate) ? null : $template->approvedDate;
|
||||
$this->dao->update(TABLE_DOC)->data($template)->where('id')->eq($id)->exec();
|
||||
if(dao::isError()) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文档模板类型的模块。
|
||||
* Get modules of doc template type.
|
||||
*
|
||||
* @param bool $onlyNode
|
||||
* @param string|int $root
|
||||
* @param string $grade
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getTemplateModules($root = 'all', $grade = 'all')
|
||||
{
|
||||
$modules = $this->dao->select('*')->from(TABLE_MODULE)
|
||||
->where('deleted')->eq('0')
|
||||
->andWhere('type')->eq('docTemplate')
|
||||
->beginIF($root != 'all')->andWhere('root')->eq($root)->fi()
|
||||
->beginIF($grade != 'all')->andWhere('grade')->eq($grade)->fi()
|
||||
->fetchAll('id');
|
||||
|
||||
foreach($modules as $module)
|
||||
{
|
||||
$path = explode(',', trim($module->path, ','));
|
||||
$names = array('');
|
||||
foreach($path as $id)
|
||||
{
|
||||
if(!isset($modules[$id])) continue;
|
||||
$names[] = $modules[$id]->name;
|
||||
}
|
||||
$module->fullName = implode('/', $names);
|
||||
}
|
||||
|
||||
return array_values($modules);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取范围数据。
|
||||
* Get scope items.
|
||||
*
|
||||
* @param array $scopeList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getScopeItems(array $scopeList = array())
|
||||
{
|
||||
$items = array();
|
||||
foreach($scopeList as $scope) $items[] = array('value' => $scope->id, 'text' => $scope->name);
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断一个模块是否是内置的文档模板类型。
|
||||
* Judge whether a module is builtin template type.
|
||||
*
|
||||
* @param array $scopeIdList
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function getScopeTemplates(array $scopeIdList = array())
|
||||
{
|
||||
$scopeTemplates = array();
|
||||
|
||||
foreach($scopeIdList as $scopeID)
|
||||
{
|
||||
$templates = $this->getHotTemplates($scopeID, 5);
|
||||
$scopeTemplates[$scopeID] = $this->filterPrivDocs($templates, 'template');
|
||||
}
|
||||
|
||||
return $scopeTemplates;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取范围内的最近顶层文档模板。
|
||||
* Get the recent top template of scope.
|
||||
*
|
||||
* @param int $scopeID
|
||||
* @param int $limit
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getHotTemplates($scopeID = 0, $limit = 0)
|
||||
{
|
||||
return $this->dao->select('*, CASE WHEN addedDate > editedDate THEN addedDate ELSE editedDate END as hotDate')->from(TABLE_DOC)
|
||||
->where('templateType')->ne('')
|
||||
->andWhere('builtIn')->eq('0')
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('status')->eq('normal')
|
||||
->andWhere('parent')->eq(0)
|
||||
->andWhere('vision')->eq($this->config->vision)
|
||||
->beginIF($scopeID)->andWhere('lib')->eq($scopeID)->fi()
|
||||
->orderBy('hotDate_desc')
|
||||
->beginIF($limit)->limit($limit)->fi()
|
||||
->fetchAll('', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除一个文档模板。
|
||||
* Delete a doc template.
|
||||
*
|
||||
* @param string $table
|
||||
* @param int $id
|
||||
* @param string $objectType
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function deleteTemplate(int $id)
|
||||
{
|
||||
if(empty($id)) return false;
|
||||
|
||||
$this->dao->update(TABLE_DOC)->set('deleted')->eq(1)->where('id')->eq($id)->exec();
|
||||
$this->loadModel('action')->create('doctemplate', $id, 'deleted', '', ACTIONMODEL::CAN_UNDELETED);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加文档模板类型。
|
||||
* Add template type.
|
||||
*
|
||||
* @param object $moduleData
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function addTemplateType($moduleData)
|
||||
{
|
||||
$this->dao->insert(TABLE_MODULE)->data($moduleData)->autoCheck()->exec();
|
||||
$moduleID = $this->dao->lastInsertID();
|
||||
|
||||
$path = $moduleData->grade == 1 ? ",{$moduleID}," : ",{$moduleData->parent},{$moduleID},";
|
||||
$this->dao->update(TABLE_MODULE)->set('path')->eq($path)->set('short')->eq("custom{$moduleID}")->where('id')->eq($moduleID)->exec();
|
||||
|
||||
return $moduleID;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个模板类型下的所有模板。
|
||||
* Get template list by type.
|
||||
*
|
||||
* @param int|null $type
|
||||
* @param string $status
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function getTemplatesByType($type = null, $status = 'all')
|
||||
{
|
||||
$types = array();
|
||||
if(!is_null($type))
|
||||
{
|
||||
$subTypes = $this->dao->select('id')->from(TABLE_MODULE)
|
||||
->where('deleted')->eq('0')
|
||||
->andWhere('parent')->eq($type)
|
||||
->andWhere('type')->eq('docTemplate')
|
||||
->fetchPairs('id');
|
||||
$types = array_values($subTypes);
|
||||
$types[] = $type;
|
||||
}
|
||||
|
||||
return $this->dao->select('*')->from(TABLE_DOC)
|
||||
->where('deleted')->eq('0')
|
||||
->andWhere('templateType')->ne('')
|
||||
->andWhere('builtIn')->eq('0')
|
||||
->andWhere('vision')->eq($this->config->vision)
|
||||
->beginIF(!is_null($type))->andWhere('module')->in($types)->fi()
|
||||
->beginIF($status != 'all')->andWhere('status')->eq($status)->fi()
|
||||
->fetchAll('id', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上次访问的文档对象。
|
||||
* Get last viewed doc object.
|
||||
@@ -4098,4 +4509,207 @@ class docModel extends model
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文档模板的范围。
|
||||
* Get the scope of template.
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getTemplateScopes(): array
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_DOCLIB)->where('type')->eq('template')->andWhere('vision')->eq($this->config->vision)->andWhere('deleted')->eq('0')->fetchAll('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新模板范围。
|
||||
* Update the scope of template.
|
||||
*
|
||||
* @param array scopeList
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function updateTemplateScopes(array $scopeList = array())
|
||||
{
|
||||
foreach($scopeList as $id => $name)
|
||||
{
|
||||
$this->dao->update(TABLE_DOCLIB)->set('name')->eq($name)->where('id')->eq($id)->andWhere('vision')->eq($this->config->vision)->exec();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入模板范围。
|
||||
* Insert the scope of template.
|
||||
*
|
||||
* @param array scopeList
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function insertTemplateScopes(array $scopeList = array())
|
||||
{
|
||||
foreach($scopeList as $name)
|
||||
{
|
||||
if(empty($name)) continue;
|
||||
|
||||
$scope = new stdClass();
|
||||
$scope->name = $name;
|
||||
$scope->type = 'template';
|
||||
$scope->main = '0';
|
||||
$scope->vision = $this->config->vision;
|
||||
$scope->addedBy = $this->app->user->account;
|
||||
$scope->addedDate = helper::now();
|
||||
$this->dao->insert(TABLE_DOCLIB)->data($scope)->exec();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除模板范围。
|
||||
* Delete the scope of template.
|
||||
*
|
||||
* @param array scopeList
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function deleteTemplateScopes(array $scopeIdList = array())
|
||||
{
|
||||
$this->dao->update(TABLE_DOCLIB)->set('deleted')->eq('1')->where('id')->in($scopeIdList)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制模板,将研发界面的除Wiki类型的模板复制到OR界面,将OR界面的所有文档模板复制到研发界面。
|
||||
* Copy templates of R&D interface, except for wiki type templates, to OR interface, and copy all templates of OR interface to R&D interface.
|
||||
*
|
||||
* @param array templateIdList
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function copyTemplate(array $templateIdList = array())
|
||||
{
|
||||
if(empty($templateIdList)) return array();
|
||||
|
||||
$oldTemplateList = $this->dao->select('*')->from(TABLE_DOC)->where('id')->in($templateIdList)->fetchAll('id');
|
||||
$oldContentList = $this->dao->select('*')->from(TABLE_DOCCONTENT)->where('doc')->in($templateIdList)->fetchGroup('doc', 'id');
|
||||
$oldChapterList = $this->dao->select('*')->from(TABLE_DOC)->where('template')->ne('')->andWhere('type')->in('chapter,article')->fetchGroup('template', 'id');
|
||||
$newTemplateList = array();
|
||||
|
||||
foreach($oldTemplateList as $oldTemplateID => $template)
|
||||
{
|
||||
/* 研发界面的Wiki类型模板不复制到OR界面。*/
|
||||
/* The wiki type template of R&D interface is not copied to OR interface. */
|
||||
if($template->vision == 'rnd' && $template->type == 'book') continue;
|
||||
|
||||
/* 复制模板及模板内容。*/
|
||||
/* Copy template and content. */
|
||||
unset($template->id);
|
||||
$templateVision = $template->vision == 'rnd' ? 'or' : 'rnd';
|
||||
$template->vision = $templateVision;
|
||||
$template->assignedDate = helper::isZeroDate($template->assignedDate) ? null : $template->assignedDate;
|
||||
$template->approvedDate = helper::isZeroDate($template->approvedDate) ? null : $template->approvedDate;
|
||||
$this->dao->insert(TABLE_DOC)->data($template)->exec();
|
||||
$newTemplateID = $this->dao->lastInsertID();
|
||||
|
||||
foreach($oldContentList[$oldTemplateID] as $content)
|
||||
{
|
||||
unset($content->id);
|
||||
$content->doc = $newTemplateID;
|
||||
$content->addedDate = helper::isZeroDate($content->addedDate) ? null : $content->addedDate;
|
||||
$content->editedDate = helper::isZeroDate($content->editedDate) ? null : $content->editedDate;
|
||||
$this->dao->insert(TABLE_DOCCONTENT)->data($content)->exec();
|
||||
}
|
||||
|
||||
/* OR界面的Wiki类型模板复制到研发界面。*/
|
||||
/* Copy the wiki type template of OR interface to R&D interface. */
|
||||
if($template->type == 'book' && isset($oldChapterList[$oldTemplateID]))
|
||||
{
|
||||
$chapterList = $oldChapterList[$oldTemplateID];
|
||||
$chapterContent = $this->dao->select('*')->from(TABLE_DOCCONTENT)->where('doc')->in(array_keys($chapterList))->fetchGroup('doc', 'id');
|
||||
foreach($chapterList as $oldChapterID => $chapter)
|
||||
{
|
||||
unset($chapter->id);
|
||||
$chapter->vision = 'rnd';
|
||||
$chapter->template = $newTemplateID;
|
||||
$this->dao->insert(TABLE_DOC)->data($chapter)->exec();
|
||||
$newChapterID = $this->dao->lastInsertID();
|
||||
|
||||
foreach($chapterContent[$oldChapterID] as $content)
|
||||
{
|
||||
unset($content->id);
|
||||
$content->doc = $newChapterID;
|
||||
$this->dao->insert(TABLE_DOCCONTENT)->data($content)->exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!isset($newTemplateList['all'])) $newTemplateList['all'] = array();
|
||||
if(!isset($newTemplateList['wiki'])) $newTemplateList['wiki'] = array();
|
||||
if(!isset($newTemplateList['html'])) $newTemplateList['html'] = array();
|
||||
$newTemplateList['all'][] = $newTemplateID;
|
||||
if($template->type == 'book') $newTemplateList['wiki'][] = $newTemplateID;
|
||||
if($template->type == 'html' || $template->type == 'markdown') $newTemplateList['html'][] = $newTemplateID;
|
||||
}
|
||||
|
||||
return $newTemplateList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加内置文档模板。
|
||||
* Add the built-in doc template.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function addBuiltInDocTemplateByType()
|
||||
{
|
||||
$builtInDocTemplate = $this->dao->select('*')->from(TABLE_DOC)->where('builtIn')->eq('1')->fetchAll();
|
||||
if(!empty($builtInDocTemplate)) return;
|
||||
|
||||
$rndScopeMaps = $this->loadModel('setting')->getItem('vision=rnd&owner=system&module=doc&key=builtInScopeMaps');
|
||||
$rndScopeMaps = json_decode($rndScopeMaps, true);
|
||||
$projectScopeID = zget($rndScopeMaps, 'project', 0);
|
||||
$modulePairs = $this->dao->select('short,id')->from(TABLE_MODULE)->where('root')->eq($projectScopeID)->andWhere('type')->eq('docTemplate')->fetchPairs('short');
|
||||
|
||||
$builtInTemplate = new stdClass();
|
||||
$builtInTemplate->lib = $projectScopeID;
|
||||
$builtInTemplate->type = 'text';
|
||||
$builtInTemplate->addedBy = 'system';
|
||||
$builtInTemplate->addedDate = helper::now();
|
||||
$builtInTemplate->builtIn = '1';
|
||||
|
||||
$templateContent = new stdClass();
|
||||
$templateContent->type = 'doc';
|
||||
$templateContent->version = 1;
|
||||
$templateContent->addedBy = 'system';
|
||||
$templateContent->addedDate = helper::now();
|
||||
|
||||
$this->loadModel('upgrade');
|
||||
$this->app->loadLang('baseline');
|
||||
foreach(array('PP', 'SRS', 'HLDS', 'DDS', 'ADS', 'DBDS', 'ITTC', 'STTC') as $type)
|
||||
{
|
||||
/* 创建与分类同名的内置文档模板。*/
|
||||
/* Add the doc template with the same name as the type. */
|
||||
$builtInTemplate->module = zget($modulePairs, $type, 0);
|
||||
$builtInTemplate->title = $this->lang->baseline->objectList[$type];
|
||||
$builtInTemplate->templateType = $type;
|
||||
$this->dao->insert(TABLE_DOC)->data($builtInTemplate)->exec();
|
||||
$templateID = $this->dao->lastInsertID();
|
||||
|
||||
/* 获取模板的动态区块。*/
|
||||
/* Get the block of doc template. */
|
||||
$templateBlock = $this->upgrade->getTemplateBlock($templateID);
|
||||
$templateHtml = empty($templateBlock) ? '' : "<div class='tml-zentaolist' data-title='{$templateBlock['blockTitle']}' data-export-url='{$templateBlock['exportUrl']}' data-fetcher='{$templateBlock['fetcherUrl']}'></div>";
|
||||
|
||||
/* 添加模板内容。*/
|
||||
/* Add the content of doc template. */
|
||||
$templateContent->content = $templateHtml;
|
||||
$templateContent->rawContent = json_encode(array('$migrate' => 'html', '$data' => $templateHtml));
|
||||
$templateContent->doc = $templateID;
|
||||
$templateContent->title = $builtInTemplate->title;
|
||||
$this->dao->insert(TABLE_DOCCONTENT)->data($templateContent)->exec();
|
||||
}
|
||||
|
||||
/* 记录文档模板的更新时间。*/
|
||||
/* Record the time of upgrade doc template. */
|
||||
$this->setting->setItem("system.doc.upgradeTime", helper::now());
|
||||
}
|
||||
}
|
||||
|
||||
+14
-1
@@ -266,12 +266,25 @@ class docTao extends docModel
|
||||
*
|
||||
* @param int $docID
|
||||
* @param object $doc
|
||||
* @param bool $basicInfoChanged
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function doUpdateDoc(int $docID, object $doc)
|
||||
public function doUpdateDoc(int $docID, object $doc, $basicInfoChanged = false)
|
||||
{
|
||||
$this->dao->update(TABLE_DOC)->data($doc)->autoCheck()->where('id')->eq($docID)->exec();
|
||||
|
||||
if(empty($doc->parent) && $basicInfoChanged)
|
||||
{
|
||||
$childData = new stdclass();
|
||||
$childData->module = $doc->module;
|
||||
$childData->lib = $doc->lib;
|
||||
$childData->acl = $doc->acl;
|
||||
if(isset($doc->groups)) $childData->groups = $doc->groups;
|
||||
if(isset($doc->users)) $childData->users = $doc->users;
|
||||
|
||||
$this->dao->update(TABLE_DOC)->data($childData)->where("FIND_IN_SET('{$docID}', `path`)")->exec();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,7 @@ class docTest
|
||||
*/
|
||||
public function createLibTest(array $param, string $type = '', string $libType = ''): object|array
|
||||
{
|
||||
$createFields = array('type' => '', 'name' => '', 'acl' => '', 'product' => 0, 'project' => 0, 'execution' => 0);
|
||||
$createFields = array('type' => '', 'name' => '', 'acl' => '', 'product' => 0, 'project' => 0, 'execution' => 0, 'parent' => 0);
|
||||
|
||||
$lib = new stdClass();
|
||||
foreach($createFields as $field => $defaultValue) $lib->{$field} = $defaultValue;
|
||||
@@ -223,7 +223,7 @@ class docTest
|
||||
*/
|
||||
public function updateTest(int $docID, array $param): array
|
||||
{
|
||||
$createFields = array('lib' => 0, 'module' => 0, 'title' => '', 'keywords' => '', 'type' => 'text', 'content' => '', 'contentType' => 'html', 'acl' => 'private', 'status' => 'normal');
|
||||
$createFields = array('lib' => 0, 'module' => 0, 'title' => '', 'keywords' => '', 'type' => 'text', 'content' => '', 'contentType' => 'html', 'acl' => 'private', 'status' => 'normal', 'editedBy' => 'admin', 'rawContent' => '');
|
||||
|
||||
$doc = new stdclass();
|
||||
foreach($createFields as $field => $defaultValue) $doc->{$field} = $defaultValue;
|
||||
@@ -1364,11 +1364,12 @@ class docTest
|
||||
$pager = new pager(0, $recPerPage, $pageID);
|
||||
|
||||
$actions = $this->objectModel->getDynamic($pager);
|
||||
$idList = '';
|
||||
foreach($actions as $action) $idList .= $action->id . ';';
|
||||
$idList = array();
|
||||
foreach($actions as $action) $idList []= $action->id;
|
||||
sort($idList);
|
||||
|
||||
if(dao::isError()) return dao::getError();
|
||||
return $idList;
|
||||
return implode(';', $idList);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1413,9 +1414,9 @@ class docTest
|
||||
* @param int $order
|
||||
* @param string $type api|doc
|
||||
* @access public
|
||||
* @return int|false
|
||||
* @return int|false|string
|
||||
*/
|
||||
public function updateOrderTest(int $catalogID, int $order, string $type = 'doc'): int|false
|
||||
public function updateOrderTest(int $catalogID, int $order, string $type = 'doc'): int|false|string
|
||||
{
|
||||
$this->objectModel->updateOrder($catalogID, $order, $type);
|
||||
|
||||
@@ -1441,6 +1442,167 @@ class docTest
|
||||
return $this->objectModel->dao->select('*')->from(TABLE_DOCCONTENT)->where('doc')->eq($docID)->andWhere('version')->eq($doc->version + 1)->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文档库的文档列表。
|
||||
* Get doc list.
|
||||
*
|
||||
* @param array $libs
|
||||
* @param string $spaceType
|
||||
* @param int $excludeID
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getDocsOfLibsTest(array $libs, string $spaceType, int $excludeID = 0): array
|
||||
{
|
||||
$docs = $this->objectModel->getDocsOfLibs($libs, $spaceType, $excludeID);
|
||||
if(dao::isError()) return dao::getError();
|
||||
return $docs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文档模板列表。
|
||||
* Get doc template list.
|
||||
*
|
||||
* @param int $libID
|
||||
* @param string $type
|
||||
* @param string $orderBy
|
||||
* @param string $searchName
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getDocTemplateListTest(int $libID = 0, string $type = 'all', string $orderBy = 'id_desc', string $searchName = ''): array
|
||||
{
|
||||
$templates = $this->objectModel->getDocTemplateList($libID, $type, $orderBy, null, $searchName);
|
||||
if(dao::isError()) return dao::getError();
|
||||
return $templates;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加文档模板类型。
|
||||
* Add the type of template lis.
|
||||
*
|
||||
* @param array $moduleData
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function addTemplateTypeTest(array $moduleData)
|
||||
{
|
||||
$module = new stdClass();
|
||||
foreach($moduleData as $field => $value) $module->{$field} = $value;
|
||||
$moduleID = $this->objectModel->addTemplateType($module);
|
||||
return $this->objectModel->dao->select('*')->from(TABLE_MODULE)->where('id')->eq($moduleID)->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个模板类型下的所有模板。
|
||||
* Get template list by type.
|
||||
*
|
||||
* @param int|null $type
|
||||
* @param string $status
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getTemplatesByTypeTest($type = null, $status = 'all')
|
||||
{
|
||||
$templates = $this->objectModel->getTemplatesByType($type, $status);
|
||||
if(dao::isError()) return dao::getError();
|
||||
return $templates;
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试获取模板类型。
|
||||
* Test get template modules.
|
||||
*
|
||||
* @param string $root
|
||||
* @param string $grade
|
||||
* @access public
|
||||
* @return array|bool
|
||||
*/
|
||||
public function getTemplateModulesTest($root = 'all', $grade = 'all')
|
||||
{
|
||||
$templateModules = $this->objectModel->getTemplateModules($root, $grade);
|
||||
if(dao::isError()) return dao::getError();
|
||||
return $templateModules;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取范围下最近编辑的模板。
|
||||
* Get templates of scope.
|
||||
*
|
||||
* @param int $scopeID
|
||||
* @param int $limit
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function getHotTemplatesTest($scopeID = 0, $limit = 0)
|
||||
{
|
||||
$templates = $this->objectModel->getHotTemplates($scopeID, $limit);
|
||||
if(dao::isError()) return dao::getError();
|
||||
return $templates;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有范围下的模板。
|
||||
* Get templats of all scopes.
|
||||
*
|
||||
* @param int $scopeID
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getScopeTemplatesTest(int $scopeID = 0)
|
||||
{
|
||||
$templates = $this->objectModel->getScopeTemplates(array($scopeID));
|
||||
if(dao::isError()) return dao::getError();
|
||||
return $templates;
|
||||
}
|
||||
|
||||
/**
|
||||
* 升级旧的文档模板。
|
||||
* Upgrade old template.
|
||||
*
|
||||
* @param int $templateID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function upgradeTemplateLibAndModuleTest(int $templateID)
|
||||
{
|
||||
$this->objectModel->upgradeTemplateLibAndModule();
|
||||
return $this->objectModel->dao->select('*')->from(TABLE_DOC)->where('id')->eq($templateID)->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 升级用户自定义模板类型数据。
|
||||
* Upgrade custom doc template types.
|
||||
*
|
||||
* @param int $moduleID
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function upgradeTemplateTypesTest(int $moduleID, string $name)
|
||||
{
|
||||
if($this->objectModel->config->edition != 'ipd') return true;
|
||||
|
||||
$this->objectModel->upgradeTemplateTypes();
|
||||
$moduleName = $this->objectModel->dao->select('name')->from(TABLE_MODULE)->where('id')->eq($moduleID)->fetch('name');
|
||||
return $moduleName == $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch move document.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $docIdList
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function batchMoveDocTest(array $data, array $docIdList)
|
||||
{
|
||||
$docData = new stdClass();
|
||||
foreach($data as $field => $value) $docData->{$field} = $value;
|
||||
$this->objectModel->batchMoveDoc($docData, $docIdList);
|
||||
return $this->objectModel->dao->select('*')->from(TABLE_DOC)->where('id')->in($docIdList)->fetchAll('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文档。
|
||||
* Delete document.
|
||||
@@ -1523,4 +1685,216 @@ class docTest
|
||||
$this->objectModel->setDocPrivError($docID, $objectID, $type);
|
||||
return $_SESSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文档模板是否已升级。
|
||||
* Check if doc template has been upgraded
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function checkIsTemplateUpgradedTest()
|
||||
{
|
||||
return $this->objectModel->checkIsTemplateUpgraded();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除一个文档模板。
|
||||
* Delete a doc template.
|
||||
*
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteTemplateTest(int $id)
|
||||
{
|
||||
$result = $this->objectModel->deleteTemplate($id);
|
||||
if(!$result) return false;
|
||||
|
||||
$deleted = $this->objectModel->dao->select('deleted')->from(TABLE_DOC)->where('id')->eq($id)->fetch('deleted');
|
||||
return $deleted == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取范围数据。
|
||||
* Get scope items.
|
||||
*
|
||||
* @param array scopeList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getScopeItemsTest(array $scopeList = array())
|
||||
{
|
||||
$scopes = array();
|
||||
foreach($scopeList as $scopeID => $scopeName)
|
||||
{
|
||||
$data = new stdClass();
|
||||
$data->id = $scopeID;
|
||||
$data->name = $scopeName;
|
||||
$scopes[] = $data;
|
||||
}
|
||||
$result = $this->objectModel->getScopeItems($scopes);
|
||||
if(!$result) return false;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建模板类型数据。
|
||||
* Build data of template type module.
|
||||
*
|
||||
* @param int $scope
|
||||
* @param int $parent
|
||||
* @param string $name
|
||||
* @param string $code
|
||||
* @param int $grade
|
||||
* @param string $path
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function buildTemplateModuleTest($scope, $parent, $name, $code, $grade)
|
||||
{
|
||||
$result = $this->objectModel->buildTemplateModule($scope, $parent, $name, $code, $grade);
|
||||
if(!$result) return false;
|
||||
return $result ?: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新文档。
|
||||
* Update document.
|
||||
*
|
||||
* @param int $docID
|
||||
* @param array $doc
|
||||
* @param bool $basicInfoChanged
|
||||
* @access protected
|
||||
* @return object
|
||||
*/
|
||||
public function doUpdateDocTest(int $docID, array $doc)
|
||||
{
|
||||
$docData = new stdClass();
|
||||
foreach($doc as $field => $value) $docData->{$field} = $value;
|
||||
$this->objectModel->doUpdateDoc($docID, $docData);
|
||||
return $this->objectModel->dao->select('*')->from(TABLE_DOC)->where('id')->eq($docID)->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新模板范围。
|
||||
* Update the scope of template.
|
||||
*
|
||||
* @param array scopeList
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function updateTemplateScopesTest(array $scopeList = array())
|
||||
{
|
||||
$this->objectModel->updateTemplateScopes($scopeList);
|
||||
return $this->objectModel->dao->select('id,name')->from(TABLE_DOCLIB)->where('id')->in(array_keys($scopeList))->fetchPairs('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入模板范围。
|
||||
* Insert the scope of template.
|
||||
*
|
||||
* @param array scopeList
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function insertTemplateScopesTest(array $scopeList = array())
|
||||
{
|
||||
$this->objectModel->insertTemplateScopes($scopeList);
|
||||
return $this->objectModel->dao->select('*')->from(TABLE_DOCLIB)->fetchAll('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除模板范围。
|
||||
* Delete the scope of template.
|
||||
*
|
||||
* @param int scopeID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function deleteTemplateScopesTest(int $scopeID = 0)
|
||||
{
|
||||
$this->objectModel->deleteTemplateScopes(array($scopeID));
|
||||
return $this->objectModel->dao->select('deleted')->from(TABLE_DOCLIB)->where('id')->eq($scopeID)->fetch('deleted');
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加内置的模板范围。
|
||||
* Add built in scopes.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function addBuiltInScopesTest()
|
||||
{
|
||||
$this->objectModel->addBuiltInScopes();
|
||||
return $this->objectModel->dao->select('*')->from(TABLE_DOCLIB)->fetchAll('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制模板数据到OR界面。
|
||||
* Copy template to OR page.
|
||||
*
|
||||
* @param array scopeIdList
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function copyTemplateTest(array $templateIdList = array())
|
||||
{
|
||||
return $this->objectModel->copyTemplate($templateIdList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加内置文档模板。
|
||||
* Add the built-in doc template.
|
||||
*
|
||||
* @param int templateID
|
||||
* @param array typeList
|
||||
* @param string name
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function addBuiltInDocTemplateByTypeTest(int $templateID, array $typeList, string $name)
|
||||
{
|
||||
if($this->objectModel->config->edition != 'ipd') return true;
|
||||
|
||||
$this->objectModel->addBuiltInScopes();
|
||||
$this->objectModel->upgradeTemplateTypes();
|
||||
$this->objectModel->addBuiltInDocTemplateByType($typeList);
|
||||
$templateName = $this->objectModel->dao->select('title')->from(TABLE_DOC)->where('id')->eq($templateID)->orderBy('id_desc')->fetch('title');
|
||||
return $templateName == $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置文档的权限。
|
||||
* Set document priviledge test.
|
||||
*
|
||||
* @param object $doc
|
||||
* @param string $spaceType
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function setDocPrivTest(object $doc, string $spaceType = 'mine'): object
|
||||
{
|
||||
$doc = $this->objectModel->setDocPriv($doc, $spaceType);
|
||||
|
||||
$doc->readable = $doc->readable ? '1' : '0';
|
||||
$doc->editable = $doc->editable ? '1' : '0';
|
||||
|
||||
return $doc;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文档内容。
|
||||
* Get document content test.
|
||||
*
|
||||
* @param int $docID
|
||||
* @param int $version
|
||||
* @access public
|
||||
* @return object|null
|
||||
*/
|
||||
public function getContentTest(int $docID, int $version): object|null
|
||||
{
|
||||
return $this->objectModel->getContent($docID, $version);
|
||||
}
|
||||
}
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
|
||||
title=测试 docModel->addBuiltInDocTemplateByType();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 添加内置项目计划模板 @1
|
||||
- 添加内置软件需求说明书模板 @1
|
||||
- 添加内置概要设计说明书模板 @1
|
||||
- 添加内置详细设计说明书模板 @1
|
||||
- 添加内置接口设计文档模板 @1
|
||||
- 添加内置数据库设计文档模板 @1
|
||||
- 添加内置集成测试用例模板 @1
|
||||
- 添加内置系统测试用例模板 @1
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php';
|
||||
|
||||
zenData('user')->gen(5);
|
||||
su('admin');
|
||||
|
||||
zenData('doc')->gen(0);
|
||||
zenData('doccontent')->gen(0);
|
||||
zenData('doclib')->gen(0);
|
||||
zenData('module')->gen(0);
|
||||
zenData('lang')->gen(0);
|
||||
$docTester = new docTest();
|
||||
r($docTester->addBuiltInDocTemplateByTypeTest(1, array('PP'), '项目计划')) && p() && e('1'); // 添加内置项目计划模板
|
||||
r($docTester->addBuiltInDocTemplateByTypeTest(2, array('SRS'), '软件需求规格说明书')) && p() && e('1'); // 添加内置软件需求说明书模板
|
||||
r($docTester->addBuiltInDocTemplateByTypeTest(3, array('HLDS'), '概要设计说明书')) && p() && e('1'); // 添加内置概要设计说明书模板
|
||||
r($docTester->addBuiltInDocTemplateByTypeTest(4, array('DDS'), '详细设计说明书')) && p() && e('1'); // 添加内置详细设计说明书模板
|
||||
r($docTester->addBuiltInDocTemplateByTypeTest(5, array('ADS'), '接口设计文档')) && p() && e('1'); // 添加内置接口设计文档模板
|
||||
r($docTester->addBuiltInDocTemplateByTypeTest(6, array('DBDS'), '数据库设计文档')) && p() && e('1'); // 添加内置数据库设计文档模板
|
||||
r($docTester->addBuiltInDocTemplateByTypeTest(7, array('ITTC'), '集成测试用例')) && p() && e('1'); // 添加内置集成测试用例模板
|
||||
r($docTester->addBuiltInDocTemplateByTypeTest(8, array('STTC'), '系统测试用例')) && p() && e('1'); // 添加内置系统测试用例模板
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
|
||||
title=测试 docModel->addBuiltInScopes();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 测试添加研发界面内置产品范围
|
||||
- 第1条的name属性 @产品
|
||||
- 第1条的type属性 @template
|
||||
- 第1条的main属性 @1
|
||||
- 第1条的vision属性 @rnd
|
||||
- 测试添加研发界面内置项目范围
|
||||
- 第2条的name属性 @项目
|
||||
- 第2条的type属性 @template
|
||||
- 第2条的main属性 @1
|
||||
- 第2条的vision属性 @rnd
|
||||
- 测试添加OR界面内置市场范围
|
||||
- 第5条的name属性 @市场
|
||||
- 第5条的type属性 @template
|
||||
- 第5条的main属性 @1
|
||||
- 第5条的vision属性 @or
|
||||
- 测试添加OR界面内置产品范围
|
||||
- 第6条的name属性 @产品
|
||||
- 第6条的type属性 @template
|
||||
- 第6条的main属性 @1
|
||||
- 第6条的vision属性 @or
|
||||
- 测试添加运营界面内置项目范围
|
||||
- 第8条的name属性 @项目
|
||||
- 第8条的type属性 @template
|
||||
- 第8条的main属性 @1
|
||||
- 第8条的vision属性 @lite
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php';
|
||||
|
||||
zenData('user')->gen(5);
|
||||
su('admin');
|
||||
|
||||
zenData('doclib')->gen(0);
|
||||
$docTester = new docTest();
|
||||
r($docTester->addBuiltInScopesTest()) && p('1:name,type,main,vision') && e('产品,template,1,rnd'); // 测试添加研发界面内置产品范围
|
||||
r($docTester->addBuiltInScopesTest()) && p('2:name,type,main,vision') && e('项目,template,1,rnd'); // 测试添加研发界面内置项目范围
|
||||
r($docTester->addBuiltInScopesTest()) && p('5:name,type,main,vision') && e('市场,template,1,or'); // 测试添加OR界面内置市场范围
|
||||
r($docTester->addBuiltInScopesTest()) && p('6:name,type,main,vision') && e('产品,template,1,or'); // 测试添加OR界面内置产品范围
|
||||
r($docTester->addBuiltInScopesTest()) && p('8:name,type,main,vision') && e('项目,template,1,lite'); // 测试添加运营界面内置项目范围
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
|
||||
title=测试 docModel->addTemplateType();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 添加产品模板类型
|
||||
- 属性short @custom1
|
||||
- 属性path @,1,
|
||||
- 添加产品子模板类型
|
||||
- 属性short @custom2
|
||||
- 属性path @,1,2,
|
||||
- 添加项目模板类型
|
||||
- 属性short @custom3
|
||||
- 属性path @,3,
|
||||
- 添加项目子模板类型
|
||||
- 属性short @custom4
|
||||
- 属性path @,3,4,
|
||||
- 添加执行模板类型
|
||||
- 属性short @custom5
|
||||
- 属性path @,5,
|
||||
- 添加执行子模板类型
|
||||
- 属性short @custom6
|
||||
- 属性path @,5,6,
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php';
|
||||
|
||||
zenData('module')->gen(0);
|
||||
zenData('user')->gen(5);
|
||||
su('admin');
|
||||
|
||||
$productModule = array('name' => '产品计划', 'root' => 1, 'grade' => 1, 'order' => 10, 'type' => 'doctemplate');
|
||||
$productSubModule = array('name' => '软件产品计划', 'root' => 1, 'grade' => 2, 'order' => 20, 'type' => 'doctemplate', 'parent' => 1);
|
||||
$projectModule = array('name' => '项目计划', 'root' => 2, 'grade' => 1, 'order' => 10, 'type' => 'doctemplate');
|
||||
$projectSubModule = array('name' => '质量保证计划', 'root' => 2, 'grade' => 2, 'order' => 20, 'type' => 'doctemplate', 'parent' => 3);
|
||||
$executionModule = array('name' => '开发计划', 'root' => 3, 'grade' => 1, 'order' => 10, 'type' => 'doctemplate');
|
||||
$executionSubModule = array('name' => '软件需求说明书', 'root' => 3, 'grade' => 2, 'order' => 20, 'type' => 'doctemplate', 'parent' => 5);
|
||||
|
||||
$docTester = new docTest();
|
||||
r($docTester->addTemplateTypeTest($productModule)) && p('short|path', '|') && e('custom1|,1,'); // 添加产品模板类型
|
||||
r($docTester->addTemplateTypeTest($productSubModule)) && p('short|path', '|') && e('custom2|,1,2,'); // 添加产品子模板类型
|
||||
r($docTester->addTemplateTypeTest($projectModule)) && p('short|path', '|') && e('custom3|,3,'); // 添加项目模板类型
|
||||
r($docTester->addTemplateTypeTest($projectSubModule)) && p('short|path', '|') && e('custom4|,3,4,'); // 添加项目子模板类型
|
||||
r($docTester->addTemplateTypeTest($executionModule)) && p('short|path', '|') && e('custom5|,5,'); // 添加执行模板类型
|
||||
r($docTester->addTemplateTypeTest($executionSubModule)) && p('short|path', '|') && e('custom6|,5,6,'); // 添加执行子模板类型
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
|
||||
title=测试 docModel->batchMoveDoc();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 测试ID为空时 @0
|
||||
- 测试文档1文档2的字段
|
||||
- 第1条的lib属性 @100
|
||||
- 第1条的module属性 @99
|
||||
- 第2条的lib属性 @100
|
||||
- 第2条的module属性 @99
|
||||
- 测试文档3文档4的字段
|
||||
- 第3条的lib属性 @100
|
||||
- 第3条的module属性 @99
|
||||
- 第4条的lib属性 @100
|
||||
- 第4条的module属性 @99
|
||||
- 测试文档5文档6的字段
|
||||
- 第5条的lib属性 @100
|
||||
- 第5条的module属性 @99
|
||||
- 第6条的lib属性 @100
|
||||
- 第6条的module属性 @99
|
||||
- 测试文档7文档8的字段
|
||||
- 第7条的lib属性 @100
|
||||
- 第7条的module属性 @99
|
||||
- 第8条的lib属性 @100
|
||||
- 第8条的module属性 @99
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php';
|
||||
|
||||
zenData('doc')->loadYaml('doc')->gen(20);
|
||||
zenData('user')->gen(5);
|
||||
su('admin');
|
||||
|
||||
$docData = array('lib' => 100, 'module' => 99);
|
||||
$docIdList = array(array(), array(1, 2), array(3, 4), array(5, 6), array(7, 8));
|
||||
|
||||
$docTester = new docTest();
|
||||
r($docTester->batchMoveDocTest($docData, $docIdList[0])) && p('') && e('0'); // 测试ID为空时
|
||||
r($docTester->batchMoveDocTest($docData, $docIdList[1])) && p('1:lib,module;2:lib,module') && e('100,99;100,99'); // 测试文档1文档2的字段
|
||||
r($docTester->batchMoveDocTest($docData, $docIdList[2])) && p('3:lib,module;4:lib,module') && e('100,99;100,99'); // 测试文档3文档4的字段
|
||||
r($docTester->batchMoveDocTest($docData, $docIdList[3])) && p('5:lib,module;6:lib,module') && e('100,99;100,99'); // 测试文档5文档6的字段
|
||||
r($docTester->batchMoveDocTest($docData, $docIdList[4])) && p('7:lib,module;8:lib,module') && e('100,99;100,99'); // 测试文档7文档8的字段
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
|
||||
title=测试 docModel->buildTemplateModule();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 创建模板类型对象
|
||||
- 属性root @1
|
||||
- 属性parent @1
|
||||
- 属性name @模板名称
|
||||
- 属性short @ShortName
|
||||
- 属性grade @1
|
||||
- 创建模板类型对象
|
||||
- 属性root @2
|
||||
- 属性parent @1
|
||||
- 属性name @模板名称
|
||||
- 属性short @ShortName
|
||||
- 属性grade @1
|
||||
- 创建模板类型对象
|
||||
- 属性root @2
|
||||
- 属性parent @2
|
||||
- 属性name @模板名称
|
||||
- 属性short @ShortName
|
||||
- 属性grade @1
|
||||
- 创建模板类型对象
|
||||
- 属性root @1
|
||||
- 属性parent @2
|
||||
- 属性name @模板名称
|
||||
- 属性short @ShortName
|
||||
- 属性grade @1
|
||||
- 创建模板类型对象
|
||||
- 属性root @2
|
||||
- 属性parent @2
|
||||
- 属性name @模板名称
|
||||
- 属性short @ShortName
|
||||
- 属性grade @2
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php';
|
||||
|
||||
zenData('user')->gen(5);
|
||||
su('admin');
|
||||
|
||||
$scopeList = array(1, 2);
|
||||
$parentList = array(1, 2);
|
||||
$nameList = array('模板名称');
|
||||
$codeList = array('ShortName');
|
||||
$gradeList = array(1, 2);
|
||||
|
||||
$docTester = new docTest();
|
||||
r($docTester->buildTemplateModuleTest($scopeList[0], $parentList[0], $nameList[0], $codeList[0], $gradeList[0])) && p('root,parent,name,short,grade') && e('1,1,模板名称,ShortName,1'); // 创建模板类型对象
|
||||
r($docTester->buildTemplateModuleTest($scopeList[1], $parentList[0], $nameList[0], $codeList[0], $gradeList[0])) && p('root,parent,name,short,grade') && e('2,1,模板名称,ShortName,1'); // 创建模板类型对象
|
||||
r($docTester->buildTemplateModuleTest($scopeList[1], $parentList[1], $nameList[0], $codeList[0], $gradeList[0])) && p('root,parent,name,short,grade') && e('2,2,模板名称,ShortName,1'); // 创建模板类型对象
|
||||
r($docTester->buildTemplateModuleTest($scopeList[0], $parentList[1], $nameList[0], $codeList[0], $gradeList[0])) && p('root,parent,name,short,grade') && e('1,2,模板名称,ShortName,1'); // 创建模板类型对象
|
||||
r($docTester->buildTemplateModuleTest($scopeList[1], $parentList[1], $nameList[0], $codeList[0], $gradeList[1])) && p('root,parent,name,short,grade') && e('2,2,模板名称,ShortName,2'); // 创建模板类型对象
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
|
||||
title=测试 docModel->checkIsTemplateUpgraded();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 检查文档模板已升级 @1
|
||||
- 检查文档模板已升级 @1
|
||||
- 检查文档模板已升级 @1
|
||||
- 检查文档模板未升级 @0
|
||||
- 检查文档模板未升级 @0
|
||||
- 检查文档模板未升级 @0
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php';
|
||||
|
||||
zenData('module')->loadYaml('templatemodule')->gen(10);
|
||||
zenData('user')->gen(5);
|
||||
su('admin');
|
||||
|
||||
$docTester = new docTest();
|
||||
r($docTester->checkIsTemplateUpgradedTest()) && p('') && e('1'); // 检查文档模板已升级
|
||||
r($docTester->checkIsTemplateUpgradedTest()) && p('') && e('1'); // 检查文档模板已升级
|
||||
r($docTester->checkIsTemplateUpgradedTest()) && p('') && e('1'); // 检查文档模板已升级
|
||||
|
||||
zenData('module')->gen(0);
|
||||
r($docTester->checkIsTemplateUpgradedTest()) && p('') && e('0'); // 检查文档模板未升级
|
||||
r($docTester->checkIsTemplateUpgradedTest()) && p('') && e('0'); // 检查文档模板未升级
|
||||
r($docTester->checkIsTemplateUpgradedTest()) && p('') && e('0'); // 检查文档模板未升级
|
||||
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
|
||||
title=测试 docModel->copyTemplate();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 测试复制文档模板1
|
||||
- 第all条的0属性 @6
|
||||
- 第html条的0属性 @6
|
||||
- 测试复制文档模板2
|
||||
- 第all条的0属性 @7
|
||||
- 第html条的0属性 @7
|
||||
- 测试复制文档模板3
|
||||
- 第all条的0属性 @8
|
||||
- 第wiki条的0属性 @8
|
||||
- 测试复制文档模板4
|
||||
- 第all条的0属性 @9
|
||||
- 第html条的0属性 @9
|
||||
- 测试复制文档模板5
|
||||
- 第all条的0属性 @10
|
||||
- 第html条的0属性 @10
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php';
|
||||
|
||||
$scope = zenData('doclib');
|
||||
$scope->id->range('1-10');
|
||||
$scope->type->range('template');
|
||||
$scope->vision->range('rnd{4},or{3},lite{2},rnd');
|
||||
$scope->name->range('产品,项目,执行,个人,市场,产品,个人,项目,个人,自定义范围');
|
||||
$scope->main->range('1{9},0');
|
||||
|
||||
$scope->gen(10);
|
||||
$doc = zenData('doc')->loadYaml('template');
|
||||
$doc->templateType->range('custom1,custom2,custom3,custom4,custom5');
|
||||
$doc->vision->range('rnd,rnd,or,or,or');
|
||||
$doc->type->range('html,markdown,book,html,markdown');
|
||||
$doc->gen(5);
|
||||
|
||||
$module = zenData('module')->loadYaml('templatemodule');
|
||||
$module->root->range('6');
|
||||
$module->gen(5);
|
||||
|
||||
zenData('doccontent')->gen(5);
|
||||
zenData('user')->gen(5);
|
||||
su('admin');
|
||||
|
||||
$docTester = new docTest();
|
||||
r($docTester->copyTemplateTest(array(1))) && p('all:0;html:0') && e('6,6'); // 测试复制文档模板1
|
||||
r($docTester->copyTemplateTest(array(2))) && p('all:0;html:0') && e('7,7'); // 测试复制文档模板2
|
||||
r($docTester->copyTemplateTest(array(3))) && p('all:0;wiki:0') && e('8,8'); // 测试复制文档模板3
|
||||
r($docTester->copyTemplateTest(array(4))) && p('all:0;html:0') && e('9,9'); // 测试复制文档模板4
|
||||
r($docTester->copyTemplateTest(array(5))) && p('all:0;html:0') && e('10,10'); // 测试复制文档模板5
|
||||
@@ -39,16 +39,16 @@ $acl = array('open', 'custom', 'private');
|
||||
$groups = '1,2,3';
|
||||
$users = 'admin,dev1,dev10';
|
||||
|
||||
$createProductDoc = array('lib' => $libIDs[1], 'title' => '新建产品文档', 'acl' => $acl[0]);
|
||||
$createProjectDoc = array('lib' => $libIDs[2], 'title' => '新建项目文档', 'acl' => $acl[0]);
|
||||
$createExecutionDoc = array('lib' => $libIDs[3], 'title' => '新建执行文档', 'acl' => $acl[0]);
|
||||
$createCustomDoc = array('lib' => $libIDs[4], 'title' => '新建自定义文档', 'acl' => $acl[1]);
|
||||
$privateDoc = array('lib' => $libIDs[4], 'title' => '新建私有文档', 'acl' => $acl[2]);
|
||||
$customDoc = array('lib' => $libIDs[5], 'title' => '新建自定义文档', 'acl' => $acl[1], 'groups' => $groups, 'users' => $users);
|
||||
$mineDoc = array('lib' => $libIDs[3], 'title' => '新建我的文档', 'acl' => $acl[0]);
|
||||
$draftDoc = array('lib' => $libIDs[3], 'title' => '新建我的草稿文档', 'acl' => $acl[0], 'status' => 'draft');
|
||||
$noLib = array('lib' => $libIDs[0], 'title' => '无文档库', 'acl' => $acl[0]);
|
||||
$noTitle = array('lib' => $libIDs[1], 'title' => '', 'acl' => $acl[0]);
|
||||
$createProductDoc = array('lib' => $libIDs[1], 'title' => '新建产品文档', 'acl' => $acl[0], 'parent' => 0);
|
||||
$createProjectDoc = array('lib' => $libIDs[2], 'title' => '新建项目文档', 'acl' => $acl[0], 'parent' => 0);
|
||||
$createExecutionDoc = array('lib' => $libIDs[3], 'title' => '新建执行文档', 'acl' => $acl[0], 'parent' => 0);
|
||||
$createCustomDoc = array('lib' => $libIDs[4], 'title' => '新建自定义文档', 'acl' => $acl[1], 'parent' => 0);
|
||||
$privateDoc = array('lib' => $libIDs[4], 'title' => '新建私有文档', 'acl' => $acl[2], 'parent' => 0);
|
||||
$customDoc = array('lib' => $libIDs[5], 'title' => '新建自定义文档', 'acl' => $acl[1], 'groups' => $groups, 'users' => $users, 'parent' => 0);
|
||||
$mineDoc = array('lib' => $libIDs[3], 'title' => '新建我的文档', 'acl' => $acl[0], 'parent' => 0);
|
||||
$draftDoc = array('lib' => $libIDs[3], 'title' => '新建我的草稿文档', 'acl' => $acl[0], 'status' => 'draft', 'parent' => 0);
|
||||
$noLib = array('lib' => $libIDs[0], 'title' => '无文档库', 'acl' => $acl[0], 'parent' => 0);
|
||||
$noTitle = array('lib' => $libIDs[1], 'title' => '', 'acl' => $acl[0], 'parent' => 0);
|
||||
|
||||
$docTester = new docTest();
|
||||
r($docTester->createTest($createProductDoc)) && p('1:title') && e('新建产品文档'); // 创建产品文档
|
||||
|
||||
@@ -44,6 +44,7 @@ cid=1
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php';
|
||||
|
||||
zenData('project')->loadYaml('execution')->gen(100);
|
||||
zenData('user')->gen(5);
|
||||
su('admin');
|
||||
|
||||
|
||||
@@ -9,9 +9,11 @@ cid=1
|
||||
- 测试正常数据属性1 @1
|
||||
- 测试有不存在的数据属性1 @1
|
||||
- 测试不存在的数据 @0
|
||||
- 测试异常数据 @0
|
||||
|
||||
*/
|
||||
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php';
|
||||
|
||||
@@ -27,9 +29,11 @@ $docIdList[] = array();
|
||||
$docIdList[] = range(1, 5);
|
||||
$docIdList[] = array(1, 2, 100, 101);
|
||||
$docIdList[] = range(100, 105);
|
||||
$docIdList[] = array(999);
|
||||
|
||||
$docTester = new docTest();
|
||||
r($docTester->deleteFilesTest($docIdList[0])) && p() && e('0'); // 测试空数据
|
||||
r($docTester->deleteFilesTest($docIdList[1])) && p('1') && e('1'); // 测试正常数据
|
||||
r($docTester->deleteFilesTest($docIdList[2])) && p('1') && e('1'); // 测试有不存在的数据
|
||||
r($docTester->deleteFilesTest($docIdList[3])) && p() && e('0'); // 测试不存在的数据
|
||||
r($docTester->deleteFilesTest($docIdList[4])) && p() && e('0'); // 测试异常数据
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
|
||||
title=测试 docModel->deleteTemplate();
|
||||
cid=1
|
||||
|
||||
- 测试删除ID为0的模板 @0
|
||||
- 测试删除ID为1的模板 @1
|
||||
- 测试删除ID为2的模板 @1
|
||||
- 测试删除ID为3的模板 @1
|
||||
- 测试删除ID不存在的模板 @0
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php';
|
||||
|
||||
zenData('doc')->loadYaml('template')->gen(10);
|
||||
zenData('user')->gen(5);
|
||||
su('admin');
|
||||
|
||||
$templateIdList = array(0, 1, 2, 3, 11);
|
||||
|
||||
$docTester = new docTest();
|
||||
r($docTester->deleteTemplateTest($templateIdList[0])) && p() && e('0'); // 测试删除ID为0的模板
|
||||
r($docTester->deleteTemplateTest($templateIdList[1])) && p() && e('1'); // 测试删除ID为1的模板
|
||||
r($docTester->deleteTemplateTest($templateIdList[2])) && p() && e('1'); // 测试删除ID为2的模板
|
||||
r($docTester->deleteTemplateTest($templateIdList[3])) && p() && e('1'); // 测试删除ID为3的模板
|
||||
r($docTester->deleteTemplateTest($templateIdList[4])) && p() && e('0'); // 测试删除ID不存在的模板
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user