Merge branch 'sprint/285' of https://gitlab.zcorp.cc/easycorp/zentaopms into sprint/285

This commit is contained in:
wangyidong
2023-01-31 16:19:10 +08:00
11 changed files with 261 additions and 59 deletions
+32
View File
@@ -23,3 +23,35 @@ $config->admin->menuModuleGroup['model']['custom|required'] = array('project',
$config->admin->menuModuleGroup['feature']['custom|set'] = array('todo', 'feedback', 'user', 'block', 'story', 'task', 'bug', 'testcase', 'testtask', 'feedback', 'user');
$config->admin->menuModuleGroup['feature']['custom|required'] = array('bug', 'doc', 'product', 'story', 'productplan', 'release', 'task', 'bug', 'testcase', 'testsuite', 'testtask', 'testreport', 'caselib', 'doc', 'feedback', 'user');
$config->admin->menuModuleGroup['template']['custom|set'] = array('baseline');
$config->admin->plugIns[203] = new stdClass();
$config->admin->plugIns[203]->name = '人力资源日历';
$config->admin->plugIns[203]->desc = '禅道人力资源日历插件可以帮助项目管理者查看不同维度下的消耗工时、未完成工作量、并行工作量及负载率,同时组织维度待处理状态下实现了模拟负载的功能,帮助管理者详细了解成员的工作负载情况,更好的进行项目人力资源调度。';
$config->admin->plugIns[203]->viewLink = 'https://www.zentao.net/extension-viewExt-203.html';
$config->admin->plugIns[198] = new stdClass();
$config->admin->plugIns[198]->name = '需求池插件';
$config->admin->plugIns[198]->desc = '本插件为禅道需求池管理插件,包括:创建需求池 需求池权限管理 收集需求并向需求池录入需求 记录需求提出人信息 评审需求 拆分用户需求、研发需求 需求跟踪矩阵';
$config->admin->plugIns[198]->viewLink = 'https://www.zentao.net/extension-viewExt-198.html';
$config->admin->plugIns[27] = new stdClass();
$config->admin->plugIns[27]->name = 'Excel导出/导入';
$config->admin->plugIns[27]->desc = '安装该插件可以支持Excel导出和任务、需求、Bug、用例导入功能。更新提示:新增任务、需求、Bug的excel导入功能。';
$config->admin->plugIns[27]->viewLink = 'https://www.zentao.net/extension-viewExt-27.html';
$config->admin->plugIns[26] = new stdClass();
$config->admin->plugIns[26]->name = '甘特图';
$config->admin->plugIns[26]->desc = '禅道甘特图插件 运用此插件可以查看甘特图,维护任务关系。';
$config->admin->plugIns[26]->viewLink = 'https://www.zentao.net/extension-viewExt-26.html';
$config->admin->plugIns[30] = new stdClass();
$config->admin->plugIns[30]->name = '日志日历';
$config->admin->plugIns[30]->desc = '运用此插件可以实现工作日志的添加、编辑、查看、删除、导出等功能,方便用户管理工作日志。';
$config->admin->plugIns[30]->viewLink = 'https://www.zentao.net/extension-viewExt-30.html';
//$config->admin->plugIns[] = new stdClass();
//$config->admin->plugIns[]->name = '';
//$config->admin->plugIns[]->desc = '';
//$config->admin->plugIns[]->viewLink = 'https://www.zentao.net/extension-viewExt-203.html';
$config->admin->apiRoot = 'https://www.zentao.net/';
+10 -4
View File
@@ -34,11 +34,17 @@ class admin extends control
$this->loadModel('misc');
$extensions = $this->loadModel('extension')->getExtensionsByAPI('byUpdatedTime', '', 0, 6);
$hasInternet = $this->admin->checkInternet();
$clientLang = $this->app->getClientLang();
$langNotCN = common::checkNotCN();
$this->view->title = $this->lang->admin->common;
$this->view->position[] = $this->lang->admin->index;
$this->view->extensions = isset($extensions->extensions) ? (array)$extensions->extensions : array();
$this->view->title = $this->lang->admin->common;
$this->view->position[] = $this->lang->admin->index;
$this->view->extensions = $this->admin->getExtensionsByAPI('extension', $langNotCN ? 5 : 6, $hasInternet);
$this->view->patches = $this->admin->getExtensionsByAPI('patch', 3, $hasInternet);
$this->view->hasInternet = $hasInternet;
$this->view->publicClass = ($hasInternet and !$langNotCN) ? $this->admin->getPublicClassByAPI() : array();
$this->view->langNotCN = $langNotCN;
$this->display();
}
+10 -5
View File
@@ -2,7 +2,7 @@
#zentaoLinks {margin-top: 20px;}
#zentaoLinks .panel .panel-heading {padding: 6px 10px;}
.admin {display: flex; background: unset;}
.admin > .main {flex: 1 1 60%; padding-right: 10px;}
.admin > .main {flex: 1 1 60%; padding-right: 20px;}
.admin > .side {flex: 1 1 40%; padding-left: 10px;}
.panel-title {padding: 10px 0px;}
.flex {display: flex;}
@@ -12,14 +12,19 @@
.settings-list > .setting-box {flex: 0 0 20%; padding: 18px 0;}
.plugin-list {display: flex; flex-wrap: wrap; padding: 12px 4px 4px 4px;}
.plugin-list > .plugin-item {flex: 1 1 30%; padding: 16px 4px; border: 1px solid #EDEEF2; border-radius: 4px; margin-right: 16px; margin-bottom: 16px;}
.plugin-list > .plugin-item {flex: 1 1 26%; padding: 16px 4px; border: 1px solid #EDEEF2; border-radius: 4px; margin-right: 16px; margin-bottom: 16px; width: 0px;}
.plugin-list > .plugin-item .ext-download {float: right; padding: 6px 0px;}
.plugin-list > .plugin-item > .plug-title {height: 16px; overflow: hidden;}
.plugin-list > .plugin-item .extension-desc {overflow: hidden; height: 16px;}
.bottom.flex > .official {flex: 1 1 30%; margin-right: 20px;}
.bottom.flex > .openClass {flex: 1 1 60%;}
.bottom.flex > .publicClass {flex: 1 1 60%;}
.official.panel > .main-panel {min-height: 200px;}
.official-img {background-image: url('/static/images/wechat.jpg'); background-repeat: no-repeat; background-size: contain; flex: 1 1 50%; aspect-ratio: 1 / 1; background-position: center;}
.official-content {flex: 0 0 50%;}
.official-content {flex: 0 0 50%; display: flex; flex-direction: column; justify-content: center;}
.official-content > .content {color: #838A9D; font-size: 12px;}
.official-content > .title {color: #313C52; font-size: 13px;}
.classList > .classItem {flex: 0 0 50%;}
.classItem > .classImg {background-image: url('/static/images/wechat.jpg'); background-repeat: no-repeat; background-size: contain; flex: 1 1 50%; aspect-ratio: 1 / 1; }
.classItem > .classContent {flex: 1 1 50%;}
+11 -5
View File
@@ -25,11 +25,17 @@ $lang->admin->resetPWDSetting = 'Reset password Setting';
$lang->admin->tableEngine = 'Table Engine';
$lang->admin->setModuleIndex = 'Set Module';
$lang->admin->api = 'API';
$lang->admin->log = 'Log';
$lang->admin->setting = 'Einstellungen';
$lang->admin->days = 'Gültige Tage';
$lang->admin->resetPWDByMail = 'Reset the password via the email';
$lang->admin->api = 'API';
$lang->admin->log = 'Log';
$lang->admin->setting = 'Einstellungen';
$lang->admin->pluginRecommendation = 'Recommended plug-ins';
$lang->admin->zentaoInfo = 'ZenTao information';
$lang->admin->officialAccount = 'WeChat Official Account';
$lang->admin->publicClass = 'Public class';
$lang->admin->days = 'Gültige Tage';
$lang->admin->resetPWDByMail = 'Reset the password via the email';
$lang->admin->followUs = 'Follow Us';
$lang->admin->followUsContent = 'Check out ZenTao news, events, and support at any time';
$lang->admin->changeEngine = "Change to InnoDB";
$lang->admin->changingTable = 'Replacing data table %s engine...';
+12 -6
View File
@@ -25,11 +25,17 @@ $lang->admin->resetPWDSetting = 'Reset password Setting';
$lang->admin->tableEngine = 'Table Engine';
$lang->admin->setModuleIndex = 'Set Module';
$lang->admin->api = 'API';
$lang->admin->log = 'Log';
$lang->admin->setting = 'Setting';
$lang->admin->days = 'Valid Day';
$lang->admin->resetPWDByMail = 'Reset the password via the email';
$lang->admin->api = 'API';
$lang->admin->log = 'Log';
$lang->admin->setting = 'Setting';
$lang->admin->pluginRecommendation = 'Recommended plug-ins';
$lang->admin->zentaoInfo = 'ZenTao information';
$lang->admin->officialAccount = 'WeChat Official Account';
$lang->admin->publicClass = 'Public class';
$lang->admin->days = 'Valid Day';
$lang->admin->resetPWDByMail = 'Reset the password via the email';
$lang->admin->followUs = 'Follow Us';
$lang->admin->followUsContent = 'Check out ZenTao news, events, and support at any time';
$lang->admin->changeEngine = "Change to InnoDB";
$lang->admin->changingTable = 'Replacing data table %s engine...';
@@ -141,4 +147,4 @@ $lang->admin->safe->resetPWDList[0] = 'Off';
$lang->admin->safe->noticeMode = 'The password will be checked when creating and modifying user information, and changing passwords.';
$lang->admin->safe->noticeWeakMode = 'The password will be checked when logging into the system, creating and modifying user information, and changing passwords.';
$lang->admin->safe->noticeStrong = 'The longer the password, the more letters, numbers, or special characters it contains, and the less repetitive the password, the more secure it is!';
$lang->admin->safe->noticeGd = 'Your server does not have GD module installed, you cannot use the Captcha function, Please use it after installation.';
$lang->admin->safe->noticeGd = 'Your server does not have GD module installed, you cannot use the Captcha function, Please use it after installation.';
+11 -5
View File
@@ -25,11 +25,17 @@ $lang->admin->resetPWDSetting = 'Reset password Setting';
$lang->admin->tableEngine = 'Table Engine';
$lang->admin->setModuleIndex = 'Set Module';
$lang->admin->api = 'API';
$lang->admin->log = 'Log';
$lang->admin->setting = 'Paramétrage';
$lang->admin->days = 'Durée de conservation';
$lang->admin->resetPWDByMail = 'Reset the password via the email';
$lang->admin->api = 'API';
$lang->admin->log = 'Log';
$lang->admin->setting = 'Paramétrage';
$lang->admin->pluginRecommendation = 'Recommended plug-ins';
$lang->admin->zentaoInfo = 'ZenTao information';
$lang->admin->officialAccount = 'WeChat Official Account';
$lang->admin->publicClass = 'Public class';
$lang->admin->days = 'Durée de conservation';
$lang->admin->resetPWDByMail = 'Reset the password via the email';
$lang->admin->followUs = 'Follow Us';
$lang->admin->followUsContent = 'Check out ZenTao news, events, and support at any time';
$lang->admin->changeEngine = "Change to InnoDB";
$lang->admin->changingTable = 'Replacing data table %s engine...';
+12 -5
View File
@@ -22,10 +22,17 @@ $lang->admin->captcha = 'Mã xác thực';
$lang->admin->getCaptcha = 'Gửi Mã xác thực';
$lang->admin->register = 'Register';
$lang->admin->api = 'API';
$lang->admin->log = 'Nhật ký';
$lang->admin->setting = 'Thiết lập';
$lang->admin->days = 'Ngày hợp lệ';
$lang->admin->api = 'API';
$lang->admin->log = 'Nhật ký';
$lang->admin->setting = 'Thiết lập';
$lang->admin->pluginRecommendation = 'Recommended plug-ins';
$lang->admin->zentaoInfo = 'ZenTao information';
$lang->admin->officialAccount = 'WeChat Official Account';
$lang->admin->publicClass = 'Public class';
$lang->admin->days = 'Ngày hợp lệ';
$lang->admin->resetPWDByMail = 'Reset the password via the email';
$lang->admin->followUs = 'Follow Us';
$lang->admin->followUsContent = 'Check out ZenTao news, events, and support at any time';
$lang->admin->info = new stdclass();
$lang->admin->info->version = 'Phiên bản hiện tại là %s. ';
@@ -84,4 +91,4 @@ $lang->admin->safe->loginCaptchaList[0] = 'No';
$lang->admin->safe->noticeMode = 'Mật khẩu sẽ được kiểm tra khi người dùng đăng nhập hoặc người dùng thêm hoặc sửa.';
$lang->admin->safe->noticeStrong = '';
$lang->admin->safe->noticeGd = 'Your server does not have GD module installed, you cannot use the Captcha function, Please use it after installation.';
$lang->admin->safe->noticeGd = 'Your server does not have GD module installed, you cannot use the Captcha function, Please use it after installation.';
+10 -8
View File
@@ -31,17 +31,19 @@ $lang->admin->setting = '设置';
$lang->admin->pluginRecommendation = '插件推荐';
$lang->admin->zentaoInfo = '禅道信息';
$lang->admin->officialAccount = '官方公众号';
$lang->admin->openClass = '公开课';
$lang->admin->publicClass = '公开课';
$lang->admin->days = '日志保存天数';
$lang->admin->resetPWDByMail = '通过邮箱重置密码';
$lang->admin->followUs = '扫码关注公众号';
$lang->admin->followUsContent = '随时查看禅道动态、活动信息、也可获取帮助支持';
$lang->admin->changeEngine = "更换到InnoDB";
$lang->admin->changingTable = '正在更换数据表%s引擎...';
$lang->admin->changeSuccess = '已经更换数据表%s引擎为InnoDB。';
$lang->admin->changeFail = "更换数据表%s引擎失败,原因:<span class='text-red'>%s</span>。";
$lang->admin->errorInnodb = '您当前的数据库不支持使用InnoDB数据表引擎。';
$lang->admin->changeFinished = "更换数据库引擎完毕。";
$lang->admin->engineInfo = "表<strong>%s</strong>的引擎是<strong>%s</strong>。";
$lang->admin->changeEngine = "更换到InnoDB";
$lang->admin->changingTable = '正在更换数据表%s引擎...';
$lang->admin->changeSuccess = '已经更换数据表%s引擎为InnoDB。';
$lang->admin->changeFail = "更换数据表%s引擎失败,原因:<span class='text-red'>%s</span>。";
$lang->admin->errorInnodb = '您当前的数据库不支持使用InnoDB数据表引擎。';
$lang->admin->changeFinished = "更换数据库引擎完毕。";
$lang->admin->engineInfo = "表<strong>%s</strong>的引擎是<strong>%s</strong>。";
$lang->admin->engineSummary['hasMyISAM'] = "有%s个表不是InnoDB引擎";
$lang->admin->engineSummary['allInnoDB'] = "所有的表都是InnoDB引擎了";
+114
View File
@@ -13,6 +13,11 @@
<?php
class adminModel extends model
{
/**
* The extension manager version. Don't change it.
*/
const EXT_MANAGER_VERSION = '1.3';
/**
* The api root.
*
@@ -396,4 +401,113 @@ class adminModel extends model
return $output;
}
/**
* Get extensions from zentao.net.
*
* @param string $type extension|patch
* @param int $limit
* @param bool $hasInternet
* @access public
* @return array
*/
public function getExtensionsByAPI($type = 'extension', $limit = 6, $hasInternet = true)
{
if($hasInternet)
{
$searchType = $type == 'extension' ? 'byUpdatedTime' : 'byModule';
$param = $type == 'extension' ? '' : 'MTIxOA==';
$extensions = $this->loadModel('extension')->getExtensionsByAPI($searchType, $param, 0, $limit);
$extensions = isset($extensions->extensions) ? (array)$extensions->extensions : array();
}
else
{
if($this->config->edition == 'open')
{
$extensions = array(
$this->config->admin->plugIns[27],
$this->config->admin->plugIns[26],
$this->config->admin->plugIns[30]
);
}
else
{
$extensions = array(
$this->config->admin->plugIns[198],
$this->config->admin->plugIns[203]
);
}
}
return $extensions;
}
/**
* Fetch data from an api.
*
* @param string $url
* @access public
* @return mixed
*/
public function fetchAPI($url)
{
$version = $this->loadModel('upgrade')->getOpenVersion(str_replace('.', '_', $this->config->version));
$version = str_replace('_', '.', $version);
$url .= (strpos($url, '?') === false ? '?' : '&') . 'lang=' . str_replace('-', '_', $this->app->getClientLang()) . '&managerVersion=' . self::EXT_MANAGER_VERSION . '&zentaoVersion=' . $version;
$result = json_decode(preg_replace('/[[:cntrl:]]/mu', '', common::http($url)));
if(!isset($result->status)) return false;
if($result->status != 'success') return false;
if(isset($result->data)) return json_decode($result->data);
}
/**
* Get public class from zentao.net.
*
* @param int $limit
* @access public
* @return array
*/
public function getPublicClassByAPI($limit = 2)
{
$apiURL = $this->config->admin->apiRoot . "publicclass.json";
$data = $this->fetchAPI($apiURL);
$courses = $data->videos;
$index = 1;
$publicClass = array();
foreach($courses as $course)
{
if($index > $limit) return $publicClass;
$publicClass[$index] = new stdClass();
$publicClass[$index]->name = $course->title;
$publicClass[$index]->image = $this->config->admin->apiRoot . $course->image->list[0]->smallURL;
$publicClass[$index]->viewLink = $this->config->admin->apiRoot . "{$course->alias}-{$course->id}.html";
$index++;
}
return $publicClass;
}
/**
* Check internet.
*
* @access public
* @return bool
*/
public function checkInternet()
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'https://api.zentao.net/extension-apiGetExtensions.json');
curl_setopt($curl, CURLOPT_TIMEOUT_MS, 1000);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT_MS, 1000);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
$connected = curl_exec($curl);
curl_close($curl);
return (bool)$connected;
}
}
+24 -5
View File
@@ -11,6 +11,7 @@
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php js::set('hasInternet', $hasInternet);?>
<div id='mainContent' class='main-content admin'>
<div class="main">
<div class="settings panel">
@@ -28,6 +29,8 @@
<div class="setting-box">10</div>
</div>
</div>
<?php if($extensions):?>
<div class="plug panel">
<div class="panel-title"><?php echo $lang->admin->pluginRecommendation?></div>
<div class="plugin-list">
@@ -40,22 +43,38 @@
<?php endforeach;?>
</div>
</div>
<?php endif;?>
<div class="flex bottom">
<div class="panel official">
<div class="panel-title"><?php echo $lang->admin->officialAccount?></div>
<div class="flex main-panel">
<div class="official-img"></div>
<div class="official-content">
<div class="flex main-panel">
<div class="official-img"></div>
<div class="official-content">
<div class="title"><?php echo $lang->admin->followUs?></div>
<div class="content"> <?php echo $lang->admin->followUsContent?></div>
</div>
</div>
</div>
<div class="panel openClass">
<div class="panel-title"><?php echo $lang->admin->openClass?></div>
<?php if($publicClass):?>
<div class="panel publicClass">
<div class="panel-title"><?php echo $lang->admin->publicClass?></div>
<div class="classList flex">
<?php foreach($publicClass as $class):?>
<div class="classItem flex">
<div class="classImg" style="background-image: url('<?php echo $class->image;?>');"></div>
<div class="classContent"><?php echo $class->name;?></div>
</div>
<?php endforeach;?>
</div>
</div>
<?php endif;?>
</div>
</div>
<?php if($hasInternet and !$langNotCN):?>
<div class="side panel">
<div class="panel-title"><?php echo $lang->admin->zentaoInfo?></div>
</div>
<?php endif;?>
</div>
<?php include '../../common/view/footer.html.php';?>
@@ -1,23 +1,22 @@
<?php
$lang->xuanxuan = new stdclass();
$lang->admin->menu->xuanxuan['subMenu'] = new stdclass();
$lang->admin->menu->xuanxuan['subMenu']->index = array('link' => '首页|admin|xuanxuan');
$lang->admin->menu->xuanxuan['subMenu']->setting = array('link' => '参数|setting|xuanxuan');
$lang->admin->menu->xuanxuan['subMenu']->update = array('link' => '更新|client|browse', 'subModule' => 'client');
$lang->admin->menu->xuanxuan['menuOrder'][0] = 'index';
$lang->admin->menu->xuanxuan['menuOrder'][5] = 'setting';
$lang->admin->menu->xuanxuan['menuOrder'][10] = 'update';
//$lang->admin->menu->xuanxuan['subMenu'] = new stdclass();
//$lang->admin->menu->xuanxuan['subMenu']->index = array('link' => '首页|admin|xuanxuan');
//$lang->admin->menu->xuanxuan['subMenu']->setting = array('link' => '参数|setting|xuanxuan');
//$lang->admin->menu->xuanxuan['subMenu']->update = array('link' => '更新|client|browse', 'subModule' => 'client');
//
//$lang->admin->menu->xuanxuan['menuOrder'][0] = 'index';
//$lang->admin->menu->xuanxuan['menuOrder'][5] = 'setting';
//$lang->admin->menu->xuanxuan['menuOrder'][10] = 'update';
global $config;
if($config->edition != 'open')
{
$lang->admin->menu->xuanxuan['subModule'] = 'client,setting,conference';
$lang->admin->menu->xuanxuan['subMenu']->conference = array('link' => '音视频|conference|admin');
$lang->admin->menu->xuanxuan['menuOrder'][7] = 'conference';
$lang->navGroup->conference = 'admin';
}
//if($config->edition != 'open')
//{
// $lang->admin->menu->xuanxuan['subModule'] = 'client,setting,conference';
// $lang->admin->menu->xuanxuan['subMenu']->conference = array('link' => '音视频|conference|admin');
// $lang->admin->menu->xuanxuan['menuOrder'][7] = 'conference';
// $lang->navGroup->conference = 'admin';
//}
$lang->navGroup->im = 'admin';
$lang->navGroup->setting = 'admin';