Merge branch 'release/21.7.1' into feature/doctemplate

This commit is contained in:
xieqiyu
2025-05-19 17:10:17 +08:00
238 changed files with 11017 additions and 1167 deletions
+2 -2
View File
@@ -23,7 +23,7 @@ spec:
container:
image: hub.zentao.net/ci/git:2.45.2
script:
- git diff --name-only --diff-filter=d ${GITFOX_COMMIT_AFTER}${GITFOX_COMMIT_BEFORE} | tee .changes
- git diff --name-only --diff-filter=d ${GITFOX_COMMIT_AFTER} ${GITFOX_COMMIT_BEFORE} | tee .changes
- |
cat > sonar-project.properties <<EOL
sonar.projectKey=$(echo $CI_REPO_NAME-$GITFOX_COMMIT_AUTHOR | tr '/' ':')
@@ -69,7 +69,7 @@ spec:
content: |-
代码库: {{ .GITFOX_REPO_NAME }}
[分析报告]({{ .SONAR_HOST_URL }}/dashboard?branch={{ .GITFOX_BRANCH }}&id={{ .SONAR_PROJECT_KEY }})
[分析报告]({{ .SONAR_HOST_URL }}/dashboard?branch={{ .GITFOX_TARGET_BRANCH }}&id={{ .SONAR_PROJECT_KEY }})
帐号 guest/guest
url: ${GITFOX_BUILD_LINK}
+5 -4
View File
@@ -40,14 +40,14 @@ spec:
spec:
container: hub.zentao.net/ci/git:2.45.2
script:
- git clone --depth 1 -q http://${GITFOX_SERVER}/git/xuan/xuanxuan.git
- git clone -q http://${GITFOX_SERVER}/git/xuan/xuanxuan.git
xuansrc && cd xuansrc && git checkout $XUANVERSION && cd -
- git clone --depth 1 -q -b $GITFOX_BRANCH
- git clone --depth 1 -q
http://${GITFOX_SERVER}/git/${ZENTAOEXT_GIT_REPO}.git
zentaoext
- git clone --depth 1 -b $GITFOX_BRANCH
- git clone --depth 1
http://${GITFOX_SERVER}/git/zentao/zentaomax.git zentaomax
- git clone --depth 1 -b $GITFOX_BRANCH
- git clone --depth 1
http://${GITFOX_SERVER}/git/zentao/zentaoipd.git zentaoipd
- name: 版本变量设定
type: run
@@ -68,6 +68,7 @@ spec:
container: hub.zentao.net/ci/zentao-package:master
script:
- mkdir -pv ${ZENTAO_RELEASE_PATH}
- mkdir -pv /opt/build/zentaopms
- test -d $PWD/zentaoext/zentaomax && rm -rf
$PWD/zentaoext/zentaomax
- test -d $PWD/zentaoext/zentaoipd && rm -rf
+1
View File
@@ -154,6 +154,7 @@ zentaoxx:
sed -i "s/'wangwang', //g" zentaoxx/extension/xuan/im/config.php
sed -i "s/'site', //g" zentaoxx/extension/xuan/im/config.php
sed -i 's/xuanim.com/zentao.net/g' zentaoxx/extension/xuan/im/config.php
sed -i 's/xuanxuan/zentaoclient/g' zentaoxx/extension/xuan/im/config.php
sed -i "s/'reload'/inlink('browse')/g" zentaoxx/extension/xuan/client/control.php
sed -i 's/tree/dept/' zentaoxx/extension/xuan/im/model.php
sed -i 's/tree/dept/' zentaoxx/extension/xuan/im/control.php
+1 -1
View File
@@ -1 +1 @@
21.6
21.7
+1 -1
View File
@@ -84,7 +84,7 @@ class testresultsEntry extends entry
$reals[$stepID] = $step->real;
}
$this->setPost('result', $results);
$this->setPost('reals', $reals);
$this->setPost('real', $reals);
}
$control->runCase($runID, $caseID, $version);
+9 -2
View File
@@ -1,11 +1,18 @@
{
"pkg": {
"xuanxuan": {
"gitVersion": "383b4e4630ead6f25559cbe8bc0cbf1a01b71c26",
"gitVersion": "1672c352e2fb7bccaf94f30cf9341c7027c4ce89",
"version": "9.3"
},
"zentaoext": {
"gitRepo": "zentao/zentaoext"
"gitRepo": "zentao/zentaoext",
"gitVersion": "patch/11.7"
},
"zentaomax": {
"gitVersion": "patch/6.7"
},
"zentaoipd": {
"gitVersion": "patch/3.7"
},
"devops": {
"gitRepo": "zentao/devops"
+2 -3
View File
@@ -16,7 +16,7 @@ if(!class_exists('config')){class config{}}
if(!function_exists('getWebRoot')){function getWebRoot(){}}
/* 基本设置。Basic settings. */
$config->version = '21.6'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->version = '21.7'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->liteVersion = '1.2'; // 迅捷版版本。 The version of Lite.
$config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP.
$config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time.
@@ -170,10 +170,9 @@ $config->allowedTags = '<p><span><h1><h2><h3><h4><h5><em><u><strong><br><ol><ul>
$config->accountRule = '|^[a-zA-Z0-9_]{1}[a-zA-Z0-9_\.]{1,}[a-zA-Z0-9_]{1}$|';
$config->checkVersion = true; // Auto check for new version or not.
/* Set the wide window size and timeout(ms) and duplicate interval time(s). */
/* Set the wide window size and timeout(ms). */
$config->wideSize = 1400;
$config->timeout = 30000;
$config->duplicateTime = 30;
$config->maxCount = 500;
$config->moreLinks = array();
+2
View File
@@ -429,6 +429,7 @@ define('TABLE_ACL', '`' . $config->db->prefix . 'acl`');
define('TABLE_DESIGN', '`' . $config->db->prefix . 'design`');
define('TABLE_DESIGNSPEC', '`' . $config->db->prefix . 'designspec`');
define('TABLE_DELIVERABLE', '`' . $config->db->prefix . 'deliverable`');
define('TABLE_DOCLIB', '`' . $config->db->prefix . 'doclib`');
define('TABLE_DOC', '`' . $config->db->prefix . 'doc`');
define('TABLE_DOCBLOCK', '`' . $config->db->prefix . 'docblock`');
@@ -673,6 +674,7 @@ $config->objectTables['demand'] = TABLE_DEMAND;
$config->objectTables['demandpool'] = TABLE_DEMANDPOOL;
$config->objectTables['demandspec'] = TABLE_DEMANDSPEC;
$config->objectTables['demandreview'] = TABLE_DEMANDREVIEW;
$config->objectTables['deliverable'] = TABLE_DELIVERABLE;
$config->objectTables['todo'] = TABLE_TODO;
$config->objectTables['custom'] = TABLE_LANG;
$config->objectTables['branch'] = TABLE_BRANCH;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+7
View File
@@ -0,0 +1,7 @@
ALTER TABLE `zt_task` ADD COLUMN `docs` text NULL AFTER `fromIssue`;
ALTER TABLE `zt_task` ADD COLUMN `docVersions` text NULL AFTER `docs`;
ALTER TABLE `zt_storyspec` ADD COLUMN `docs` text NULL AFTER `files`;
ALTER TABLE `zt_storyspec` ADD COLUMN `docVersions` text NULL AFTER `docs`;
ALTER TABLE `zt_design` ADD COLUMN `docs` text NULL AFTER `storyVersion`;
ALTER TABLE `zt_design` ADD COLUMN `docVersions` text NULL AFTER `docs`;
ALTER TABLE `zt_project` ADD `taskDateLimit` varchar(30) NOT NULL DEFAULT 'auto' AFTER `linkType`;
+39
View File
@@ -0,0 +1,39 @@
UPDATE `zt_workflowaction` SET `module` = 'story', `action` = 'browse' WHERE `module` = 'product' AND `action` = 'browse';
UPDATE `zt_workflowlayout` SET `module` = 'story', `action` = 'browse' WHERE `module` = 'product' AND `action` = 'browse';
UPDATE `zt_workflowaction` SET `module` = 'requirement', `action` = 'browse' WHERE `module` = 'product' AND `action` = 'requirement';
UPDATE `zt_workflowlayout` SET `module` = 'requirement', `action` = 'browse' WHERE `module` = 'product' AND `action` = 'requirement';
UPDATE `zt_workflowaction` SET `module` = 'epic', `action` = 'browse' WHERE `module` = 'product' AND `action` = 'epic';
UPDATE `zt_workflowlayout` SET `module` = 'epic', `action` = 'browse' WHERE `module` = 'product' AND `action` = 'epic';
UPDATE `zt_workflowaction` SET `module` = 'build', `action` = 'browse' WHERE `module` = 'execution' AND `action` = 'build';
UPDATE `zt_workflowlayout` SET `module` = 'build', `action` = 'browse' WHERE `module` = 'execution' AND `action` = 'build';
UPDATE `zt_workflowaction` SET `module` = 'task', `action` = 'browse' WHERE `module` = 'execution' AND `action` = 'task';
UPDATE `zt_workflowlayout` SET `module` = 'task', `action` = 'browse' WHERE `module` = 'execution' AND `action` = 'task';
ALTER TABLE `zt_relationoftasks` ADD COLUMN `project` mediumint(8) unsigned NOT NULL DEFAULT 0 AFTER `id`;
ALTER TABLE `zt_relationoftasks` MODIFY `execution` char(30) NOT NULL DEFAULT '' AFTER `project`;
UPDATE `zt_relationoftasks` SET `project` = (SELECT `project` FROM `zt_task` WHERE `id` = `zt_relationoftasks`.`task`);
CREATE TABLE IF NOT EXISTS `zt_deliverable` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`module` varchar(30) NULL,
`method` varchar(30) NULL,
`model` text NULL,
`type` enum('doc','file') NULL DEFAULT 'file',
`desc` text NULL,
`files` varchar(255) NULL,
`createdBy` varchar(30) NULL,
`createdDate` date NULL,
`lastEditedBy` varchar(30) NULL,
`lastEditedDate` date NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE `zt_workflowgroup` ADD `objectID` mediumint(8) unsigned NOT NULL DEFAULT '0' AFTER `id`;
ALTER TABLE `zt_workflowgroup` ADD COLUMN `deliverable` text NULL AFTER `editedDate`;
ALTER TABLE `zt_project` ADD COLUMN `deliverable` text NULL AFTER `maxColWidth`;
+30 -1
View File
@@ -578,6 +578,24 @@ CREATE TABLE IF NOT EXISTS `zt_screen` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- DROP TABLE IF EXISTS `zt_deliverable`;
CREATE TABLE IF NOT EXISTS `zt_deliverable` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`module` varchar(30) NULL,
`method` varchar(30) NULL,
`model` text NULL,
`type` enum('doc','file') NULL DEFAULT 'file',
`desc` text NULL,
`files` varchar(255) NULL,
`createdBy` varchar(30) NULL,
`createdDate` date NULL,
`lastEditedBy` varchar(30) NULL,
`lastEditedDate` date NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- DROP TABLE IF EXISTS `zt_dimension`;
CREATE TABLE IF NOT EXISTS `zt_dimension` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
@@ -751,6 +769,8 @@ CREATE TABLE IF NOT EXISTS `zt_design` (
`deleted` enum('0','1') NOT NULL DEFAULT '0',
`story` char(30) NOT NULL DEFAULT '',
`storyVersion` smallint(6) UNSIGNED NOT NULL DEFAULT '1',
`docs` text NULL,
`docVersions` text NULL,
`desc` mediumtext NULL,
`version` smallint(6) NOT NULL DEFAULT '0',
`type` char(30) NOT NULL DEFAULT '',
@@ -1591,9 +1611,11 @@ CREATE TABLE IF NOT EXISTS `zt_project` (
`parallel` mediumint(9) NOT NULL DEFAULT '0',
`enabled` enum('on','off') NOT NULL DEFAULT 'on',
`linkType` varchar(30) NOT NULL DEFAULT 'plan',
`taskDateLimit` varchar(30) NOT NULL DEFAULT 'auto',
`colWidth` smallint(6) NOT NULL DEFAULT '264',
`minColWidth` smallint(6) NOT NULL DEFAULT '200',
`maxColWidth` smallint(6) NOT NULL DEFAULT '384',
`deliverable` text NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
@@ -1945,6 +1967,7 @@ CREATE TABLE IF NOT EXISTS `zt_story` (
`toBug` mediumint(8) unsigned NOT NULL DEFAULT '0',
`linkStories` varchar(255) NOT NULL DEFAULT '',
`linkRequirements` varchar(255) NOT NULL DEFAULT '',
`docs` text NULL,
`twins` varchar(255) NOT NULL DEFAULT '',
`duplicateStory` mediumint(8) unsigned NOT NULL DEFAULT '0',
`version` smallint(6) NOT NULL DEFAULT '1',
@@ -2008,7 +2031,9 @@ CREATE TABLE IF NOT EXISTS `zt_storyspec` (
`title` varchar(255) NOT NULL DEFAULT '',
`spec` mediumtext NULL,
`verify` mediumtext NULL,
`files` text NULL
`files` text NULL,
`docs` text NULL,
`docVersions` text NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE UNIQUE INDEX `story` ON `zt_storyspec`(`story`,`version`);
@@ -2047,6 +2072,8 @@ CREATE TABLE IF NOT EXISTS `zt_task` (
`fromBug` mediumint(8) unsigned NOT NULL DEFAULT '0',
`feedback` mediumint(8) unsigned NOT NULL DEFAULT '0',
`fromIssue` mediumint(8) unsigned NOT NULL DEFAULT '0',
`docs` text NULL,
`docVersions` text NULL,
`name` varchar(255) NOT NULL DEFAULT '',
`type` varchar(20) NOT NULL DEFAULT '',
`mode` varchar(10) NOT NULL DEFAULT '',
@@ -13227,6 +13254,7 @@ CREATE INDEX `order` ON `zt_workflow` (`order`);
-- DROP TABLE IF EXISTS `zt_workflowgroup`;
CREATE TABLE IF NOT EXISTS `zt_workflowgroup` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`objectID` mediumint(8) unsigned NOT NULL DEFAULT '0',
`type` varchar(10) NOT NULL DEFAULT '',
`projectModel` varchar(10) NOT NULL DEFAULT '',
`projectType` varchar(10) NOT NULL DEFAULT '',
@@ -13242,6 +13270,7 @@ CREATE TABLE IF NOT EXISTS `zt_workflowgroup` (
`createdDate` datetime NULL,
`editedBy` varchar(30) NOT NULL DEFAULT '',
`editedDate` datetime NULL,
`deliverable` text NULL,
`deleted` enum('0', '1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+62
View File
@@ -1,3 +1,65 @@
2025-05-16 21.7
完成的需求
开源版:
74400 修改代码块中的语言项显示为中文
74398 版本恢复成功后存为新版本
74397 版本恢复前增加弹窗提示
74396 在文档版本切换右侧打印「恢复」按钮
73166 编辑器有序列表和无序列表样式
修复的Bug
开源版:
61513 场景下用例关联的研发需求显示undefined
61525 快捷访问下编辑文档提示无权限 (Feedback#9021)
61758 【内禅】文档升级成功后内容有丢失
61761 【内禅】预览文档附件有报错
61772 接口文档的历史记录不正确
61773 [内禅]文档中显示附件已做防盗链处理
61785 需要手动刷新浏览器后,文档正文才显示
61799 [内禅]文档正文内容为空
61808 【内禅】火狐浏览器简单表格内文字丢失
61873 emoji显示不正确
62130 从用例库导入用例性能存在问题 (Feedback#9169)
62159 计划关联需求搜索后报错
62162 使用版本1恢复创建了版本3,版本3还显示恢复按钮
62163 执行下需求估算页直接点击保存后sql报错
62164 切换文档版本,一直显示“正在加载文档”
62170 文档加载中时,点击恢复实际是不生效的
62175 执行下任务看板中在制品设置页保存后有报错
62180 用例执行后执行结果展示样式错乱
62181 点击接口编辑按钮无反应
62182 旧编辑器的全屏查看,无法查看完整内容
62183 子任务的截止日期大于父任务截止日期时没有自动修改父任务的截止日期
62185 执行分组视图页面分组下拉菜单缺少选中态
62186 只读用户恢复文档时应提示无编辑权限
62187 回收站中文档点击版本恢复按钮无反应
62188 biz10.5升级biz11.6.1,升级后编辑之前zenEditor创建的文档,存为草稿报错
62193 权限选择全选,点击保存报错
62258 执行下需求估算页面预计工时输入空格保存时提示信息不正确
62259 开启音视频功能后大桌面登录报错
62276 执行分组视图页面按状态分组时有报错
企业版:
62195 未分配项目阶段模板导出和导入任务权限时,显示了对应按钮
旗舰版:
62152 DevOps代码页面,没有列表页码 (Feedback#9205)
62483 复制项目保存时报错
IPD版:
39515 IPD项目有迭代的父阶段在迭代没开始时就可以关闭
62165 IPD项目设置阶段保存时页面报错
2025-04-30 21.6.1
完成的需求
修复的Bug
开源版:
61525 快捷访问下编辑文档提示无权限 (Feedback#9021)
61758 【内禅】文档升级成功后内容有丢失
61761 【内禅】预览文档附件有报错
61772 接口文档的历史记录不正确
61773 [内禅]文档中显示附件已做防盗链处理
61785 需要手动刷新浏览器后,文档正文才显示
61799 [内禅]文档正文内容为空
61808 【内禅】火狐浏览器简单表格内文字丢失
61873 emoji显示不正确
2025-04-11 21.6
完成的需求
开源版:
+1 -1
View File
@@ -254,7 +254,7 @@ class baseHelper
static public function importControl($moduleName)
{
global $app;
return helper::import($app->getModulePath($moduleName) . 'control.php');
return helper::import($app->getModulePath('', $moduleName) . 'control.php');
}
/**
+1 -1
View File
@@ -443,7 +443,7 @@ class router extends baseRouter
/* 加载每一个配置文件。Load every config file. */
foreach($configFiles as $configFile)
{
if(isset(static::$loadedConfigs[$configFile])) continue;
if(isset(static::$loadedConfigs[$configFile]) && !$force) continue;
if(file_exists($configFile)) include $configFile;
static::$loadedConfigs[$configFile] = $configFile;
}
+12 -23
View File
@@ -1771,19 +1771,8 @@ class baseDAO
*/
public function getFieldsType()
{
try
{
$this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
$sql = "DESC $this->table";
$rawFields = $this->dbh->rawQuery($sql)->fetchAll();
$this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
}
catch (PDOException $e)
{
$this->sqlError($e);
}
$fields = array();
$fields = array();
$rawFields = $this->descTable($this->table);
foreach($rawFields as $rawField)
{
$firstPOS = strpos($rawField->type, '(');
@@ -1875,17 +1864,17 @@ class baseDAO
$performanceSwitch = $performanceSchema->Value ?? 'OFF';
if($performanceSwitch == 'ON')
{
$profiles = $this->select('t1.EVENT_ID AS Query_ID, TRUNCATE(t1.TIMER_WAIT/1000000000000,6) AS Duration, t1.SQL_TEXT AS Query')
->from('performance_schema.events_statements_history_long')->alias('t1')
->leftJoin('performance_schema.threads')->alias('t2')->on('t1.THREAD_ID=t2.THREAD_ID')
->where('t2.PROCESSLIST_ID=CONNECTION_ID()')
->orderBy('EVENT_ID')
->fetchAll();
}
else
{
$profiles = $this->query('SHOW PROFILES')->fetchAll();
try
{
$sql = "SELECT t1.EVENT_ID AS Query_ID, TRUNCATE(t1.TIMER_WAIT/1000000000000,6) AS Duration, t1.SQL_TEXT AS Query FROM performance_schema.events_statements_history_long AS t1 LEFT JOIN performance_schema.threads AS t2 ON t1.THREAD_ID=t2.THREAD_ID wHeRe t2.PROCESSLIST_ID=CONNECTION_ID() oRdEr bY EVENT_ID";
$profiles = $this->dbh->query($sql)->fetchAll();
}
catch(PDOException $e)
{
$profiles = $this->query('SHOW PROFILES')->fetchAll();
}
}
if(empty($profiles)) $profiles = $this->query('SHOW PROFILES')->fetchAll();
foreach($profiles as $profile)
{
+1 -1
View File
@@ -85,7 +85,7 @@ class dbh
if($driver == 'mysql')
{
$pdo->exec("SET NAMES {$config->encoding}");
if(isset($this->config->strictMode) and $this->config->strictMode == false) $pdo->exec("SET @@sql_mode= ''");
if(isset($config->strictMode) and $config->strictMode == false) $pdo->exec("SET @@sql_mode= ''");
}
else if($setSchema)
{
+2
View File
@@ -224,6 +224,8 @@ class form extends fixer
if($app->rawModule == 'feedback' && $app->rawMethod == 'touserstory') $module = 'requirement';
if($app->rawModule == 'feedback' && $app->rawMethod == 'toepic') $module = 'epic';
if($app->rawModule == 'projectrelease') $module = 'release';
if($method == 'batchcreate') $method = 'create';
if($method == 'batchedit') $method = 'edit';
+3 -1
View File
@@ -248,6 +248,8 @@ function pivotConfig(): pivotConfig {return createWg('pivotConfig', func_get_arg
function iconPicker(): iconPicker {return createWg('iconPicker', func_get_args());}
function relatedObjectList(): relatedObjectList {return createWg('relatedObjectList', func_get_args());}
function taskAssignedTo(): taskAssignedTo {return createWg('taskAssignedTo', func_get_args());}
function docList(): docList {return createWg('docList', func_get_args());}
function deliverable(): deliverable {return createWg('deliverable', func_get_args());}
if(is_dir(__DIR__ . DS . 'wg' . DS . 'schedule'))
{
@@ -257,4 +259,4 @@ if(is_dir(__DIR__ . DS . 'wg' . DS . 'schedule'))
if(is_dir(__DIR__ . DS . 'wg' . DS . 'boardeditor'))
{
function boardEditor(): boardEditor {return createWg('boardeditor', func_get_args());}
}
}
+3 -1
View File
@@ -96,7 +96,9 @@ class backBtn extends btn
'approvalflow' => 'approvalflow-browse',
'host' => 'host-browse,my-index',
'deploy' => 'deploy-browse',
'program' => 'program-browse,program-productview'
'program' => 'program-browse,program-productview',
'workflowgroup' => 'workflowgroup-project,workflowgroup-deliverable',
'deliverable' => 'deliverable-browse'
);
$props = parent::getProps();
+44
View File
@@ -0,0 +1,44 @@
/**
* 获取附件的操作按钮。
* Get file actions.
*/
window.getDeliverableFileActions = function(file, deliverable)
{
let actions = [];
if(canDownload && typeof file.id === 'number') actions[0] = {icon: 'download', key: 'download', url: $.createLink('file', 'download', 'id=' + file.id), target: '_blank'};
actions[1] = {icon: 'edit', key: 'rename'};
actions[2] = {icon: 'trash', key: 'delete'};
/* 可以预览的文件。 */
if(['txt', 'jpg', 'jpeg', 'gif', 'png', 'bmp', 'mp4'].includes(file.extension) && canDownload)
{
actions[3] = {icon: 'eye', key: 'view', url: $.createLink('file', 'download', `fileID=${file.id}&mouse=left`), 'data-toggle' : 'modal', 'data-size' : 'lg'};
}
return actions;
}
/**
* 获取文档的操作按钮。
* Get file actions.
*/
window.getDocActions = function(doc, deliverable)
{
let actions = [];
actions[0] = {icon: 'eye', key: 'view', url: $.createLink('doc', 'view', 'docID=' + doc.id)};
actions[1] = {icon: 'edit', key: 'rename'};
actions[2] = {icon: 'trash', key: 'delete'};
return actions;
}
/**
* 获取交付物的操作按钮。
* Get deliverable actions.
*/
window.getDeliverableActions = function(deliverable)
{
let actions = [];
actions[0] = {text: addFile, icon: 'file', key: 'selectFile'};
if(deliverable.template > 0 && canDownload) actions[1] = {text: downloadTemplate, icon: 'download', key: 'downloadTemplate', url: $.createLink('file', 'download', 'templateID=' + deliverable.template), target: '_blank'};
return actions;
}
+78
View File
@@ -0,0 +1,78 @@
<?php
declare(strict_types=1);
namespace zin;
class deliverable extends wg
{
/**
* 默认的组件属性。
* Define widget properties.
*
* @var array
* @access protected
*/
protected static array $defineProps = array
(
'items: array', // 交付物条目。
'formName: string', // 表单名称。
'maxFileSize: string' // 最大文件大小。
);
/**
* 获取JS。
* Get page JS.
*
* @static
* @access public
* @return string
*/
public static function getPageJS(): ?string
{
global $lang, $app;
$app->loadLang('doc');
$app->loadLang('file');
jsVar('addFile', $lang->doc->addFile);
jsVar('downloadTemplate', $lang->doc->downloadTemplate);
jsVar('deleteItem', $lang->delete);
jsVar('canDownload', hasPriv('file', 'download'));
return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
}
/**
* 构建组件。
* Build.
*
* @access protected
* @return zui
*/
protected function build(): zui
{
global $lang, $app;
$app->loadLang('doc');
$app->loadLang('file');
$formName = $this->prop('formName') ? $this->prop('formName') : 'deliverable';
if(!$this->hasProp('maxFileSize'))
{
$maxFileSize = ini_get('upload_max_filesize');
$lastChar = substr($maxFileSize, -1);
$fileSizeUnit = array('K', 'M', 'G', 'T');
if(in_array($lastChar, $fileSizeUnit)) $maxFileSize .= 'B';
$this->setProp('maxFileSize', $maxFileSize);
}
return zui::deliverableList
(
set::formName($formName),
set::items($this->prop('items')),
set::docPicker(array('placeholder' => $lang->doc->selectDoc, 'items' => helper::createLink('doc', 'ajaxGetMineDocs', 'keyword={search}'))),
set::getFileActions(jsRaw('window.getDeliverableFileActions')),
set::getDocActions(jsRaw('window.getDocActions')),
set::getEmptyActions(jsRaw('window.getDeliverableActions')),
set::maxFileSize($this->prop('maxFileSize')),
set::extraCategory($lang->other)
);
}
}
+10 -6
View File
@@ -581,6 +581,7 @@ function handleSaveDoc(doc)
space : spaceType,
uid : (doc.uid || `doc${doc.id}`),
};
if(doc.fromVersion) docData.fromVersion = doc.fromVersion;
if(savingDocData[doc.id])
{
@@ -602,6 +603,14 @@ function handleSaveDoc(doc)
throw new Error(message);
}
doc = $.extend({}, doc, docData, data.doc);
if(docApp.spaceType == 'quick')
{
resolve(false);
const libType = docApp.lib.data.quickType;
return loadPage($.createLink('doc', 'quick', `type=${libType}&docID=${doc.id}`));
}
const libID = +doc.lib;
const lib = docApp.getLib(libID);
if(!lib)
@@ -1190,12 +1199,7 @@ const commands =
if (typeof doc !== 'object') {
doc = docApp._treeMap.value.docs.get(doc)?.data;
}
docApp.load(null, null, null, {noLoading: false, picks: 'doc'}).then(() => {
doc = docApp._treeMap.value.docs.get(doc.id)?.data;
const editable = doc?.editable;
if(!editable) return zui.Modal.alert(getLang('needEditable'));
docApp.startEditDoc(doc, options);
});
return docApp.startEditDoc(doc, options);
},
/** 上传文档。Upload Doc. */
uploadDoc: function()
+1
View File
@@ -317,6 +317,7 @@ class docApp extends wg
set::viewModeUrl($viewModeUrl),
set::langData($langData),
set::historyPanel($historyPanelProps),
set::showToolbar(true),
$hasZentaoSlashMenu ? jsCall('setZentaoSlashMenu', $this->getZentaoListMenu(), $lang->doc->zentaoData, $config->vision, $config->doc->zentaoListMenuPosition) : null
);
}
+12
View File
@@ -0,0 +1,12 @@
window.removeDocs = function(event)
{
const docID = $(event.target).closest(".docItem").data('docID');
const docTitle = $(event.target).closest(".docItem").find('.docTitle').text();
/* 删掉的这一行追加到相关文档下拉组件里。 */
items = $("#docs").zui('picker').$.state.items;
items.push({text: docTitle, value: docID, key: docID});
$("#docs").zui('picker').render({items, toolbar: true});
$(event.target).closest(".docItem").empty();
}
+78
View File
@@ -0,0 +1,78 @@
<?php
declare(strict_types=1);
namespace zin;
class docList extends wg
{
protected static array $defineProps = array(
'data' => '?object', // 对象数据。
'mode' => '?string="edit"' // view还是edit模式。
);
public static function getPageJS(): ?string
{
return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
}
protected function build()
{
global $app, $lang;
$app->loadLang('task');
$data = $this->prop('data');
$mode = $this->prop('mode');
$oldDocs = $app->control->dao->select('id,title,version')->from(TABLE_DOC)->where('id')->in($data->docs)->fetchAll('id');
$docList = $app->control->loadModel('doc')->getMySpaceDocs('all', 'bykeyword', '', 'id_desc', null, '', $data->docs);
$docs = array();
foreach($docList as $doc) $docs[] = array('text' => $doc->title, 'value' => $doc->id);
if($mode == 'edit')
{
$oldDocVersions = $app->control->dao->select('doc,version')->from(TABLE_DOCCONTENT)->where('doc')->in($data->docs)->fetchGroup('doc', 'version');
$oldDocVersions = \json_decode(json_encode($oldDocVersions), true);
foreach($oldDocVersions as $docID => $versions)
{
foreach($versions as $versionID => $version) $oldDocVersions[$docID][$versionID] = "#{$version['version']}";
}
}
if(is_string($data->docVersions)) $data->docVersions = \json_decode($data->docVersions, true);
$docBox = array();
if($data->docs)
{
foreach(explode(',', $data->docs) as $docID)
{
$link = $mode == 'view' && common::hasPriv('doc', 'view') ? a(set::href(helper::createLink('doc', 'view', "docID={$docID}&version={$data->docVersions[$docID]}")), $oldDocs[$docID]->title) : $oldDocs[$docID]->title;
$docBox[] = div
(
setData(array('docID' => $docID)),
setClass('docItem flex items-center py-1'),
span(setClass('mr-4 p-1 docTitle'), icon(setClass('mr-2'), 'file-text'), $link),
div(setClass('w-24'), $mode == 'edit' ? picker(set::required(true), set::name("docVersions[$docID]"), set::items($oldDocVersions[$docID]), set::value($data->docVersions[$docID])) : "#{$data->docVersions[$docID]}"),
$mode == 'edit' && $oldDocs[$docID]->version != $data->docVersions[$docID] ? label(setClass('ml-2 warning'), $lang->task->docSyncTips) : null,
$mode == 'edit' ? input(setClass('hidden'), set::name("oldDocs[$docID]"), set::value($docID)) : null,
$mode == 'edit' ? btn(setClass('ghost ml-2'), icon('trash'), setData(array('on' => 'click', 'call' => 'window.removeDocs', 'params' => 'event'))) : null
);
}
}
return div
(
setClass('form-group-wrapper picker-box'),
$mode == 'edit' ? picker
(
setID('docs'),
set::name('docs'),
set::items($docs),
set::multiple(true),
set::maxItemsCount(50),
set::menu(array('checkbox' => true)),
!empty($items) ? set::toolbar(true) : null
) : null,
div(setClass('mt-2'), $docBox)
);
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
#pick-pop-admin-menu {width: 139px!important;}
#pick-pop-admin-menu {width: 145px!important;}
#pick-pop-admin-menu .dropmenu-list {padding: 8px;}
#pick-pop-admin-menu .dropmenu-item + .dropmenu-item {margin-top: 4px}
#pick-pop-admin-menu .dropmenu-item.active {background-color: unset;}
+1 -1
View File
@@ -32,7 +32,7 @@ class filter extends wg
return picker
(
setClass('flex-auto'),
setClass('flex-auto no-morph'),
set::name($name),
set::value($value),
set::items($items),
+28 -27
View File
@@ -270,7 +270,6 @@ function validateResources(id)
let status = task.status;
let type = task.type;
let statusLang = ganttLang.taskStatusList['wait'];
flag = true;
/* Check status. */
if(status !== statusLang && type != 'point')
@@ -292,32 +291,26 @@ function validateResources(id)
if(type == 'point') itemID = task.id.split("-")[2];
/* Check data. */
let postData = {
'id' : itemID,
'startDate' : from.toLocaleDateString('en-CA'),
'endDate' : to.toLocaleDateString('en-CA'),
'type' : type
};
/* Sync Close. */
$.ajax({
url: $.createLink('programplan', 'ajaxResponseGanttDragEvent'),
dataType: "json",
data: postData,
type: "post",
success: function(response)
{
if(response.result == 'fail' && response.message)
{
zui.Messager.show({content: response.message, type: 'danger-outline', icon: 'exclamation-sign'});
flag = false;
}
else
{
gantt.updateTask(task.id, task);
if(task.parent) changeParentTask(task, task.parent);
}
}
});
const postData = 'id=' + itemID + '&startDate=' + from.toLocaleDateString('en-CA') + '&endDate=' + to.toLocaleDateString('en-CA') + '&type=' +type;
const xhr = new XMLHttpRequest();
xhr.open('POST', $.createLink('programplan', 'ajaxResponseGanttDragEvent'), false); // 同步模式
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send(postData);
let flag = true;
const response = JSON.parse(xhr.responseText);
if(response.result == 'fail' && response.message)
{
zui.Messager.show({content: response.message, type: 'danger-outline', icon: 'exclamation-sign'});
flag = false;
}
else
{
gantt.updateTask(task.id, task);
if(task.parent) changeParentTask(task, task.parent);
}
return flag;
}
@@ -714,6 +707,14 @@ function initGantt()
return false;
}
const sourceTask = gantt.getTask(link.source);
const targetTask = gantt.getTask(link.target);
if(sourceTask.allowLinks === false || targetTask.allowLinks === false)
{
zui.Messager.show({content: ganttLang.wrongKanbanTasks, type: 'danger-outline', icon: 'exclamation-sign'});
return false;
};
return true;
});
+1 -1
View File
@@ -131,7 +131,7 @@ class moduleMenu extends wg
$modules = $this->prop('modules');
$moduleName = '';
if($modules) array_map(function($module) use(&$moduleName, $activeKey) { if($module->id == $activeKey || $module->id == 'product-' . $activeKey) $moduleName = $module->name; }, $modules);
if(empty($moduleName))
if(!empty($modules) && empty($moduleName))
{
$module = $app->control->loadModel('tree')->getByID($activeKey);
if($module) $moduleName = $module->name;
+2
View File
@@ -53,6 +53,8 @@ class userAvatar extends wg
$realname = isset($user->realname) ? $user->realname : $realname;
}
if($avatar) $avatar .= '?v=' . uniqid(); // 给头像URL添加一个随机参数,避免浏览器缓存。
return avatar
(
set::src($avatar),
+6 -4
View File
@@ -26,8 +26,10 @@ pipeline {
separator(name: "replay", sectionHeader: "仓库切换")
string description: '指定一个构建Id用于回放', name: 'REPLAY_ID', trim: true
string description: '指定 zentaoext 分支, 也可以是 tag 或者 commit', name: 'zentaoext_version', trim: true
string description: '指定 xuanxuan 分支', name: 'xuanxuan_version', trim: true
string description: '指定企业版分支, 也可以是 tag 或者 commit', name: 'zentaoext_version', trim: true
string description: '指定旗舰版分支, 也可以是 tag 或者 commit', name: 'zentaomax_version', trim: true
string description: '指定IPD版分支, 也可以是 tag 或者 commit', name: 'zentaoipd_version', trim: true
string description: '指定喧喧分支', name: 'xuanxuan_version', trim: true
string description: '指定开源版全量降级 revision', name: 'fulldown_pms_version', trim: true
string description: '指定收费版全量降级 revision', name: 'fulldown_ext_version', trim: true
@@ -95,8 +97,8 @@ pipeline {
zCheckout([
[name: "xuansrc", subDir: true, url: "https://${env.GITFOX_HOST}/git/xuan/xuanxuan.git", credentialsId: "gitfox-zcorp-cc-ci-robot", branchs: ["${params.xuanxuan_version}", j.getReplaySHA("xuanxuan"), "${env.XUANVERSION}"] ],
[name: "zentaoext", subDir: true, url: "https://${env.GITFOX_HOST}/git/${env.ZENTAOEXT_GIT_REPO}.git", credentialsId: "gitfox-zcorp-cc-ci-robot", branchs: ["${params.zentaoext_version}", j.getReplaySHA("zentaoext"), "${env.ZENTAOEXT_VERSION}", "${env.GIT_BRANCH}"] ],
[name: "zentaomax", subDir: true, url: "https://${env.GITFOX_HOST}/git/zentao/zentaomax.git", credentialsId: "gitfox-zcorp-cc-ci-robot", branchs: ["${env.GIT_BRANCH}"] ],
[name: "zentaoipd", subDir: true, url: "https://${env.GITFOX_HOST}/git/zentao/zentaoipd.git", credentialsId: "gitfox-zcorp-cc-ci-robot", branchs: ["${env.GIT_BRANCH}"] ],
[name: "zentaomax", subDir: true, url: "https://${env.GITFOX_HOST}/git/zentao/zentaomax.git", credentialsId: "gitfox-zcorp-cc-ci-robot", branchs: ["${params.zentaomax_version}", j.getReplaySHA("zentaomax"), "${env.ZENTAOMAX_VERSION}", "${env.GIT_BRANCH}"] ],
[name: "zentaoipd", subDir: true, url: "https://${env.GITFOX_HOST}/git/zentao/zentaoipd.git", credentialsId: "gitfox-zcorp-cc-ci-robot", branchs: ["${params.zentaoipd_version}", j.getReplaySHA("zentaoipd"), "${env.ZENTAOIPD_VERSION}", "${env.GIT_BRANCH}"] ],
[name: "downRepo", subDir: true, url: "https://${env.GITFOX_HOST}/git/${env.DOWNGRADE_GIT_REPO}.git", credentialsId: "gitfox-zcorp-cc-ci-robot", branchs: ["${params.fulldown_pms_version}", j.getReplaySHA("${env.DOWNGRADE_GIT_REPO}"), "downgrade/${env.GIT_BRANCH}/src"] ],
[name: "downRepoExt", subDir: true, url: "https://${env.GITFOX_HOST}/git/${env.DOWNGRADE_EXT_GIT_REPO}.git", credentialsId: "gitfox-zcorp-cc-ci-robot", branchs: ["${params.fulldown_ext_version}", j.getReplaySHA("${env.DOWNGRADE_EXT_GIT_REPO}"), "downgrade/${env.GIT_BRANCH}/src"] ]
])
+6 -4
View File
@@ -18,8 +18,10 @@ pipeline {
parameters {
separator(name: "spec", sectionHeader: "仓库切换")
string description: '指定 zentaoext 分支, 也可以是 tag 或者 commit', name: 'zentaoext_version', trim: true
string description: '指定 xuanxuan 分支', name: 'xuanxuan_version', trim: true
string description: '指定企业版分支, 也可以是 tag 或者 commit', name: 'zentaoext_version', trim: true
string description: '指定旗舰版分支, 也可以是 tag 或者 commit', name: 'zentaomax_version', trim: true
string description: '指定IPD版分支, 也可以是 tag 或者 commit', name: 'zentaoipd_version', trim: true
string description: '指定喧喧分支', name: 'xuanxuan_version', trim: true
separator(name: "other", sectionHeader: "其它")
booleanParam defaultValue: false, description: '调试模式', name: 'DEBUG'
@@ -67,8 +69,8 @@ pipeline {
zCheckout([
[name: "xuansrc", subDir: true, url: "https://${env.GITFOX_HOST}/git/xuan/xuanxuan.git", credentialsId: "gitfox-zcorp-cc-ci-robot", branchs: ["${params.xuanxuan_version}", "${env.XUANVERSION}"] ],
[name: "zentaoext", subDir: true, url: "https://${env.GITFOX_HOST}/git/${env.ZENTAOEXT_GIT_REPO}.git", credentialsId: "gitfox-zcorp-cc-ci-robot", branchs: ["${params.zentaoext_version}", "${env.ZENTAOEXT_VERSION}", "${env.GIT_BRANCH}"] ],
[name: "zentaomax", subDir: true, url: "https://${env.GITFOX_HOST}/git/zentao/zentaomax.git", credentialsId: "gitfox-zcorp-cc-ci-robot", branchs: ["${env.GIT_BRANCH}"] ],
[name: "zentaoipd", subDir: true, url: "https://${env.GITFOX_HOST}/git/zentao/zentaoipd.git", credentialsId: "gitfox-zcorp-cc-ci-robot", branchs: ["${env.GIT_BRANCH}"] ],
[name: "zentaomax", subDir: true, url: "https://${env.GITFOX_HOST}/git/zentao/zentaomax.git", credentialsId: "gitfox-zcorp-cc-ci-robot", branchs: ["${params.zentaomax_version}", "${env.ZENTAOMAX_VERSION}", "${env.GIT_BRANCH}"] ],
[name: "zentaoipd", subDir: true, url: "https://${env.GITFOX_HOST}/git/zentao/zentaoipd.git", credentialsId: "gitfox-zcorp-cc-ci-robot", branchs: ["${params.zentaoipd_version}", "${env.ZENTAOIPD_VERSION}", "${env.GIT_BRANCH}"] ],
[name: "downRepo", subDir: true, url: "https://${env.GITFOX_HOST}/git/${env.DOWNGRADE_GIT_REPO}.git", credentialsId: "gitfox-zcorp-cc-ci-robot", branchs: ["downgrade/blank"] ],
[name: "downRepoExt", subDir: true, url: "https://${env.GITFOX_HOST}/git/${env.DOWNGRADE_EXT_GIT_REPO}.git", credentialsId: "gitfox-zcorp-cc-ci-robot", branchs: ["downgrade/blank"] ]
])
+1
View File
@@ -72,6 +72,7 @@ $config->action->objectNameFields['prompt'] = 'name';
$config->action->objectNameFields['miniprogram'] = 'name';
$config->action->objectNameFields['holiday'] = 'name';
$config->action->objectNameFields['system'] = 'name';
$config->action->objectNameFields['deliverable'] = 'name';
$config->action->commonImgSize = 870;
+2
View File
@@ -192,6 +192,7 @@ $lang->action->objectTypes['board'] = 'Board';
$lang->action->objectTypes['boardspace'] = 'Board Space';
$lang->action->objectTypes['productline'] = 'Product Line';
$lang->action->objectTypes['system'] = $lang->product->system;
$lang->action->objectTypes['deliverable'] = 'Deliverable';
/* Used to describe operation history. */
$lang->action->desc = new stdclass();
@@ -944,6 +945,7 @@ $lang->action->label->instance = 'Application|instance|view|id=%s';
$lang->action->label->prompt = 'Prompt|ai|promptview|id=%s';
$lang->action->label->miniprogram = 'Mini Program|aiapp|browseminiprogram|id=%s';
$lang->action->label->holiday = 'Holiday|holiday|browse|';
$lang->action->label->deliverable = 'Deliverable|deliverable|view|id=%s';
/* Object type. */
$lang->action->search = new stdclass();
+2
View File
@@ -192,6 +192,7 @@ $lang->action->objectTypes['board'] = 'Board';
$lang->action->objectTypes['boardspace'] = 'Board Space';
$lang->action->objectTypes['productline'] = 'Product Line';
$lang->action->objectTypes['system'] = $lang->product->system;
$lang->action->objectTypes['deliverable'] = 'Deliverable';
/* Used to describe operation history. */
$lang->action->desc = new stdclass();
@@ -944,6 +945,7 @@ $lang->action->label->instance = 'Application|instance|view|id=%s';
$lang->action->label->prompt = 'Prompt|ai|promptview|id=%s';
$lang->action->label->miniprogram = 'Mini Program|aiapp|browseminiprogram|id=%s';
$lang->action->label->holiday = 'Holiday|holiday|browse|';
$lang->action->label->deliverable = 'Deliverable|deliverable|view|id=%s';
/* Object type. */
$lang->action->search = new stdclass();
+2
View File
@@ -192,6 +192,7 @@ $lang->action->objectTypes['board'] = 'Board';
$lang->action->objectTypes['boardspace'] = 'Board Space';
$lang->action->objectTypes['productline'] = 'Product Line';
$lang->action->objectTypes['system'] = $lang->product->system;
$lang->action->objectTypes['deliverable'] = 'Deliverable';
/* Used to describe operation history. */
$lang->action->desc = new stdclass();
@@ -944,6 +945,7 @@ $lang->action->label->instance = 'Application|instance|view|id=%s';
$lang->action->label->prompt = 'Prompt|ai|promptview|id=%s';
$lang->action->label->miniprogram = 'Mini Program|aiapp|browseminiprogram|id=%s';
$lang->action->label->holiday = 'Holiday|holiday|browse|';
$lang->action->label->deliverable = 'Deliverable|deliverable|view|id=%s';
/* Object type. */
$lang->action->search = new stdclass();
+2
View File
@@ -192,6 +192,7 @@ $lang->action->objectTypes['board'] = '白板';
$lang->action->objectTypes['boardspace'] = '白板空间';
$lang->action->objectTypes['productline'] = '产品线';
$lang->action->objectTypes['system'] = $lang->product->system;
$lang->action->objectTypes['deliverable'] = '交付物';
/* 用来描述操作历史记录。*/
$lang->action->desc = new stdclass();
@@ -944,6 +945,7 @@ $lang->action->label->instance = '服务|instance|view|id=%s';
$lang->action->label->prompt = '提词|ai|promptview|id=%s';
$lang->action->label->miniprogram = '小程序|aiapp|browseminiprogram|id=%s';
$lang->action->label->holiday = '节假日|holiday|browse|';
$lang->action->label->deliverable = '交付物|deliverable|view|id=%s';
/* Object type. */
$lang->action->search = new stdclass();
+32 -6
View File
@@ -940,6 +940,12 @@ class actionModel extends model
foreach($actions as $action)
{
$item = new stdClass();
if(strlen(trim(($action->comment))) !== 0)
{
$item->comment = $this->formatActionComment($action->comment);
$currentUserCanEdit = $action->id == $endAction->id && $action->actor == $account && $action->action == 'commented';
$item->commentEditable = $commentEditable && common::hasPriv('action', 'editComment') && $currentUserCanEdit;
}
if($action->action === 'assigned' || $action->action === 'toaudit')
{
@@ -951,7 +957,7 @@ class actionModel extends model
$action->actor = zget($users, $action->actor);
if(str_contains($action->actor, ':')) $action->actor = substr($action->actor, strpos($action->actor, ':') + 1);
if(!empty($action->history)) $item->historyChanges = $this->renderChanges($action->objectType, $action->history);
if(!empty($action->history)) $item->historyChanges = $this->renderChanges($action->objectType, $action->objectID, $action->history);
$item->id = $action->id;
$item->action = $action->action;
@@ -1452,12 +1458,13 @@ class actionModel extends model
* Render histories of every action.
*
* @param string $objectType
* @param int $objectID
* @param array $histories
* @param bool $canChangeTag
* @access public
* @return string
*/
public function renderChanges(string $objectType, array $histories, bool $canChangeTag = true): string
public function renderChanges(string $objectType, int $objectID, array $histories, bool $canChangeTag = true): string
{
if(empty($histories)) return '';
@@ -1509,7 +1516,14 @@ class actionModel extends model
}
else
{
$content .= sprintf($this->lang->action->desc->diff1, $history->fieldLabel, $history->old, $history->new);
if($history->field == 'deliverable' && ($objectType == 'project' || $objectType == 'execution'))
{
$content .= $this->processDeliverableJson($objectType, $objectID, $history);
}
else
{
$content .= sprintf($this->lang->action->desc->diff1, $history->fieldLabel, $history->old, $history->new);
}
}
}
return $content;
@@ -1520,14 +1534,15 @@ class actionModel extends model
* Print histories of every action.
*
* @param string $objectType
* @param int $objectID
* @param array $histories
* @param bool $canChangeTag
* @access public
* @return void
*/
public function printChanges(string $objectType, array $histories, bool $canChangeTag = true): void
public function printChanges(string $objectType, int $objectID, array $histories, bool $canChangeTag = true): void
{
$content = $this->renderChanges($objectType, $histories, $canChangeTag);
$content = $this->renderChanges($objectType, $objectID, $histories, $canChangeTag);
if(is_string($content)) echo $content;
}
@@ -2324,7 +2339,18 @@ class actionModel extends model
if($action->objectType == 'task')
{
$task = $this->loadModel('task')->fetchByID((int)$action->objectID);
$this->loadModel('task')->updateParent($task, false);
if($task->parent > 0)
{
$parentConsumed = $this->dao->select('consumed')->from(TABLE_TASK)->where('id')->eq($task->parent)->fetch('consumed');
if($parentConsumed)
{
$this->dao->update(TABLE_TASK)->set('parent')->eq('0')->set('path')->eq(",{$task->id},")->where('id')->eq($task->id)->exec();
}
else
{
$this->loadModel('task')->updateParent($task, false);
}
}
}
}
+1 -1
View File
@@ -8,7 +8,7 @@ if(!isset($config->safe->weak)) $config->safe->weak = '123456,password,12345,123
$config->admin->menuGroup['system'] = array('custom|mode', 'backup', 'cron', 'action|trash', 'admin|xuanxuan', 'setting|xuanxuan', 'admin|license', 'admin|checkweak', 'admin|resetpwdsetting', 'admin|safe', 'cache|setting', 'custom|timezone', 'search|buildindex', 'admin|tableengine', 'ldap', 'custom|libreoffice', 'conference', 'watermark', 'client', 'system|browsebackup', 'system|restorebackup');
$config->admin->menuGroup['company'] = array('dept', 'company', 'user', 'group', 'tutorial');
$config->admin->menuGroup['switch'] = array('admin|setmodule');
$config->admin->menuGroup['model'] = array('auditcl', 'stage', '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['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');
+1
View File
@@ -118,6 +118,7 @@ $lang->admin->setModule->opportunitylib = 'Opportunity Lib';
$lang->admin->setModule->practicelib = 'Practice Lib';
$lang->admin->setModule->componentlib = 'Component Lib';
$lang->admin->setModule->devops = 'DevOps';
$lang->admin->setModule->deliverable = 'Deliverable';
$lang->admin->setModule->kanban = 'Kanban';
$lang->admin->setModule->OA = 'OA';
$lang->admin->setModule->deploy = 'Deploy';
+1
View File
@@ -118,6 +118,7 @@ $lang->admin->setModule->opportunitylib = 'Opportunity Lib';
$lang->admin->setModule->practicelib = 'Practice Lib';
$lang->admin->setModule->componentlib = 'Component Lib';
$lang->admin->setModule->devops = 'DevOps';
$lang->admin->setModule->deliverable = 'Deliverable';
$lang->admin->setModule->kanban = 'Kanban';
$lang->admin->setModule->OA = 'OA';
$lang->admin->setModule->deploy = 'Deploy';
+1
View File
@@ -118,6 +118,7 @@ $lang->admin->setModule->opportunitylib = 'Opportunity Lib';
$lang->admin->setModule->practicelib = 'Practice Lib';
$lang->admin->setModule->componentlib = 'Component Lib';
$lang->admin->setModule->devops = 'DevOps';
$lang->admin->setModule->deliverable = 'Deliverable';
$lang->admin->setModule->kanban = 'Kanban';
$lang->admin->setModule->OA = 'OA';
$lang->admin->setModule->deploy = 'Deploy';
+12 -7
View File
@@ -74,7 +74,7 @@ $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', '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', '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']['agileplus'] = array('link' => "{$lang->agilePlusModel}|auditcl|agileplusbrowse|", 'subModule' => 'auditcl');
@@ -86,13 +86,14 @@ $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'));
if(helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['common']['stage'] = array('link' => "{$lang->stage->type}|stage|settype|", 'subModule' => 'stage');
$lang->admin->menuList->model['tabMenu']['common']['build'] = array('link' => "{$lang->build->common}|custom|required|module=build", 'alias' => 'set', 'exclude' => 'custom');
$lang->admin->menuList->model['tabMenu']['common']['flow'] = array('link' => "{$lang->custom->flow}|custom|flow|", 'divider' => true);
$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'));
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');
$lang->admin->menuList->model['tabMenu']['common']['flow'] = array('link' => "{$lang->custom->flow}|custom|flow|", 'divider' => true);
$lang->admin->menuList->model['tabMenu']['common']['percent'] = array('link' => "{$lang->stage->percent}|custom|percent|");
$lang->admin->menuList->model['tabMenu']['common']['hours'] = array('link' => "{$lang->workingHour}|custom|hours|", 'subModule' => 'holiday', 'links' => array('holiday|browse|', 'custom|hours|'));
$lang->admin->menuList->model['tabMenu']['common']['percent'] = array('link' => "{$lang->stage->percent}|custom|percent|");
$lang->admin->menuList->model['tabMenu']['common']['hours'] = array('link' => "{$lang->workingHour}|custom|hours|", 'subModule' => 'holiday', 'links' => array('holiday|browse|', 'custom|hours|'));
if(helper::hasFeature('waterfall')) $lang->admin->menuList->model['tabMenu']['waterfall']['stage'] = array('link' => "{$lang->stage->list}|stage|browse|", 'subModule' => 'stage', 'exclude' => 'stage-plusbrowse');
if(helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['waterfallplus']['stage'] = array('link' => "{$lang->stage->list}|stage|plusbrowse|", 'subModule' => 'stage', 'exclude' => 'stage-browse');
$lang->admin->menuList->model['tabMenu']['menuOrder']['common']['5'] = 'project';
@@ -103,6 +104,10 @@ $lang->admin->menuList->model['tabMenu']['menuOrder']['common']['40'] = 'p
$lang->admin->menuList->model['tabMenu']['menuOrder']['common']['45'] = 'hours';
if(helper::hasFeature('waterfall')) $lang->admin->menuList->model['tabMenu']['menuOrder']['waterfall']['5'] = 'stage';
if(helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['menuOrder']['waterfallplus']['5'] = 'stage';
if($config->edition == 'max' or $config->edition == 'ipd')
{
$lang->admin->menuList->model['tabMenu']['menuOrder']['common']['15'] = 'deliverable';
}
$lang->admin->menuList->feature['subMenu']['my'] = array('link' => "{$lang->my->common}|custom|set|module=todo&field=priList", 'exclude' => 'set,required');
$lang->admin->menuList->feature['subMenu']['product'] = array('link' => "{$lang->productCommon}|custom|required|module=product", 'exclude' => 'set,required', 'alias' => 'browsestoryconcept,product');
+2 -1
View File
@@ -118,6 +118,7 @@ $lang->admin->setModule->opportunitylib = '机会库';
$lang->admin->setModule->practicelib = '最佳实践库';
$lang->admin->setModule->componentlib = '组件库';
$lang->admin->setModule->devops = 'DevOps';
$lang->admin->setModule->deliverable = '交付物';
$lang->admin->setModule->kanban = '通用看板';
$lang->admin->setModule->OA = '办公';
$lang->admin->setModule->deploy = '运维';
@@ -170,7 +171,7 @@ $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']['name'] = '项目模型配置';
$lang->admin->menuSetting['model']['desc'] = '不同项目管理模型和项目通用要素配置。';
$lang->admin->menuSetting['feature']['name'] = '功能配置';
$lang->admin->menuSetting['feature']['desc'] = '按照功能菜单进行系统的要素配置。';
+3 -3
View File
@@ -6,7 +6,7 @@ window.testConnection = () =>
{
type: 'POST',
url: $.createLink('ai', 'modelTestConnection'),
data: $('#model-form').find('form').serialize(),
data: $('.form').serialize(),
dataType: 'json',
success: data =>
{
@@ -68,8 +68,8 @@ $(() =>
$.ajax(
{
type: 'POST',
url: $.createLink('ai', 'modelcreate'),
data: $('#model-form').serialize(),
url: $.createLink('ai', 'modeledit', "id=" + modelData.id),
data: $('.form').serialize(),
dataType: 'json',
success: data =>
{
+1 -1
View File
@@ -326,7 +326,7 @@ class apiModel extends model
/* 如果要根据版本号查询,那主要查询的是spec表,否则查询api表即可。 */
if($version)
{
$fields = 'spec.*,api.id,api.product,api.lib,api.version,doc.name as libName,module.name as moduleName,api.editedBy,api.editedDate';
$fields = 'spec.*,api.id,api.product,api.lib,doc.name as libName,module.name as moduleName,api.editedBy,api.editedDate';
}
else
{
+2 -1
View File
@@ -139,6 +139,7 @@ $apiData = (array)$api;
foreach($unsetProps as $prop) unset($apiData[$prop]);
$apiData['api'] = true;
$apiData['title'] = "$api->method $api->path $api->title";
$apiData['desc'] = htmlspecialchars_decode($apiData['desc']);
div
(
@@ -156,7 +157,7 @@ div
h2(setClass('flex-none min-w-0 max-w-full'), $api->title),
(isset($api->deleted) && $api->deleted) ? span(setClass('label danger flex-none'), $lang->deleted) : null
),
div(setClass('desc'), html($api->desc)),
div(setClass('desc'), html(htmlspecialchars_decode($api->desc))),
$apiHeader,
$apiQuery,
$apiParams,
+2 -2
View File
@@ -34,14 +34,14 @@ $config->bug->list->allFields = 'id, module, execution, story, task,
$config->bug->list->defaultFields = 'id,title,severity,pri,openedBy,assignedTo,resolvedBy,resolution';
$config->bug->list->customCreateFields = 'execution,noticefeedbackBy,story,task,pri,severity,os,browser,deadline,mailto,keywords';
$config->bug->list->customBatchEditFields = 'type,severity,pri,productplan,assignedTo,deadline,resolvedBy,resolution,os,browser,keywords';
$config->bug->list->customBatchCreateFields = 'project,execution,steps,type,pri,deadline,severity,os,browser,keywords';
$config->bug->list->customBatchCreateFields = 'project,execution,plan,steps,type,pri,deadline,severity,os,browser,keywords';
$config->bug->custom = new stdclass();
$config->bug->custom->createFields = $config->bug->list->customCreateFields;
$config->bug->custom->batchCreateFields = 'project,execution,deadline,steps,type,pri,severity,os,browser,%s';
$config->bug->custom->batchEditFields = 'type,severity,pri,assignedTo,deadline,status,resolvedBy,resolution';
$config->bug->exportFields = 'id, product, branch, module, project, execution, story, task,
$config->bug->exportFields = 'id, product, branch, module, project, execution, plan, story, task,
title, keywords, severity, pri, type, os, browser,
steps, status, deadline, activatedCount, confirmed, mailto,
openedBy, openedDate, openedBuild,
+2
View File
@@ -10,6 +10,7 @@ $config->bug->form->create['openedBuild'] = array('required' => true, 'type' =>
$config->bug->form->create['product'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->create['branch'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->create['module'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->create['plan'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->create['project'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->create['execution'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->create['assignedTo'] = array('required' => false, 'type' => 'string', 'default' => '');
@@ -159,6 +160,7 @@ $config->bug->form->batchCreate['story'] = array('required' => false, 'typ
$config->bug->form->batchCreate['branch'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->batchCreate['laneID'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->batchCreate['openedBuild'] = array('required' => true, 'type' => 'array', 'default' => '', 'filter' => 'join');
$config->bug->form->batchCreate['plan'] = array('required' => false, 'type' => 'int', 'default' => 0);
$config->bug->form->batchCreate['title'] = array('required' => true, 'type' => 'string', 'default' => '', 'base' => true);
$config->bug->form->batchCreate['deadline'] = array('required' => false, 'type' => 'date', 'default' => null);
$config->bug->form->batchCreate['steps'] = array('required' => false, 'type' => 'string', 'default' => '', 'control' => 'editor');
+6 -5
View File
@@ -70,11 +70,12 @@ $config->bug->dtable->fieldList['execution']['group'] = 3;
$config->bug->dtable->fieldList['execution']['dataSource'] = array('module' => 'execution', 'method' =>'getPairs', 'params' => ['projectID' => 0]);
$config->bug->dtable->fieldList['execution']['sortType'] = true;
$config->bug->dtable->fieldList['plan']['title'] = $lang->bug->plan;
$config->bug->dtable->fieldList['plan']['width'] = 120;
$config->bug->dtable->fieldList['plan']['group'] = 3;
$config->bug->dtable->fieldList['plan']['sortType'] = true;
$config->bug->dtable->fieldList['plan']['hint'] = true;
$config->bug->dtable->fieldList['plan']['title'] = $lang->bug->plan;
$config->bug->dtable->fieldList['plan']['width'] = 120;
$config->bug->dtable->fieldList['plan']['group'] = 3;
$config->bug->dtable->fieldList['plan']['sortType'] = true;
$config->bug->dtable->fieldList['plan']['hint'] = true;
$config->bug->dtable->fieldList['plan']['dataSource'] = array('module' => 'productplan', 'method' =>'getPairs', 'params' => ['productIdList' => '$productIdList', 'branch' => '$branch']);
$config->bug->dtable->fieldList['openedBuild']['title'] = $lang->bug->openedBuild;
$config->bug->dtable->fieldList['openedBuild']['type'] = 'text';
+12 -4
View File
@@ -251,8 +251,6 @@ class bug extends control
$formData = form::data($this->config->bug->form->create);
$bug = $this->bugZen->prepareCreateExtras($formData);
$this->bugZen->checkExistBug($bug);
$bugID = $this->bug->create($bug, $from);
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
@@ -648,7 +646,17 @@ class bug extends control
{
/* 设置bug导出的参数。 */
/* Set bug export params. */
$this->session->set('bugTransferParams', array('productID' => $productID, 'executionID' => $executionID, 'branch' => 'all'));
if($executionID)
{
$productIdList = $this->loadModel('product')->getProductPairsByProject($executionID);
$productIdList = array_keys($productIdList);
}
else
{
$productIdList = array($productID);
}
$this->session->set('bugTransferParams', array('productID' => $productID, 'executionID' => $executionID, 'branch' => 'all', 'productIdList' => $productIdList));
/* 设置导出数据源。 */
/* Set export data source. */
@@ -797,7 +805,7 @@ class bug extends control
if(!empty($_POST))
{
$bugs = $this->bugZen->buildBugsForBatchCreate($productID, $branch, $bugImagesFile);
$bugs = $this->bugZen->checkBugsForBatchCreate($bugs, $productID);
$bugs = $this->bugZen->checkBugsForBatchCreate($bugs);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$message = '';
+1 -1
View File
@@ -771,7 +771,7 @@ class bugModel extends model
$this->config->bug->search['queryID'] = $queryID;
$this->config->bug->search['params']['project']['values'] = $projectParams;
$this->config->bug->search['params']['product']['values'] = $productParams;
$this->config->bug->search['params']['plan']['values'] = $this->loadModel('productplan')->getPairs($productID);
$this->config->bug->search['params']['plan']['values'] = $this->loadModel('productplan')->getPairs($productID, '', '', true);
$this->config->bug->search['params']['module']['values'] = $modules;
$this->config->bug->search['params']['execution']['values'] = $this->loadModel('product')->getExecutionPairsByProduct($productID, '0', (int)$projectID);
$this->config->bug->search['params']['severity']['values'] = array(0 => '') + $this->lang->bug->severityList; //Fix bug #939.
+4
View File
@@ -12,6 +12,7 @@ namespace zin;
$defaultBug = array('module' => $moduleID, 'project' => $projectID, 'execution' => $executionID, 'openedBuild' => 'trunk', 'pri' => 3, 'severity' => 3);
if($product->type != 'normal') $defaultBug['branch'] = $branch;
if($product->shadow) unset($customFields['plan']);
if(isset($executionType) && $executionType == 'kanban')
{
$defaultBug['region'] = $regionID;
@@ -64,6 +65,9 @@ $items[] = array
/* Field of openedBuild. */
$items[] = array('name' => 'openedBuild', 'label' => $lang->bug->openedBuild, 'control' => 'picker', 'items' => $builds, 'value' => 'trunk', 'multiple' => true, 'width' => '200px', 'required' => true, 'ditto' => true);
/* Field of plan. */
if(!$product->shadow) $items[] = array('name' => 'plan', 'label' => $lang->bug->plan, 'control' => 'picker', 'items' => $plans, 'value' => '', 'width' => '200px', 'required' => isset($requiredFields['plan']), 'ditto' => true);
/* Field of title. */
$items[] = array( 'name' => 'title', 'label' => $lang->bug->title, 'width' => '240px', 'required' => true, 'control' => 'colorInput');
+7
View File
@@ -27,6 +27,13 @@ $fields->field('execution')
->className($isShadowProduct && $isOriginalProduct ? 'full:w-1/2' : 'full:w-1/4')
->foldable(!$isShadowProduct);
$fields->field('plan')
->label($lang->bug->plan)
->className('w-1/2 full:w-1/2')
->hidden($isShadowProduct)
->items(data('plans'))
->foldable();
if(common::hasPriv('build', 'create'))
{
$fields->field('openedBuild')
+1 -1
View File
@@ -24,7 +24,7 @@ $fields->autoLoad('branch', 'module,execution,project,story,task,assignedTo')
->autoLoad('allUsers', 'assignedTo')
->autoLoad('region', 'lane');
if(!$product->shadow) $fields->fullModeOrders('module,project,execution');
if(!$product->shadow) $fields->fullModeOrders('module,project,execution,plan');
jsVar('bug', $bug);
jsVar('moduleID', $bug->moduleID);
+11 -36
View File
@@ -2,27 +2,6 @@
declare(strict_types=1);
class bugZen extends bug
{
/**
* 检查bug是否已经存在。
* Check whether bug is exist.
*
* @param object $bug
* @access protected
* @return bool
*/
protected function checkExistBug(object $bug): bool
{
$result = $this->loadModel('common')->removeDuplicate('bug', $bug, "product={$bug->product}");
if($result && $result['stop'])
{
$message = sprintf($this->lang->duplicate, $this->lang->bug->common);
return $this->send(array('result' => 'success', 'message' => $message, 'load' => $this->createLink('bug', 'view', "bugID={$result['duplicate']}")));
}
return true;
}
/**
* 检查用户是否拥有所属执行的权限。
* Check bug execution priv.
@@ -141,25 +120,11 @@ class bugZen extends bug
* Check the batch created bugs.
*
* @param array $bugs
* @param int $productID
* @access protected
* @return array
*/
protected function checkBugsForBatchCreate(array $bugs, int $productID): array
protected function checkBugsForBatchCreate(array $bugs): array
{
$this->loadModel('common');
/* Check whether the bugs meet the requirements, and if not, remove it. */
foreach($bugs as $index => $bug)
{
$result = $this->common->removeDuplicate('bug', $bug, "product={$productID}");
if(zget($result, 'stop', false) !== false)
{
unset($bugs[$index]);
continue;
}
}
/* Check required fields. */
foreach($bugs as $index => $bug)
{
@@ -414,6 +379,7 @@ class bugZen extends bug
protected function getExportFields(int $executionID, object|bool $product): string
{
$exportFields = str_replace(' ', '', $this->config->bug->exportFields);
$isShadow = false;
if(isset($product->type) and $product->type == 'normal') $exportFields = str_replace(',branch,', ',', ",{$exportFields},");;
if(!$product)
{
@@ -422,9 +388,16 @@ class bugZen extends bug
foreach($products as $product)
{
if($product->type != 'normal') $hasBranch = true;
if(!empty($product->shadow)) $isShadow = true;
}
if(!$hasBranch) $exportFields = str_replace(',branch,', ',', ",{$exportFields},");
}
else
{
$isShadow = $product->shadow;
}
if($isShadow) $exportFields = str_replace(',plan,', ',', ",{$exportFields},");
if($this->app->tab == 'project' or $this->app->tab == 'execution')
{
$execution = $this->loadModel('execution')->getByID($executionID);
@@ -1139,6 +1112,7 @@ class bugZen extends bug
$this->view->branchID = $bug->branch != 'all' ? $bug->branch : '0';
$this->view->cases = $this->loadModel('testcase')->getPairsByProduct($this->session->product, array(0, $this->view->branchID));
$this->view->copyBugID = isset($bugID) ? $bugID : 0;
$this->view->plans = $this->loadModel('productplan')->getPairs($bug->productID, $bug->branch, 'noclosed', true);
}
/**
@@ -1436,6 +1410,7 @@ class bugZen extends bug
$this->view->branch = $branch;
$this->view->branches = $branches;
$this->view->moduleOptionMenu = $this->tree->getOptionMenu($product->id, 'bug', 0, $branch === 'all' ? 'all' : (string)$branch);
$this->view->plans = $this->loadModel('productplan')->getPairs($product->id, $branch, 'noclosed', true);
}
/**
+1
View File
@@ -10,6 +10,7 @@
* @link https://www.zentao.net
*/
$lang->build->common = "Build";
$lang->build->browse = "Build List";
$lang->build->create = "Build erstellen";
$lang->build->edit = "Bearbeiten";
$lang->build->linkStory = "{$lang->SRCommon} verknüpfen";
+1
View File
@@ -10,6 +10,7 @@
* @link https://www.zentao.net
*/
$lang->build->common = "Build";
$lang->build->browse = "Build List";
$lang->build->create = "Create Build";
$lang->build->edit = "Edit Build";
$lang->build->linkStory = "Link {$lang->SRCommon}";
+1
View File
@@ -10,6 +10,7 @@
* @link https://www.zentao.net
*/
$lang->build->common = "Build";
$lang->build->browse = "Liste Build";
$lang->build->create = "Créer Build";
$lang->build->edit = "Editer Build";
$lang->build->linkStory = "Intégrer {$lang->SRCommon}";
+1
View File
@@ -10,6 +10,7 @@
* @link https://www.zentao.net
*/
$lang->build->common = "构建";
$lang->build->browse = "构建列表";
$lang->build->create = "创建构建";
$lang->build->edit = "编辑构建";
$lang->build->linkStory = "关联{$lang->SRCommon}";
+3 -5
View File
@@ -236,7 +236,7 @@ class caselib extends control
$this->loadModel('testcase');
helper::setcookie('lastLibCaseModule', (int)$this->post->module, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, false);
$case = form::data($this->config->testcase->form->create)->add('lib', $libID)
$case = form::data($this->config->testcase->form->create)->add('lib', $_POST['lib'] ? $this->post->lib : $libID)
->setIF(($this->config->testcase->needReview && strpos($this->config->testcase->forceNotReview, $this->app->user->account) === false) || (!empty($this->config->testcase->forceReview) && strpos($this->config->testcase->forceReview, $this->app->user->account) !== false), 'status', 'wait')
->get();
@@ -248,15 +248,13 @@ class caselib extends control
}
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$result = $this->loadModel('common')->removeDuplicate('case', $case, "id!='$param'");
if($result and $result['stop']) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->duplicate, $this->lang->testcase->common), 'locate' => $this->createLink('testcase', 'view', "caseID={$result['duplicate']}")));
$this->testcase->create($case);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
/* If link from no head then reload. */
if(isInModal()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $this->createLink('caselib', 'browse', "libID={$libID}&browseType=byModule&param={$_POST['module']}")));
$params = $libID == $case->lib ? "libID={$libID}&browseType=byModule&param={$_POST['module']}" : "libID={$libID}";
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $this->createLink('caselib', 'browse', $params)));
}
/* Set lib menu. */
$libraries = $this->caselib->getLibraries();
+19
View File
@@ -0,0 +1,19 @@
/**
* 加载用例库的模块。
* Load modules of the caselib.
*/
function loadModules(e)
{
const libID = $(e.target).val();
const moduleID = $('input[name=module]').val();
const getModuleLink = $.createLink('tree', 'ajaxGetOptionMenu', 'rootID=' + libID + '&viewtype=caselib&branch=0&rootModuleID=0&returnType=items');
$.getJSON(getModuleLink, function(modules)
{
if(modules)
{
const $modulePicker = $('input[name=module]').zui('picker');
$modulePicker.render({items: modules});
$modulePicker.$.setValue(moduleID);
}
});
}
+1
View File
@@ -24,6 +24,7 @@ formPanel
(
picker
(
on::change('loadModules'),
set::name('lib'),
set::items($libraries),
set::required(true),
-7
View File
@@ -153,13 +153,6 @@ class caselibZen extends caselib
$testcases = form::batchData($this->config->testcase->form->batchCreate)->get();
foreach($testcases as $i => $testcase)
{
$result = $this->common->removeDuplicate('testcase', $testcase, "lib={$libID}");
if(zget($result, 'stop', false) !== false)
{
unset($testcases[$i]);
continue;
}
$testcase->lib = $libID;
$testcase->project = 0;
$testcase->openedBy = $account;
+10 -8
View File
@@ -8,14 +8,16 @@ $lang->chart->acl = 'Access Control';
$lang->chart->aclList['open'] = 'Public (with chart view permissions and dimension permissions can access it)';
$lang->chart->aclList['private'] = 'Private (Only creators and whitelisted users with dimension permissions can access it)';
$lang->chart->group = 'Group';
$lang->chart->field = 'Related Field';
$lang->chart->agg = 'Aggregate';
$lang->chart->chooseField = 'Choose field';
$lang->chart->aggType = 'Aggregate type';
$lang->chart->other = 'Other';
$lang->chart->unlimited = 'Unlimited';
$lang->chart->colon = 'To';
$lang->chart->group = 'Group';
$lang->chart->field = 'Related Field';
$lang->chart->agg = 'Aggregate';
$lang->chart->chooseField = 'Choose field';
$lang->chart->aggType = 'Aggregate type';
$lang->chart->other = 'Other';
$lang->chart->unlimited = 'Unlimited';
$lang->chart->colon = 'To';
$lang->chart->updateCharts = 'Update the chart';
$lang->chart->updateCurrentChart = 'Update data in charts';
$lang->chart->fieldTypeList = array();
$lang->chart->fieldTypeList['input'] = 'Text';
+10 -8
View File
@@ -8,14 +8,16 @@ $lang->chart->acl = 'Access Control';
$lang->chart->aclList['open'] = 'Public (with chart view permissions and dimension permissions can access it)';
$lang->chart->aclList['private'] = 'Private (Only creators and whitelisted users with dimension permissions can access it)';
$lang->chart->group = 'Group';
$lang->chart->field = 'Related Field';
$lang->chart->agg = 'Aggregate';
$lang->chart->chooseField = 'Choose field';
$lang->chart->aggType = 'Aggregate type';
$lang->chart->other = 'Other';
$lang->chart->unlimited = 'Unlimited';
$lang->chart->colon = 'To';
$lang->chart->group = 'Group';
$lang->chart->field = 'Related Field';
$lang->chart->agg = 'Aggregate';
$lang->chart->chooseField = 'Choose field';
$lang->chart->aggType = 'Aggregate type';
$lang->chart->other = 'Other';
$lang->chart->unlimited = 'Unlimited';
$lang->chart->colon = 'To';
$lang->chart->updateCharts = 'Update the chart';
$lang->chart->updateCurrentChart = 'Update data in charts';
$lang->chart->fieldTypeList = array();
$lang->chart->fieldTypeList['input'] = 'Text';
+10 -8
View File
@@ -8,14 +8,16 @@ $lang->chart->acl = 'Access Control';
$lang->chart->aclList['open'] = 'Public (with chart view permissions and dimension permissions can access it)';
$lang->chart->aclList['private'] = 'Private (Only creators and whitelisted users with dimension permissions can access it)';
$lang->chart->group = 'Group';
$lang->chart->field = 'Related Field';
$lang->chart->agg = 'Aggregate';
$lang->chart->chooseField = 'Choose field';
$lang->chart->aggType = 'Aggregate type';
$lang->chart->other = 'Other';
$lang->chart->unlimited = 'Unlimited';
$lang->chart->colon = 'To';
$lang->chart->group = 'Group';
$lang->chart->field = 'Related Field';
$lang->chart->agg = 'Aggregate';
$lang->chart->chooseField = 'Choose field';
$lang->chart->aggType = 'Aggregate type';
$lang->chart->other = 'Other';
$lang->chart->unlimited = 'Unlimited';
$lang->chart->colon = 'To';
$lang->chart->updateCharts = 'Update the chart';
$lang->chart->updateCurrentChart = 'Update data in charts';
$lang->chart->fieldTypeList = array();
$lang->chart->fieldTypeList['input'] = 'Text';
+10 -8
View File
@@ -8,14 +8,16 @@ $lang->chart->acl = '访问控制';
$lang->chart->aclList['open'] = '公开(有图表视图权限与所在维度的访问权限即可访问)';
$lang->chart->aclList['private'] = '私有(仅创建者和白名单用户可访问)';
$lang->chart->group = '所属分组';
$lang->chart->field = '关联字段';
$lang->chart->agg = '汇总';
$lang->chart->chooseField = '选择字段';
$lang->chart->aggType = '统计方式';
$lang->chart->other = '其他';
$lang->chart->unlimited = '不限';
$lang->chart->colon = '至';
$lang->chart->group = '所属分组';
$lang->chart->field = '关联字段';
$lang->chart->agg = '汇总';
$lang->chart->chooseField = '选择字段';
$lang->chart->aggType = '统计方式';
$lang->chart->other = '其他';
$lang->chart->unlimited = '不限';
$lang->chart->colon = '至';
$lang->chart->updateCharts = '更新展示图表';
$lang->chart->updateCurrentChart = '更新当前图表数据';
$lang->chart->fieldTypeList = array();
$lang->chart->fieldTypeList['input'] = '文本框';
+1
View File
@@ -678,6 +678,7 @@ class chartModel extends model
$builtinCharts[] = array(10000, 10119);
$builtinCharts[] = array(10201, 10220);
$builtinCharts[] = array(20002, 20015);
$builtinCharts[] = array(30000, 30001);
$found = false; // 标记ID是否在范围内
+1
View File
@@ -57,6 +57,7 @@ $generateCharts = function() use($charts, $lang)
(
setClass('btn primary'),
setData(array('on' => 'click', 'call' => "loadChart('{$chartID}')")),
set::title($lang->chart->updateCurrentChart),
$lang->chart->query
)
) : null,
+1 -1
View File
@@ -77,7 +77,7 @@ sidebar
$treeMenu ? div
(
setClass('bg-canvas px-4 py-2 module-menu'),
btn($lang->chart->preview, setClass('primary'), on::click('previewCharts'))
btn($lang->chart->preview, setClass('primary'), set::hint($lang->chart->updateCharts), on::click('previewCharts'))
) : null,
$config->edition == 'open' ? div
(
+4
View File
@@ -105,8 +105,12 @@ $lang->ops = new stdclass();
$lang->domain = new stdclass();
$lang->service = new stdclass();
$lang->deployment = new stdclass();
$lang->deliverable = new stdclass();
$lang->metric = new stdclass();
$lang->projectDeliverable = new stdclass();
$lang->executionDeliverable = new stdclass();
$lang->ai = new stdclass();
$lang->aiapp = new stdclass();
+34 -31
View File
@@ -289,37 +289,40 @@ $lang->aiapp->common = 'AI';
$lang->product->system = 'Application';
$lang->configure->common = 'Configure';
$lang->programstakeholder->common = 'Stakeholder';
$lang->featureswitch->common = 'Features On/Off';
$lang->importdata->common = 'Import data';
$lang->systemsetting->common = 'System setting';
$lang->staffmanage->common = 'User management';
$lang->modelconfig->common = 'Pattern setting';
$lang->featureconfig->common = 'Features config';
$lang->doctemplate->common = 'Template Square';
$lang->notifysetting->common = 'Notification';
$lang->bidesign->common = 'BI design';
$lang->personalsettings->common = 'Personal setting ';
$lang->projectsettings->common = 'Setting';
$lang->dataaccess->common = 'Data permission';
$lang->executiongantt->common = 'Gantt chart';
$lang->executionkanban->common = 'Kanban';
$lang->executionburn->common = 'Burndown chart';
$lang->executioncfd->common = 'Cumulative Flow Diagram';
$lang->executionstory->common = 'Story';
$lang->executionqa->common = 'QA';
$lang->executionsettings->common = 'Setting';
$lang->generalcomment->common = 'Comment';
$lang->generalping->common = 'Timeout prevention';
$lang->generaltemplate->common = 'Template';
$lang->generaleffort->common = 'General log';
$lang->productsettings->common = 'Product setting';
$lang->projectreview->common = 'Review';
$lang->projecttrack->common = 'Matrix';
$lang->projectqa->common = 'QA';
$lang->holidayseason->common = 'Holiday';
$lang->codereview->common = 'Review';
$lang->repocode->common = 'Code';
$lang->programstakeholder->common = 'Stakeholder';
$lang->featureswitch->common = 'Features On/Off';
$lang->importdata->common = 'Import data';
$lang->systemsetting->common = 'System setting';
$lang->staffmanage->common = 'User management';
$lang->modelconfig->common = 'Pattern setting';
$lang->featureconfig->common = 'Features config';
$lang->doctemplate->common = 'Doc template';
$lang->notifysetting->common = 'Notification';
$lang->bidesign->common = 'BI design';
$lang->personalsettings->common = 'Personal setting ';
$lang->projectsettings->common = 'Setting';
$lang->dataaccess->common = 'Data permission';
$lang->executiongantt->common = 'Gantt chart';
$lang->executionkanban->common = 'Kanban';
$lang->executionburn->common = 'Burndown chart';
$lang->executioncfd->common = 'Cumulative Flow Diagram';
$lang->executionstory->common = 'Story';
$lang->executionqa->common = 'QA';
$lang->executionsettings->common = 'Setting';
$lang->generalcomment->common = 'Comment';
$lang->generalping->common = 'Timeout prevention';
$lang->generaltemplate->common = 'Template';
$lang->generaleffort->common = 'General log';
$lang->productsettings->common = 'Product setting';
$lang->projectreview->common = 'Review';
$lang->projecttrack->common = 'Matrix';
$lang->projectqa->common = 'QA';
$lang->holidayseason->common = 'Holiday';
$lang->codereview->common = 'Review';
$lang->repocode->common = 'Code';
$lang->deliverable->common = 'Deliverable';
$lang->projectDeliverable->common = 'Project Deliverable';
$lang->executionDeliverable->common = 'Execution Deliverable';
$lang->personnel->common = 'Member';
$lang->personnel->invest = 'Investment';
+34 -31
View File
@@ -289,37 +289,40 @@ $lang->aiapp->common = 'AI';
$lang->product->system = 'Application';
$lang->configure->common = 'Configure';
$lang->programstakeholder->common = 'Stakeholder';
$lang->featureswitch->common = 'Features On/Off';
$lang->importdata->common = 'Import data';
$lang->systemsetting->common = 'System setting';
$lang->staffmanage->common = 'User management';
$lang->modelconfig->common = 'Pattern setting';
$lang->featureconfig->common = 'Features config';
$lang->doctemplate->common = 'Template Square';
$lang->notifysetting->common = 'Notification';
$lang->bidesign->common = 'BI design';
$lang->personalsettings->common = 'Personal setting ';
$lang->projectsettings->common = 'Setting';
$lang->dataaccess->common = 'Data permission';
$lang->executiongantt->common = 'Gantt chart';
$lang->executionkanban->common = 'Kanban';
$lang->executionburn->common = 'Burndown chart';
$lang->executioncfd->common = 'Cumulative Flow Diagram';
$lang->executionstory->common = 'Story';
$lang->executionqa->common = 'QA';
$lang->executionsettings->common = 'Setting';
$lang->generalcomment->common = 'Comment';
$lang->generalping->common = 'Timeout prevention';
$lang->generaltemplate->common = 'Template';
$lang->generaleffort->common = 'General log';
$lang->productsettings->common = 'Product setting';
$lang->projectreview->common = 'Review';
$lang->projecttrack->common = 'Matrix';
$lang->projectqa->common = 'QA';
$lang->holidayseason->common = 'Holiday';
$lang->codereview->common = 'Review';
$lang->repocode->common = 'Code';
$lang->programstakeholder->common = 'Stakeholder';
$lang->featureswitch->common = 'Features On/Off';
$lang->importdata->common = 'Import data';
$lang->systemsetting->common = 'System setting';
$lang->staffmanage->common = 'User management';
$lang->modelconfig->common = 'Pattern setting';
$lang->featureconfig->common = 'Features config';
$lang->doctemplate->common = 'Doc template';
$lang->notifysetting->common = 'Notification';
$lang->bidesign->common = 'BI design';
$lang->personalsettings->common = 'Personal setting ';
$lang->projectsettings->common = 'Setting';
$lang->dataaccess->common = 'Data permission';
$lang->executiongantt->common = 'Gantt chart';
$lang->executionkanban->common = 'Kanban';
$lang->executionburn->common = 'Burndown chart';
$lang->executioncfd->common = 'Cumulative Flow Diagram';
$lang->executionstory->common = 'Story';
$lang->executionqa->common = 'QA';
$lang->executionsettings->common = 'Setting';
$lang->generalcomment->common = 'Comment';
$lang->generalping->common = 'Timeout prevention';
$lang->generaltemplate->common = 'Template';
$lang->generaleffort->common = 'General log';
$lang->productsettings->common = 'Product setting';
$lang->projectreview->common = 'Review';
$lang->projecttrack->common = 'Matrix';
$lang->projectqa->common = 'QA';
$lang->holidayseason->common = 'Holiday';
$lang->codereview->common = 'Review';
$lang->repocode->common = 'Code';
$lang->deliverable->common = 'Deliverable';
$lang->projectDeliverable->common = 'Project Deliverable';
$lang->executionDeliverable->common = 'Execution Deliverable';
$lang->personnel->common = 'Member';
$lang->personnel->invest = 'Investment';
+34 -31
View File
@@ -289,37 +289,40 @@ $lang->aiapp->common = 'AI';
$lang->product->system = 'Application';
$lang->configure->common = 'Configure';
$lang->programstakeholder->common = 'Stakeholder';
$lang->featureswitch->common = 'Features On/Off';
$lang->importdata->common = 'Import data';
$lang->systemsetting->common = 'System setting';
$lang->staffmanage->common = 'User management';
$lang->modelconfig->common = 'Pattern setting';
$lang->featureconfig->common = 'Features config';
$lang->doctemplate->common = 'Template Square';
$lang->notifysetting->common = 'Notification';
$lang->bidesign->common = 'BI design';
$lang->personalsettings->common = 'Personal setting ';
$lang->projectsettings->common = 'Setting';
$lang->dataaccess->common = 'Data permission';
$lang->executiongantt->common = 'Gantt chart';
$lang->executionkanban->common = 'Kanban';
$lang->executionburn->common = 'Burndown chart';
$lang->executioncfd->common = 'Cumulative Flow Diagram';
$lang->executionstory->common = 'Story';
$lang->executionqa->common = 'QA';
$lang->executionsettings->common = 'Setting';
$lang->generalcomment->common = 'Comment';
$lang->generalping->common = 'Timeout prevention';
$lang->generaltemplate->common = 'Template';
$lang->generaleffort->common = 'General log';
$lang->productsettings->common = 'Product setting';
$lang->projectreview->common = 'Review';
$lang->projecttrack->common = 'Matrix';
$lang->projectqa->common = 'QA';
$lang->holidayseason->common = 'Holiday';
$lang->codereview->common = 'Review';
$lang->repocode->common = 'Code';
$lang->programstakeholder->common = 'Stakeholder';
$lang->featureswitch->common = 'Features On/Off';
$lang->importdata->common = 'Import data';
$lang->systemsetting->common = 'System setting';
$lang->staffmanage->common = 'User management';
$lang->modelconfig->common = 'Pattern setting';
$lang->featureconfig->common = 'Features config';
$lang->doctemplate->common = 'Doc template';
$lang->notifysetting->common = 'Notification';
$lang->bidesign->common = 'BI design';
$lang->personalsettings->common = 'Personal setting ';
$lang->projectsettings->common = 'Setting';
$lang->dataaccess->common = 'Data permission';
$lang->executiongantt->common = 'Gantt chart';
$lang->executionkanban->common = 'Kanban';
$lang->executionburn->common = 'Burndown chart';
$lang->executioncfd->common = 'Cumulative Flow Diagram';
$lang->executionstory->common = 'Story';
$lang->executionqa->common = 'QA';
$lang->executionsettings->common = 'Setting';
$lang->generalcomment->common = 'Comment';
$lang->generalping->common = 'Timeout prevention';
$lang->generaltemplate->common = 'Template';
$lang->generaleffort->common = 'General log';
$lang->productsettings->common = 'Product setting';
$lang->projectreview->common = 'Review';
$lang->projecttrack->common = 'Matrix';
$lang->projectqa->common = 'QA';
$lang->holidayseason->common = 'Holiday';
$lang->codereview->common = 'Review';
$lang->repocode->common = 'Code';
$lang->deliverable->common = 'Deliverable';
$lang->projectDeliverable->common = 'Project Deliverable';
$lang->executionDeliverable->common = 'Execution Deliverable';
$lang->personnel->common = 'Member';
$lang->personnel->invest = 'Investment';
+2 -1
View File
@@ -240,7 +240,7 @@ if(helper::hasFeature('devops')) $lang->scrum->menu->devops = array('link'
$lang->scrum->menu->build = array('link' => "{$lang->build->common}|projectbuild|browse|project=%s", 'subModule' => 'projectbuild');
$lang->scrum->menu->release = array('link' => "{$lang->release->common}|projectrelease|browse|project=%s", 'subModule' => 'projectrelease,system');
$lang->scrum->menu->dynamic = array('link' => "$lang->dynamic|project|dynamic|project=%s");
$lang->scrum->menu->settings = array('link' => "$lang->settings|project|view|project=%s", 'subModule' => 'tree,stakeholder', 'alias' => 'edit,manageproducts,group,managemembers,manageview,managepriv,whitelist,addwhitelist,team', 'exclude' => 'tree-browsetask');
$lang->scrum->menu->settings = array('link' => "$lang->settings|project|view|project=%s", 'subModule' => 'tree,stakeholder', 'alias' => 'edit,manageproducts,group,managemembers,manageview,managepriv,whitelist,addwhitelist,team,workflowgroup', 'exclude' => 'tree-browsetask');
$lang->scrum->dividerMenu = ',execution,programplan,doc,settings,';
@@ -783,6 +783,7 @@ $lang->navGroup->extension = 'admin';
$lang->navGroup->action = 'admin';
$lang->navGroup->convert = 'admin';
$lang->navGroup->stage = 'admin';
$lang->navGroup->deliverable = 'admin';
$lang->navGroup->featureswitch = 'admin';
$lang->navGroup->importdata = 'admin';
$lang->navGroup->systemsetting = 'admin';
+34 -31
View File
@@ -289,37 +289,40 @@ $lang->aiapp->common = 'AI';
$lang->product->system = '应用';
$lang->configure->common = '配置';
$lang->programstakeholder->common = '干系人';
$lang->featureswitch->common = '功能开关';
$lang->importdata->common = '数据导入';
$lang->systemsetting->common = '系统设置';
$lang->staffmanage->common = '人员管理';
$lang->modelconfig->common = '模型配置';
$lang->featureconfig->common = '功能配置';
$lang->doctemplate->common = '模板广场';
$lang->notifysetting->common = '通知设置';
$lang->bidesign->common = 'BI设计';
$lang->personalsettings->common = '个人设置';
$lang->projectsettings->common = '设置';
$lang->dataaccess->common = '数据权限';
$lang->executiongantt->common = '甘特图';
$lang->executionkanban->common = '看板';
$lang->executionburn->common = '燃尽图';
$lang->executioncfd->common = '累积流图';
$lang->executionstory->common = '研发需求';
$lang->executionqa->common = '测试';
$lang->executionsettings->common = '设置';
$lang->generalcomment->common = '备注';
$lang->generalping->common = '防超时';
$lang->generaltemplate->common = '模板';
$lang->generaleffort->common = '通用日志';
$lang->productsettings->common = '产品设置';
$lang->projectreview->common = '评审';
$lang->projecttrack->common = '矩阵';
$lang->projectqa->common = '测试';
$lang->holidayseason->common = '节假日';
$lang->codereview->common = '问题';
$lang->repocode->common = '代码';
$lang->programstakeholder->common = '干系人';
$lang->featureswitch->common = '功能开关';
$lang->importdata->common = '数据导入';
$lang->systemsetting->common = '系统设置';
$lang->staffmanage->common = '人员管理';
$lang->modelconfig->common = '项目模型配置';
$lang->featureconfig->common = '功能配置';
$lang->doctemplate->common = '文档模板';
$lang->notifysetting->common = '通知设置';
$lang->bidesign->common = 'BI设计';
$lang->personalsettings->common = '个人设置';
$lang->projectsettings->common = '设置';
$lang->dataaccess->common = '数据权限';
$lang->executiongantt->common = '甘特图';
$lang->executionkanban->common = '看板';
$lang->executionburn->common = '燃尽图';
$lang->executioncfd->common = '累积流图';
$lang->executionstory->common = '研发需求';
$lang->executionqa->common = '测试';
$lang->executionsettings->common = '设置';
$lang->generalcomment->common = '备注';
$lang->generalping->common = '防超时';
$lang->generaltemplate->common = '模板';
$lang->generaleffort->common = '通用日志';
$lang->productsettings->common = '产品设置';
$lang->projectreview->common = '评审';
$lang->projecttrack->common = '矩阵';
$lang->projectqa->common = '测试';
$lang->holidayseason->common = '节假日';
$lang->codereview->common = '问题';
$lang->repocode->common = '代码';
$lang->deliverable->common = '交付物';
$lang->projectDeliverable->common = '项目交付物';
$lang->executionDeliverable->common = '执行交付物';
$lang->personnel->common = '人员';
$lang->personnel->invest = '投入人员';
-44
View File
@@ -1059,50 +1059,6 @@ class commonModel extends model
$this->session->set($objectType . 'BrowseList', array(), $this->app->tab);
}
/**
* 批量创建时,移除名称重复的对象。
* Remove duplicate for story, task, bug, case, doc.
*
* @param string $type e.g. story task bug case doc.
* @param array|object $data
* @param string $condition
* @access public
* @return array|false
*/
public function removeDuplicate(string $type, object|array $data, string $condition = ''): array|false
{
$table = zget($this->config->objectTables, $type, '');
if(empty($table)) return array('stop' => false, 'data' => $data);
$titleField = $type == 'task' ? 'name' : 'title';
$date = date(DT_DATETIME1, time() - $this->config->duplicateTime);
$dateField = $type == 'doc' ? 'addedDate' : 'openedDate';
$titles = zget($data, $titleField, array());
$storyType = zget($data, 'type', '');
if(empty($titles)) return false;
$duplicate = $this->dao->select("id,$titleField")->from($table)
->where('deleted')->eq(0)
->andWhere($titleField)->in($titles)
->andWhere($dateField)->ge($date)->fi()
->beginIF($condition)->andWhere($condition)->fi()
->beginIF($type == 'story')->andWhere('type')->eq($storyType)
->fetchPairs();
if($duplicate and is_string($titles)) return array('stop' => true, 'duplicate' => key($duplicate));
if($duplicate and is_array($titles))
{
foreach($titles as $i => $title)
{
if(in_array($title, $duplicate)) unset($titles[$i]);
}
if(is_object($data)) $data->$titleField = $titles;
if(is_array($data)) $data[$titleField] = $titles;
}
return array('stop' => false, 'data' => $data);
}
/**
* 追加排序字段。
* Append order by.
@@ -1,149 +0,0 @@
#!/usr/bin/env php
<?php
include dirname(__FILE__, 5) . '/test/lib/init.php';
su('admin');
$story = zenData('story');
$story->id->range('1');
$story->title->range('teststory');
$story->gen(1);
$case = zenData('case');
$case->id->range('1');
$case->title->range('testcase');
$case->gen(1);
$task = zenData('task');
$task->id->range('1');
$task->name->range('testtask');
$task->gen(1);
$bug = zenData('bug');
$bug->id->range('1');
$bug->title->range('testbug');
$bug->gen(1);
$doc = zenData('doc');
$doc->id->range('1');
$doc->title->range('testdoc');
$doc->gen(1);
/**
title=测试 commonModel->removeDuplicate();
timeout=0
cid=1
- 测试是否是重复需求
- 属性stop @1
- 属性duplicate @1
- 有条件情况下,测试是否是重复需求。属性stop @~~
- 测试是否是重复用例
- 属性stop @1
- 属性duplicate @1
- 有条件情况下,测试是否是重复用例。属性stop @~~
- 测试是否是重复任务
- 属性stop @1
- 属性duplicate @1
- 有条件情况下,测试是否是重复用例。属性stop @~~
- 测试是否是重复Bug
- 属性stop @1
- 属性duplicate @1
- 有条件情况下,测试是否是重复Bug属性stop @~~
- 测试是否是重复文档
- 属性stop @1
- 属性duplicate @1
- 有条件情况下,测试是否是重复文档属性stop @~~
- 测试批量重复需求 @story1
- 有条件情况下,测试批量重复需求 @2
- 测试批量重复用例 @case1
- 有条件情况下,测试批量重复用例 @2
- 测试批量重复任务 @task1
- 有条件情况下,测试批量重复任务 @2
- 测试批量重复Bug @bug1
- 有条件情况下,测试批量重复Bug @2
- 测试批量重复文档 @doc1
- 有条件情况下,测试批量重复文档 @2
*/
global $tester;
$tester->loadModel('common');
$now = date('Y-m-d H:i:s', time() - 5);
$tester->common->dao->update(TABLE_STORY)->set('openedDate')->eq($now)->exec();
$tester->common->dao->update(TABLE_CASE)->set('openedDate')->eq($now)->exec();
$tester->common->dao->update(TABLE_TASK)->set('openedDate')->eq($now)->exec();
$tester->common->dao->update(TABLE_BUG)->set('openedDate')->eq($now)->exec();
$tester->common->dao->update(TABLE_DOC)->set('addedDate')->eq($now)->exec();
$story = new stdclass();
$story->title = 'teststory';
$story->type = 'requirement';
r($tester->common->removeDuplicate('story', $story)) && p('stop,duplicate') && e('1,1'); //测试是否是重复需求
r($tester->common->removeDuplicate('story', $story, 'id!=1')) && p('stop') && e('~~'); //有条件情况下,测试是否是重复需求。
$case = new stdclass();
$case->title = 'testcase';
r($tester->common->removeDuplicate('case', $case)) && p('stop,duplicate') && e('1,1'); //测试是否是重复用例
r($tester->common->removeDuplicate('case', $case, 'id!=1')) && p('stop') && e('~~'); //有条件情况下,测试是否是重复用例。
$task = new stdclass();
$task->name = 'testtask';
r($tester->common->removeDuplicate('task', $task)) && p('stop,duplicate') && e('1,1'); //测试是否是重复任务
r($tester->common->removeDuplicate('task', $task, 'id!=1')) && p('stop') && e('~~'); //有条件情况下,测试是否是重复用例。
$bug = new stdclass();
$bug->title = 'testbug';
r($tester->common->removeDuplicate('bug', $bug)) && p('stop,duplicate') && e('1,1'); //测试是否是重复Bug
r($tester->common->removeDuplicate('bug', $bug, 'id!=1')) && p('stop') && e('~~'); //有条件情况下,测试是否是重复Bug
$doc = new stdclass();
$doc->title = 'testdoc';
r($tester->common->removeDuplicate('doc', $doc)) && p('stop,duplicate') && e('1,1'); //测试是否是重复文档
r($tester->common->removeDuplicate('doc', $doc, 'id!=1')) && p('stop') && e('~~'); //有条件情况下,测试是否是重复文档
$story = new stdclass();
$story->title = array('teststory', 'story1');
$result = $tester->common->removeDuplicate('story', $story);
r($result['data']->title[1]) && p() && e('story1'); //测试批量重复需求
$story->title = array('teststory', 'story1');
$result = $tester->common->removeDuplicate('story', $story, 'id!=1');
r(count($result['data']->title)) && p() && e('2'); //有条件情况下,测试批量重复需求
$case = new stdclass();
$case->title = array('testcase', 'case1');
$result = $tester->common->removeDuplicate('case', $case);
r($result['data']->title[1]) && p() && e('case1'); //测试批量重复用例
$case->title = array('testcase', 'case1');
$result = $tester->common->removeDuplicate('case', $case, 'id!=1');
r(count($result['data']->title)) && p() && e('2'); //有条件情况下,测试批量重复用例
$task = new stdclass();
$task->name = array('testtask', 'task1');
$result = $tester->common->removeDuplicate('task', $task);
r($result['data']->name[1]) && p() && e('task1'); //测试批量重复任务
$task->name = array('testtask', 'task1');
$result = $tester->common->removeDuplicate('task', $task, 'id!=1');
r(count($result['data']->name)) && p() && e('2'); //有条件情况下,测试批量重复任务
$bug = new stdclass();
$bug->title = array('testbug', 'bug1');
$result = $tester->common->removeDuplicate('bug', $bug);
r($result['data']->title[1]) && p() && e('bug1'); //测试批量重复Bug
$bug->title = array('testbug', 'bug1');
$result = $tester->common->removeDuplicate('bug', $bug, 'id!=1');
r(count($result['data']->title)) && p() && e('2'); //有条件情况下,测试批量重复Bug
$doc = new stdclass();
$doc->title = array('testdoc', 'doc1');
$result = $tester->common->removeDuplicate('doc', $doc);
r($result['data']->title[1]) && p() && e('doc1'); //测试批量重复文档
$doc->title = array('testdoc', 'doc1');
$result = $tester->common->removeDuplicate('doc', $doc, 'id!=1');
r(count($result['data']->title)) && p() && e('2'); //有条件情况下,测试批量重复文档
@@ -10,6 +10,9 @@ cid=1
- 仅保留WHERE条件 @id = 1
- 保留完整SQL语句 @SELECT * FROM zt_execution WHERE id = 1
- 仅保留WHERE条件 @1=1
- 仅保留WHERE条件 @id = 1 and type = "story"
- 仅保留WHERE条件 @id = 1 and type = "epic"
*/
@@ -17,6 +20,12 @@ global $tester;
$tester->loadModel('common')->saveQueryCondition('SELECT * FROM zt_task WHERE id = 1', 'task', true);
$tester->loadModel('common')->saveQueryCondition('SELECT * FROM zt_execution WHERE id = 1', 'execution', false);
$tester->loadModel('common')->saveQueryCondition('', 'testcase', true);
$tester->loadModel('common')->saveQueryCondition('SELECT * FROM zt_story WHERE id = 1 and type = "story"', 'story', true);
$tester->loadModel('common')->saveQueryCondition('SELECT * FROM zt_epic WHERE id = 1 and type = "epic"', 'epic', true);
r($tester->session->taskQueryCondition) && p('') && e('id = 1'); // 仅保留WHERE条件
r($tester->session->executionQueryCondition) && p('') && e('SELECT * FROM zt_execution WHERE id = 1'); // 保留完整SQL语句
r($tester->session->executionQueryCondition) && p('') && e('SELECT * FROM zt_execution WHERE id = 1'); // 保留完整SQL语句
r($tester->session->testcaseQueryCondition) && p('') && e('1=1'); // 仅保留WHERE条件
r($tester->session->storyQueryCondition) && p('') && e('id = 1 and type = "story"'); // 仅保留WHERE条件
r($tester->session->epicQueryCondition) && p('') && e('id = 1 and type = "epic"'); // 仅保留WHERE条件
+1 -1
View File
@@ -61,7 +61,7 @@
<?php if(!empty($action->history)):?>
<button type='button' class='btn btn-mini switch-btn btn-icon btn-expand' title='<?php echo $lang->switchDisplay;?>'><i class='change-show icon icon-plus icon-sm'></i></button>
<div class='history-changes' id='changeBox<?php echo $i;?>'>
<?php echo $this->action->printChanges($action->objectType, $action->history);?>
<?php echo $this->action->printChanges($action->objectType, $action->objectID, $action->history);?>
</div>
<?php endif;?>
<?php if(strlen(trim(($action->comment))) != 0):?>
+1 -1
View File
@@ -28,7 +28,7 @@ if(file_exists($extViewFile))
<?php if(!empty($action->history)):?>
<tr>
<td style='padding: 10px;'>
<div><?php $this->action->printChanges($action->objectType, $action->history, false);?></div>
<div><?php $this->action->printChanges($action->objectType, $action->objectID, $action->history, false);?></div>
</td>
</tr>
<?php endif;?>
+1 -1
View File
@@ -439,7 +439,7 @@ class custom extends control
$this->loadModel('common')->loadConfigFromDB();
$this->app->loadLang($module);
$this->app->loadConfig($module);
$this->app->loadConfig($module, '', true);
if($module == 'programplan' && $section == 'custom') $key = 'createFields';
$customFields = zget(zget($this->config->$module, 'list', array()), $section . ucfirst($key), '');
+10 -12
View File
@@ -446,25 +446,23 @@ class datatableModel extends model
*/
public function appendWorkflowFields(string $module, string $method): array
{
if(in_array($module, array('epic', 'story', 'requirement')))
if($module == 'build' && $method == 'build')
{
$method = $module == 'story' ? 'browse' : $module; // 需求加载product-browse的layout配置。
$module = 'product';
$module = 'build';
$method = 'browse'; // 版本加载build-browse的layout配置。
}
elseif($module == 'build')
elseif($module == 'task' && $method == 'task')
{
$module = 'execution';
$method = 'build'; // 版本加载execution-build的layout配置。
}
elseif($module == 'task')
{
$module = 'execution';
$method = 'task'; // 任务加载execution-task的layout配置。
$method = 'browse'; // 任务加载task-browse的layout配置。
}
elseif($module == 'bug' && $method == 'bug')
{
$method = 'browse'; // 执行bug列表加载bug-browse的layout配置。
}
elseif($module == 'story' && $method == 'story')
{
$method = 'browse'; // 执行需求列表加载story-browse的layout配置。
}
elseif($module == 'testcase' && $method == 'testcase')
{
$method = 'browse'; // 执行用例列表加载testcase-browse的layout配置。
@@ -520,4 +518,4 @@ class datatableModel extends model
return $this->loadModel('flow')->buildDtableCols($fields, [], [], isset($flow->buildin) && !$flow->buildin);
}
}
}
+3 -1
View File
@@ -33,7 +33,9 @@ function query(callback) {
$('.query').addClass('disabled');
$('#querying').removeClass('hidden');
$.post(createLink('dataview', 'ajaxQuery'), {sql: $('#sql').val(), driver: DataStorage.driver, filters: filters, recPerPage: DataStorage.recPerPage, pageID: DataStorage.pageID}, function(resp)
var sql = $('#sql').val();
sql = btoa(sql);
$.post(createLink('dataview', 'ajaxQuery'), {sql: sql, driver: DataStorage.driver, filters: filters, recPerPage: DataStorage.recPerPage, pageID: DataStorage.pageID}, function(resp)
{
resp = JSON.parse(resp);
$('.query').removeClass('disabled');
+2 -2
View File
@@ -23,7 +23,7 @@ class designModel extends model
public function create(object $design): bool|int
{
$design = $this->loadModel('file')->processImgURL($design, 'desc', (string)$this->post->uid);
$this->dao->insert(TABLE_DESIGN)->data($design)
$this->dao->insert(TABLE_DESIGN)->data($design, 'docVersions')
->autoCheck()
->batchCheck($this->config->design->create->requiredFields, 'notempty')
->exec();
@@ -97,7 +97,7 @@ class designModel extends model
if(!$oldDesign) return false;
$design = $this->loadModel('file')->processImgURL($design, 'desc', (string)$this->post->uid);
$this->dao->update(TABLE_DESIGN)->data($design, 'deleteFiles,renameFiles,files')->autoCheck()->batchCheck($this->config->design->edit->requiredFields, 'notempty')->where('id')->eq($designID)->exec();
$this->dao->update(TABLE_DESIGN)->data($design, 'deleteFiles,renameFiles,files,docs,oldDocs,docVersions')->autoCheck()->batchCheck($this->config->design->edit->requiredFields, 'notempty')->where('id')->eq($designID)->exec();
if(dao::isError()) return false;
+1
View File
@@ -85,6 +85,7 @@ formPanel
),
formRow
(
setID('files'),
formGroup
(
set::label($lang->design->file),
+1
View File
@@ -75,6 +75,7 @@ formPanel
),
formGroup
(
setID('files'),
set::label($lang->design->file),
fileSelector($design->files ? set::defaultFiles(array_values($design->files)) : null)
),
+1
View File
@@ -78,6 +78,7 @@ detailBody
(
section
(
setID('desc'),
set::title($lang->design->desc),
set::content(empty($design->desc) ? $lang->noDesc : $design->desc),
set::useHtml(true)
+1
View File
@@ -29,6 +29,7 @@ $lang->dev->ER = 'Epic';
$lang->dev->UR = 'Feature';
$lang->dev->SR = 'Story';
$lang->dev->branch = 'Branch';
$lang->dev->apiBaseUrl = 'Base URL';
$lang->dev->fields = array();
$lang->dev->fields['id'] = 'ID';
+1
View File
@@ -29,6 +29,7 @@ $lang->dev->ER = 'Epic';
$lang->dev->UR = 'Feature';
$lang->dev->SR = 'Story';
$lang->dev->branch = 'Branch';
$lang->dev->apiBaseUrl = 'Base URL';
$lang->dev->fields = array();
$lang->dev->fields['id'] = 'ID';
+1
View File
@@ -29,6 +29,7 @@ $lang->dev->ER = 'Epic';
$lang->dev->UR = 'Feature';
$lang->dev->SR = 'Story';
$lang->dev->branch = 'Branch';
$lang->dev->apiBaseUrl = 'Base URL';
$lang->dev->fields = array();
$lang->dev->fields['id'] = 'ID';
+1
View File
@@ -29,6 +29,7 @@ $lang->dev->ER = '业务需求';
$lang->dev->UR = '用户需求';
$lang->dev->SR = '软件需求';
$lang->dev->branch = '平台/分支';
$lang->dev->apiBaseUrl = '请求基路径';
$lang->dev->fields = array();
$lang->dev->fields['id'] = '序号';
+9 -1
View File
@@ -187,8 +187,15 @@ $fnGetResponseContent = function($api) use($parseTree, $typeList)
$fnBuildAPIContent = function() use($api, $fnGetHeaderContent, $fnGetQueryContent, $fnGetParamsContent, $fnGetResponseContent)
{
global $lang, $app;
$content = array();
$content[] = div
(
setClass('pb-3 font-bold'),
$lang->dev->apiBaseUrl . ': ' . commonModel::getSysURL() . $app->config->webRoot . 'api.php/v1'
);
$content[] = div
(
setClass('panel-heading'),
div(setClass('http-method label'), $api->method),
@@ -235,7 +242,8 @@ sidebar
setClass('h-10 flex items-center pl-4 flex-none gap-3'),
div(setClass('text-lg font-semibold flex items-center'), icon(setClass('pr-2'), 'list'), span($lang->dev->moduleList))
),
treeEditor(set(array('className' => 'pl-3', 'items' => $moduleTree, 'canEdit' => false, 'canDelete' => false, 'canSplit' => false)))
treeEditor(set(array('className' => 'pl-3', 'items' => $moduleTree, 'canEdit' => false, 'canDelete' => false, 'canSplit' => false))),
set::toggleBtn(false)
);
div
+6
View File
@@ -325,6 +325,8 @@ $lang->doc->uploadFormat = 'Upload Format';
$lang->doc->editedList = 'File editor';
$lang->doc->moveTo = 'Move to';
$lang->doc->notSupportExport = 'This document does not support export';
$lang->doc->downloadTemplate = 'Download Template';
$lang->doc->addFile = 'Add File';
$lang->doc->preview = 'Preview';
$lang->doc->insertTitle = 'Insert %s list';
@@ -517,6 +519,7 @@ $lang->doc->noCollectedDoc = 'Sie haben kein Dokument gesammelt.';
$lang->doc->errorEmptyLib = 'No data in document library.';
$lang->doc->confirmUpdateContent = 'You have a document that is not saved from last time. Do you want to continue editing it?';
$lang->doc->selectLibType = 'Please select a type of doc library.';
$lang->doc->selectDoc = 'Please select a doc';
$lang->doc->noLibreOffice = 'You does not have access to office conversion settings!';
$lang->doc->errorParentChapter = 'The parent chapter cannot be its own chapter or sub chapter!';
$lang->doc->errorOthersCreated = 'There are documents created by others in this library. You cannot move it.';
@@ -774,6 +777,9 @@ $lang->doc->docLang->addSubDoc = $lang->doc->addSubDoc;
$lang->doc->docLang->chapterName = $lang->doc->chapterName;
$lang->doc->docLang->autoSaveHint = 'Auto saved';
$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->moduleName = array();
$lang->docTemplate->moduleName['plan'] = 'plan';
+6
View File
@@ -325,6 +325,8 @@ $lang->doc->uploadFormat = 'Upload Format';
$lang->doc->editedList = 'File editor';
$lang->doc->moveTo = 'Move to';
$lang->doc->notSupportExport = 'This document does not support export';
$lang->doc->downloadTemplate = 'Download Template';
$lang->doc->addFile = 'Add File';
$lang->doc->preview = 'Preview';
$lang->doc->insertTitle = 'Insert %s list';
@@ -517,6 +519,7 @@ $lang->doc->noCollectedDoc = 'You have not favorited any documents.
$lang->doc->errorEmptyLib = 'No data in document library.';
$lang->doc->confirmUpdateContent = 'You have a document that is not saved from last time. Do you want to continue editing it?';
$lang->doc->selectLibType = 'Please select a type of doc library.';
$lang->doc->selectDoc = 'Please select a doc';
$lang->doc->noLibreOffice = 'You does not have access to office conversion settings!';
$lang->doc->errorParentChapter = 'The parent chapter cannot be its own chapter or sub chapter!';
$lang->doc->errorOthersCreated = 'There are documents created by others in this library. You cannot move it.';
@@ -774,6 +777,9 @@ $lang->doc->docLang->addSubDoc = $lang->doc->addSubDoc;
$lang->doc->docLang->chapterName = $lang->doc->chapterName;
$lang->doc->docLang->autoSaveHint = 'Auto saved';
$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->moduleName = array();
$lang->docTemplate->moduleName['plan'] = 'plan';
+6
View File
@@ -325,6 +325,8 @@ $lang->doc->uploadFormat = 'Upload Format';
$lang->doc->editedList = 'File editor';
$lang->doc->moveTo = 'Move to';
$lang->doc->notSupportExport = 'This document does not support export';
$lang->doc->downloadTemplate = 'Download Template';
$lang->doc->addFile = 'Add File';
$lang->doc->preview = 'Preview';
$lang->doc->insertTitle = 'Insert %s list';
@@ -517,6 +519,7 @@ $lang->doc->noCollectedDoc = "Vous avez aucun document dans vos fav
$lang->doc->errorEmptyLib = 'No data in document library.';
$lang->doc->confirmUpdateContent = 'You have a document that is not saved from last time. Do you want to continue editing it?';
$lang->doc->selectLibType = 'Please select a type of doc library.';
$lang->doc->selectDoc = 'Please select a doc';
$lang->doc->noLibreOffice = 'You does not have access to office conversion settings!';
$lang->doc->errorParentChapter = 'The parent chapter cannot be its own chapter or sub chapter!';
$lang->doc->errorOthersCreated = 'There are documents created by others in this library. You cannot move it.';
@@ -774,6 +777,9 @@ $lang->doc->docLang->addSubDoc = $lang->doc->addSubDoc;
$lang->doc->docLang->chapterName = $lang->doc->chapterName;
$lang->doc->docLang->autoSaveHint = 'Auto saved';
$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->moduleName = array();
$lang->docTemplate->moduleName['plan'] = 'plan';
+6
View File
@@ -325,6 +325,8 @@ $lang->doc->uploadFormat = '上传格式';
$lang->doc->editedList = '文档编辑者';
$lang->doc->moveTo = '移动至';
$lang->doc->notSupportExport = '(此文档暂不支持导出)';
$lang->doc->downloadTemplate = '下载模板';
$lang->doc->addFile = '提交文件';
$lang->doc->preview = '预览';
$lang->doc->insertTitle = '插入%s列表';
@@ -517,6 +519,7 @@ $lang->doc->noCollectedDoc = '您还没有收藏任何文档。';
$lang->doc->errorEmptyLib = '文档库暂无数据。';
$lang->doc->confirmUpdateContent = '检查到您有未保存的文档内容,是否继续编辑?';
$lang->doc->selectLibType = '请选择文档库类型';
$lang->doc->selectDoc = '请选择文档';
$lang->doc->noLibreOffice = '您还没有office转换设置访问权限!';
$lang->doc->errorParentChapter = '父章节不能是自身章节及子章节!';
$lang->doc->errorOthersCreated = '该库下其他人创建的文档暂不支持移动,是否确认移动?';
@@ -774,6 +777,9 @@ $lang->doc->docLang->addSubDoc = $lang->doc->addSubDoc;
$lang->doc->docLang->chapterName = $lang->doc->chapterName;
$lang->doc->docLang->autoSaveHint = '已自动保存';
$lang->doc->docLang->editing = '正在编辑';
$lang->doc->docLang->restoreVersionHint = '恢复到版本';
$lang->doc->docLang->restoreVersion = '恢复';
$lang->doc->docLang->restoreVersionConfirm = '这将使用文档版本 {version} 的内容创建一个新的版本,确定要继续吗?';
$lang->docTemplate->moduleName = array();
$lang->docTemplate->moduleName['plan'] = '计划';

Some files were not shown because too many files have changed in this diff Show More