Merge main to feature/doctemplate.

This commit is contained in:
wangyuting
2025-03-06 17:12:10 +08:00
parent 4d1b9d7cbb
commit df2bfa3feb
16 changed files with 5170 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+26
View File
@@ -0,0 +1,26 @@
window.getFileActions = function(file)
{
let fileActions = [];
let canPreview = false;
let officeTypes = 'doc|docx|xls|xlsx|ppt|pptx|pdf';
let isOfficeFile = officeTypes.includes(file.extension);
let previewExtension = 'txt|jpg|jpeg|gif|png|bmp|mp4';
if(previewExtension.includes(file.extension)) canPreview = true;
if(libreOfficeTurnon && isOfficeFile) canPreview = true;
if(canPreview)
{
let previewAction = {icon: 'eye', title: previewLang, url: previewLink.replace('{id}', file.id).replace('\\', ''), className: 'text-primary', target: '_blank'};
if(!isOfficeFile)
{
previewAction['data-toggle'] = 'modal';
previewAction['data-size'] = 'lg';
delete previewAction.target;
}
fileActions.push(previewAction);
}
fileActions.push({icon: 'download', title: downloadLang, url: downloadLink.replace('{id}', file.id).replace('\\', ''), className: 'text-primary', target: '_blank'});
return fileActions;
}
@@ -0,0 +1,26 @@
<?php
include dirname(__FILE__, 5) . '/test/lib/ui.php';
class modeManagementTester extends tester
{
/**
* 切换管理模式。
* Mode system management.
*
* @param string $programName
* @access public
* @return void
*/
public function modeManagement($programName)
{
$this->openUrl('admin', 'index');
$form = $this->loadPage('admin', 'index');
$form->dom->systemSetting->click();
$form->wait(1);
$form->dom->useLight->click();
$form->wait(1);
$form->dom->comfirmBtn->click();
$form->wait(1);
if($form->dom->secTop->getText() != '产品') return $this->failed('切换轻量级模式失败');
return $this->success('切换轻量级模式成功');
}
}
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env php
<?php
/**
title=切换管理模式测试
timeout=0
- 切换轻量级模式,切换成功
- 测试结果 @切换轻量级模式成功
- 最终测试状态 @SUCCESS
*/
chdir(__DIR__);
include '../lib/modemanagement.ui.class.php';
$program = zenData('project');
$program->id->range('1-3');
$program->type->range('program');
$program->name->range('项目集A,项目集B,项目集C');
$program->begin->range('2025-01-01');
$program->end->range('2025-12-31');
$program->status->range('doing');
$program->gen(3);
$tester = new modemanagementTester();
$tester->login();
$programName = new stdClass();
$programName->secProgram = '项目集B';
r($tester->modeManagement($programName)) && p('message,status') && e('切换轻量级模式成功,SUCCESS'); //切换轻量级模式成功
+15
View File
@@ -0,0 +1,15 @@
<?php
class indexPage extends page
{
public function __construct($webdriver)
{
parent::__construct($webdriver);
$xpath = array(
'defaultProgram' => '/html/body/div/div/div/div[2]/div/div/div[3]/form/div[2]/div/div/span[1]',
'systemSetting' => '/html/body/div/div/div/div[1]/div[1]/div[2]/div[1]/div/h4/div',
'useLight' => '//*[@id="useLight"]',
'comfirmBtn' => '//*[@class="m-custom-mode"]/div[2]/div[1]/div[1]/div[3]/nav[1]/button[1]'
);
$this->dom->xpath = array_merge($this->dom->xpath, $xpath);
}
}
+15
View File
@@ -0,0 +1,15 @@
<?php
class setPage extends page
{
public function __construct($webdriver)
{
parent::__construct($webdriver);
$xpath = array(
'openReview' => "//label[@for='needReview1']",
'closeReview' => "//label[@for='needReview0']",
'confirm' => "//button[@z-key='confirm']"
);
$this->dom->xpath = array_merge($this->dom->xpath, $xpath);
}
}
+35
View File
@@ -0,0 +1,35 @@
<?php
/**
* The mail file of execution module of ZenTaoPMS.
*
* @copyright Copyright 2009-2025 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Mengyi Liu
* @package execution
* @version $Id: sendmail.html.php
* @link https://www.zentao.net
*/
?>
<?php $mailTitle = 'EXECUTION #' . $object->id . ' ' . $object->name;?>
<?php include $this->app->getModuleRoot() . 'common/view/mail.header.html.php';?>
<tr>
<td>
<table cellpadding='0' cellspacing='0' width='600' style='border: none; border-collapse: collapse;'>
<tr>
<td style='padding: 10px; background-color: #F8FAFE; border: none; font-size: 14px; font-weight: 500; border-bottom: 1px solid #e5e5e5;'>
<?php $color = empty($object->color) ? '#333' : $object->color;?>
<?php echo html::a($domain . helper::createLink('execution', 'view', "executionID=$object->id", 'html'), $mailTitle, '', "style='color: {$color}; text-decoration: underline;'");?>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style='padding: 10px; border: none;'>
<fieldset style='border: 1px solid #e5e5e5'>
<legend style='color: #114f8e'><?php echo $this->lang->execution->desc;?></legend>
<div style='padding:5px;'><?php echo $object->desc;?></div>
</fieldset>
</td>
</tr>
<?php include $this->app->getModuleRoot() . 'common/view/mail.footer.html.php';?>
+104
View File
@@ -0,0 +1,104 @@
#!/usr/bin/env php
<?php
/**
title=完成/激活卡片
timeout=0
cid=0
*/
chdir(__DIR__);
include '../lib/card.ui.class.php';
$kanbanspace = zenData('kanbanspace');
$kanbanspace->id->range('1');
$kanbanspace->name->range('协作空间-A');
$kanbanspace->type->range('cooperation');
$kanbanspace->owner->range('admin');
$kanbanspace->team->range(',admin');
$kanbanspace->acl->range('open');
$kanbanspace->status->range('active');
$kanbanspace->createdBy->range('admin');
$kanbanspace->gen(1);
$kanban = zenData('kanban');
$kanban->id->range('1');
$kanban->space->range('1');
$kanban->name->range('看板-01');
$kanban->owner->range('admin');
$kanban->team->range(',admin');
$kanban->acl->range('open');
$kanban->archived->range('1');
$kanban->performable->range('1');
$kanban->status->range('active');
$kanban->order->range('1');
$kanban->object->range('`plans,releases,builds,executions,cards`');
$kanban->gen(1);
$kanbanregion = zenData('kanbanregion');
$kanbanregion->id->range('1');
$kanbanregion->space->range('1');
$kanbanregion->name->range('区域AAA');
$kanbanregion->order->range('1');
$kanbanregion->gen(1);
$kanbanlane = zenData('kanbanlane');
$kanbanlane->id->range('1');
$kanbanlane->execution->range('0');
$kanbanlane->type->range('common');
$kanbanlane->region->range('1');
$kanbanlane->group->range('1');
$kanbanlane->groupby->range('');
$kanbanlane->name->range('默认泳道');
$kanbanlane->color->range('#7ec5ff');
$kanbanlane->order->range('1');
$kanbanlane->gen(1);
$kanbancell = zenData('kanbancell');
$kanbancell->id->range('1-4');
$kanbancell->kanban->range('1');
$kanbancell->lane->range('1');
$kanbancell->column->range('1-4');
$kanbancell->type->range('common');
$kanbancell->gen(4);
$kanbancolumn = zenData('kanbancolumn');
$kanbancolumn->id->range('1-4');
$kanbancolumn->parent->range('0');
$kanbancolumn->type->range('column1,column2,column3,column4');
$kanbancolumn->region->range('1');
$kanbancolumn->group->range('1');
$kanbancolumn->name->range('未开始,进行中,已完成,已关闭');
$kanbancolumn->color->range('#333');
$kanbancolumn->limit->range('100');
$kanbancolumn->order->range('1-4');
$kanbancolumn->archived->range('0');
$kanbancolumn->gen(4);
$kanbangroup = zenData('kanbangroup');
$kanbangroup->id->range('1');
$kanbangroup->kanban->range('1');
$kanbangroup->region->range('1');
$kanbangroup->order->range('1');
$kanbangroup->gen(1);
$kanbancard = zenData('kanbancard');
$kanbancard->id->range('1');
$kanbancard->kanban->range('1');
$kanbancard->region->range('1');
$kanbancard->group->range('1');
$kanbancard->fromID->range('0');
$kanbancard->name->range('卡片01');
$kanbancard->status->range('doing');
$kanbancard->gen(1);
$tester = new cardTester();
$tester->login();
$kanbanurl['kanbanID'] = 1;
r($tester->finishCard($kanbanurl)) && p('message,status') && e('完成卡片成功,SUCCESS');//完成卡片
r($tester->activateCard($kanbanurl, '')) && p('message,status') && e('激活卡片提示信息正确,SUCCESS');//进度必填校验
r($tester->activateCard($kanbanurl, '200')) && p('message,status') && e('激活卡片提示信息正确,SUCCESS');//进度数值校验
r($tester->activateCard($kanbanurl, '50')) && p('message,status') && e('激活卡片成功,SUCCESS');//激活卡片
$tester->closeBrowser();
+33
View File
@@ -0,0 +1,33 @@
<?php
include dirname(__FILE__, 5) . '/test/lib/ui.php';
class addTodoTester extends tester
{
/**
* 检查待办标签。
* check todo tabs.
*
* @param string $todoTitle
* @param string $todoStatus
* @access public
* @return void
*/
public function checkTodoTabs($todoTitle)
{
$this->openUrl('my', 'todo', array('type' => 'before'));
$todoList = $this->loadPage('my', 'todo', array('type' => 'before'));
$todoList->wait(1);
$fstTodo = $todoList->dom->fstTodoTitle->getText();
$secTodo = $todoList->dom->secTodoTitle->getText();
$nameList = [$todoTitle->wait, $todoTitle->doing];
$nameToCheck = [$fstTodo, $secTodo];
foreach ($nameToCheck as $name)
{
echo "$name 在列表中" . (in_array($name, $nameList)
? '是'
: '否'
);
}
}
}
+34
View File
@@ -0,0 +1,34 @@
#!/usr/bin/env php
<?php
/**
title=添加待办测试
timeout=0
- 添加一个待办,添加成功
- 测试结果 @添加待办成功
- 最终测试状态 @SUCCESS
*/
chdir(__DIR__);
include '../lib/checktodotabs.ui.class.php';
$todo = zenData('todo');
$todo->id->range('1-4');
$todo->account->range('admin');
$todo->type->range('custom');
$todo->name->range('待办A,待办B,待办C,待办D');
$todo->status->range('wait,doing,done,closed');
$todo->assignedTo->range('admin');
$todo->assignedBy->range('admin');
$todo->gen(4);
$tester = new addTodoTester();
$tester->login();
$todoTitle = new stdClass();
$todoTitle->wait = '待办A';
$todoTitle->doing = '待办B';
r($tester->checkTodoTabs($todoTitle)) && p('message,status') && e('检查待办未完成标签成功,SUCCESS'); //检查待办未完成标签,显示正确
@@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
include dirname(__FILE__, 5).'/test/lib/ui.php';
class browseTestSuiteTester extends tester
{
/*
* check the testsuit count.
* @access public
* @return object
*/
public function browseTestSuite()
{
$form = $this->initForm('testsuite', 'browse', array('productID' => 1), 'appIframe-qa');
if($form->dom->sumCount->getText() != 2) return $this->failed('测试套件标签数统计错误');
if($form->dom->footerSumCount->getText() != 2) return $this->failed('测试套件列表底部总数统计错误');
if($form->dom->footerPublicCount->getText() != 1) return $this->failed('测试套件列表底部公开数统计错误');
if($form->dom->footerPrivateCount->getText() != 1) return $this->failed('测试套件列表底部私有数统计错误');
return $this->success('测试套件列表测试成功');
}
}
@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
include dirname(__FILE__, 5).'/test/lib/ui.php';
class viewTester extends tester
{
/**
* Check the view page.
* @access public
* @return void
*/
public function view()
{
$form = $this->initForm('testsuite', 'browse', array('productID' => 1), 'appIframe-qa');
$testsuiteName = $form->dom->name->getText();
$form->dom->name->click();
$viewPage = $this->loadPage('testsuite', 'view');
if($this->response('method') != 'view' && $viewPage->dom->name->getText() != $testsuiteName) return $this->failed('测试套件详情页不正确');
return $this->success('套件详情页测试成功');
}
}
@@ -0,0 +1,49 @@
#!/usr/bin/env php
<?php
declare(strict_types=1);
/**
title=套件列表测试
timeout=0
cid=72
*/
chdir(__DIR__);
include '../lib/browse.ui.class.php';
$product = zenData('product');
$product->id->range('1');
$product->program->range('0');
$product->name->range('产品1');
$product->shadow->range('0');
$product->bind->range('0');
$product->acl->range('open');
$product->createdBy->range('admin');
$product->vision->range('rnd');
$product->gen(1);
$testsuite = zenData('testsuite');
$testsuite->id->range('1-2');
$testsuite->product->range('1');
$testsuite->name->range('1-2')->prefix('公开套件,私有套件');
$testsuite->type->range('public,private');
$testsuite->addedBy->range('admin');
$testsuite->gen(2);
$action = zenData('action');
$action->id->range('1-2');
$action->objectType->range('product,testsuite');
$action->objectID->range('1,0');
$action->product->range('`,1,`,`,0,`');
$action->project->range('0');
$action->execution->range('0');
$action->actor->range('admin');
$action->action->range('opened');
$action->read->range('0');
$action->vision->range('rnd');
$action->gen(2);
$tester = new browseTestSuiteTester();
$tester->login();
r($tester->browseTestSuite()) && p('message,status') && e('测试套件列表测试成功,SUCCESS');
$tester->closeBrowser();
@@ -0,0 +1,49 @@
#!/usr/bin/env php
<?php
declare(strict_types=1);
/**
title=创建套件测试
timeout=0
cid=70
*/
chdir(__DIR__);
include '../lib/view.ui.class.php';
$product = zenData('product');
$product->id->range('1');
$product->program->range('0');
$product->name->range('产品1');
$product->shadow->range('0');
$product->bind->range('0');
$product->acl->range('open');
$product->createdBy->range('admin');
$product->vision->range('rnd');
$product->gen(1);
$testsuite = zenData('testsuite');
$testsuite->id->range('1');
$testsuite->product->range('1');
$testsuite->name->range('套件1');
$testsuite->type->range('public');
$testsuite->addedBy->range('admin');
$testsuite->gen(1);
$action = zenData('action');
$action->id->range('1-2');
$action->objectType->range('product,testsuite');
$action->objectID->range('1');
$action->product->range('`,1,`,`,1,`');
$action->project->range('0');
$action->execution->range('0');
$action->actor->range('admin');
$action->action->range('opened');
$action->read->range('0');
$action->vision->range('rnd');
$action->gen(2);
$tester = new viewTester();
$tester->login();
r($tester->view()) && p('message,status') && e('套件详情页测试成功,SUCCESS');
$tester->closeBrowser();
+103
View File
@@ -0,0 +1,103 @@
async function upgradeDoc(docID, options)
{
const newData = await zui.fetchData(options.docFetcher, [{docID, version: 0}]);
if(!newData || !newData.data) return false;
const oldContent = newData.data.content;
let content = '';
if(options.type === 'html')
{
const snap = await zui.Editor.htmlToSnap(oldContent);
if(!snap) return false;
}
else
{
try
{
content = await zui.Editor.convertToHtml(oldContent, undefined, options.downloadUrl);
}
catch(error)
{
console.warn('Convert doc to html failed:', error);
}
}
const docData = {content};
let result;
await $.post(zui.formatString(options.migrateUrl, {docID: docID}), docData, (res) =>
{
result = res.result === 'success' ? true : res.message;
}, 'json');
return result;
}
async function upgradeWikis(idList, options)
{
let result;
await $.post(options.wikiUrl, {wikis: idList.join(',')}, (res) =>
{
result = res.result === 'success' ? true : res.message;
}, 'json');
return result;
}
async function upgradeDocs(idList, options)
{
await zui.Editor.loadModule();
const {
onProgress,
wikiUrl = $.createLink('upgrade', 'ajaxUpgradeWikis'),
migrateUrl = $.createLink('upgrade', 'ajaxUpgradeDoc', 'docID={docID}'),
docFetcher = $.createLink('upgrade', 'ajaxUpgradeDoc', 'docID={docID}'),
downloadUrl = $.createLink('file', 'ajaxQuery', 'fileID={gid}'),
} = options || {};
const migrateOptions =
{
migrateUrl: migrateUrl,
docFetcher: docFetcher,
downloadUrl: downloadUrl,
};
let current = 0;
const total = idList.doc.length + idList.html.length + idList.wiki.length;
const types = ['doc', 'html'];
for (const type of types)
{
for(const id of idList[type])
{
onProgress(current, total);
await upgradeDoc(id, $.extend({type: type}, migrateOptions));
await zui.delay(50);
current++;
}
}
if(idList.wiki.length)
{
await upgradeWikis(idList.wiki, {wikiUrl: wikiUrl});
current += idList.wiki.length;
}
onProgress(current, total);
return idList;
}
window.startUpgradeDocs = function(event, idList, upgradingDocsText, nextText)
{
const $btn = $('#upgradeDocsBtn');
if($btn.hasClass('is-finished')) return;
event.preventDefault();
const $progressBar = $('#upgradeDocsProgress').addClass('active').find('.progress-bar');
$btn.attr('disabled', 'disabled').addClass('disabled').removeClass('primary').find('.text').text(upgradingDocsText);
upgradeDocs(idList,
{
onProgress: (current, total) =>
{
$progressBar.css('width', (100 * current / total) + '%');
$btn.find('.text').text(`${upgradingDocsText} (${current}/${total})`);
}
}).then(() =>
{
$btn.removeAttr('disabled').removeClass('disabled').addClass('primary is-finished').find('.text').text(nextText);
$('#upgradeDocsProgress').removeClass('active')
});
};
+63
View File
@@ -0,0 +1,63 @@
<?php
include '../test/result.php';
$links = array();
foreach($link as $module => $group)
{
foreach($group as $name => $url)
{
$method = explode('_', $name)[0];
$links[$module][$method][$name] = $url;
}
}
?>
<script src="https://cdn.staticfile.net/jquery/1.10.2/jquery.min.js">
</script>
<style>
h1 {text-align: center;}
ul {padding: 0;}
ul li {list-style: none; padding: 4px 0px; margin: 0px;}
.row {width: 100%; margin: 20px; display: flex; flex-flow: row wrap;}
.col {flex: 0 0 19.5%;}
a {color: #0c64eb;}
.moduleName {color: #000;}
.methodName {color: #000;}
.methodList {border: 1px solid #000; margin: 10px; margin-left: 0px; padding: 10px;}
body {overflow-x: hidden;}
</style>
<h1>禅道全连接测试</h1>
<div class="row">
<?php foreach($links as $module => $group):?>
<div class="col card">
<h3 class="title moduleName"><?php echo '模块: ' . $module;?></h3>
<?php foreach($group as $method => $urlList):?>
<div class="methodList">
<h4 class="title"><a class="methodName" href="#"><?php echo '方法: ' . $method;?></a></h4>
<ul>
<?php foreach($urlList as $name => $url):?>
<li><a href="<?php echo $url;?>" target="_blank"><?php echo $name;?></a></li>
<?php endforeach;?>
</ul>
</div>
<?php endforeach;?>
</div>
<?php endforeach;?>
</div>
<script>
$(document).ready(function()
{
$('li a').on('click', function(e)
{
$(this).css('color', '#838383');
})
$('.methodName').on('click', function()
{
$(this).closest('.methodList').find('ul li a').each(function()
{
var link = $(this).attr('href');
window.open(link);
});
})
})
</script>