diff --git a/lib/base/pager/pager.class.php b/lib/base/pager/pager.class.php index 0f55d8ccdf..6ab59865a4 100644 --- a/lib/base/pager/pager.class.php +++ b/lib/base/pager/pager.class.php @@ -545,6 +545,7 @@ class basePager vars = vars.replace('_recTotal_', recTotal) vars = vars.replace('_recPerPage_', recPerPage) vars = vars.replace('_pageID_', pageID); + $.get(createLink('score', 'ajax', "method=submitPage")); location.href=createLink('$this->moduleName', '$this->methodName', vars); } diff --git a/module/block/lang/en.php b/module/block/lang/en.php index db1ae32a0c..3fcc453cb9 100644 --- a/module/block/lang/en.php +++ b/module/block/lang/en.php @@ -280,10 +280,12 @@ $lang->block->typeList->story['closedBy'] = 'Closed by Me' ; $lang->block->typeList->product['noclosed'] = 'Open'; $lang->block->typeList->product['closed'] = 'Closed'; $lang->block->typeList->product['all'] = 'All'; +$lang->block->typeList->product['involved'] = 'Involved' -$lang->block->typeList->project['undone'] = 'Undone'; -$lang->block->typeList->project['isdoing'] = 'Doing'; -$lang->block->typeList->project['all'] = 'All'; +$lang->block->typeList->project['undone'] = 'Undone'; +$lang->block->typeList->project['isdoing'] = 'Doing'; +$lang->block->typeList->project['all'] = 'All'; +$lang->block->typeList->project['involved'] = 'Involved'; $lang->block->typeList->testtask['wait'] = 'Testing Pending'; $lang->block->typeList->testtask['doing'] = 'Testing'; diff --git a/module/block/lang/zh-cn.php b/module/block/lang/zh-cn.php index 0bbfe758ae..e1f8fe2f4f 100644 --- a/module/block/lang/zh-cn.php +++ b/module/block/lang/zh-cn.php @@ -280,10 +280,12 @@ $lang->block->typeList->story['closedBy'] = '由我关闭'; $lang->block->typeList->product['noclosed'] = '未关闭'; $lang->block->typeList->product['closed'] = '已关闭'; $lang->block->typeList->product['all'] = '全部'; +$lang->block->typeList->product['involved'] = '我参与的'; -$lang->block->typeList->project['undone'] = '未完成'; -$lang->block->typeList->project['isdoing'] = '进行中'; -$lang->block->typeList->project['all'] = '全部'; +$lang->block->typeList->project['undone'] = '未完成'; +$lang->block->typeList->project['isdoing'] = '进行中'; +$lang->block->typeList->project['all'] = '全部'; +$lang->block->typeList->project['involved'] = '我参与的'; $lang->block->typeList->testtask['wait'] = '待测版本'; $lang->block->typeList->testtask['doing'] = '测试中版本'; diff --git a/module/common/lang/en.php b/module/common/lang/en.php index d85d3bccfa..a9a47cbd8e 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -372,6 +372,7 @@ $lang->custom->menu = $lang->admin->menu; $lang->editor->menu = $lang->admin->menu; $lang->mail->menu = $lang->admin->menu; $lang->dev->menu = $lang->admin->menu; +$lang->entry->menu = $lang->admin->menu; $lang->webhook->menu = $lang->admin->menu; /* 菜单分组。*/ @@ -422,6 +423,7 @@ $lang->error->int = array("『%s』has to be numbers", "『%s』shou $lang->error->float = "『%s』should be numbers, decimals included."; $lang->error->email = "『%s』should be valid EMAIL."; $lang->error->date = "『%s』should be valid date."; +$lang->error->code = "『%s』should be english or numbers."; $lang->error->account = "『%s』should be valid account."; $lang->error->passwordsame = "Two passwords should be consistent."; $lang->error->passwordrule = "Password should meet requirements. It should be 6 characters at least."; @@ -431,6 +433,16 @@ $lang->error->noData = 'No Data'; $lang->error->editedByOther = 'This record might have been changed. Please refresh and try to edit again!'; $lang->error->tutorialData = 'No data can be imported in tutorial mode. Please exit tutorial first!'; +$lang->error->entry = array(); +$lang->error->entry['300001'] = 'Param code not set.'; +$lang->error->entry['300002'] = 'Param token not set.'; +$lang->error->entry['310001'] = 'Entry not exist.'; +$lang->error->entry['310002'] = 'Key of entry not set.'; +$lang->error->entry['320001'] = 'IP denied.'; +$lang->error->entry['330001'] = 'Invalid token.'; +$lang->error->entry['340001'] = 'Session code not set.'; +$lang->error->entry['340002'] = 'Session verify failed.'; + /* 分页信息。*/ $lang->pager = new stdclass(); $lang->pager->noRecord = "No History"; diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index e7777a6a78..c5c51831e8 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -433,6 +433,16 @@ $lang->error->noData = '没有数据'; $lang->error->editedByOther = '该记录可能已经被改动。请刷新页面重新编辑!'; $lang->error->tutorialData = '新手模式下不会插入数据,请退出新手模式操作'; +$lang->error->entry = array(); +$lang->error->entry['300001'] = '缺少code参数'; +$lang->error->entry['300002'] = '缺少token参数'; +$lang->error->entry['310001'] = '应用不存在'; +$lang->error->entry['310002'] = '应用未设置密钥'; +$lang->error->entry['320001'] = '该IP访问被限制访问'; +$lang->error->entry['330001'] = '不合法的token参数'; +$lang->error->entry['340001'] = '缺少session code'; +$lang->error->entry['340002'] = 'session验证失败'; + /* 分页信息。*/ $lang->pager = new stdclass(); $lang->pager->noRecord = "暂时没有记录"; diff --git a/module/common/model.php b/module/common/model.php index 898f63c27b..0fb9910539 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -1353,6 +1353,83 @@ class commonModel extends model return $convertedItems; } + + /** + * Check an entry. + * + * @access public + * @return void + */ + public function checkEntry() + { + if(!$this->session->valid_entry) + { + if(!$this->session->entry_code) $this->response(340001); + if($this->session->valid_entry != md5(md5($this->get->code) . $this->server->remote_addr)) $this->response(340002); + return true; + } + + if(!$this->get->code) $this->response(300001); + if(!$this->get->token) $this->response(300002); + + $entry = $this->loadModel('entry')->getByCode($this->get->code); + if(!$entry) $this->response(310001); + if(!$entry->key) $this->response(310002); + + $this->checkEntryIP($entry->ip); + $this->checkEntryToken($entry->key); + + $this->session->set('ENTRY_CODE', $this->get->code); + $this->session->set('VALID_ENTRY', md5(md5($this->get->code) . $this->server->remote_addr)); + $this->loadModel('entry')->saveLog($entry->id, $this->server->request_uri); + } + + /** + * Check ip of an entry. + * + * @param string $ip + * @access public + * @return void + */ + public function checkEntryIP($ip) + { + $ipWhiteList = $this->config->ipWhiteList; + $this->config->ipWhiteList = $ip; + $result = $this->checkIP(); + $this->config->ipWhiteList = $ipWhiteList; + if(!$result) $this->response(320001); + } + + /** + * Check token of an entry. + * + * @param string $key + * @access public + * @return void + */ + public function checkEntryToken($key) + { + parse_str($this->server->query_String, $queryString); + unset($queryString['token']); + $queryString = http_build_query($queryString); + if($_GET['token'] != md5(md5($queryString) . $key)) $this->response(330001); + } + + /** + * Response. + * + * @param int $code + * @access public + * @return void + */ + public function response($code) + { + $response = new stdclass(); + $response->errcode = $code; + $response->errmsg = $this->lang->error->entry[$code]; + + die(helper::jsonEncode($response)); + } } class common extends commonModel diff --git a/module/common/view/datatable.fix.html.php b/module/common/view/datatable.fix.html.php index 0d9f8abd03..bf17d7ad25 100644 --- a/module/common/view/datatable.fix.html.php +++ b/module/common/view/datatable.fix.html.php @@ -49,6 +49,7 @@ $(function() success:function(){if(reload) window.location.reload();}, url: 'createLink('datatable', 'ajaxSave')?>' }); + $.get(createLink('score', 'ajax', "method=switchToDataTable")); }; window.saveDatatableConfig = saveDatatableConfig; }); diff --git a/module/custom/model.php b/module/custom/model.php index e5bdc35521..978859cc16 100644 --- a/module/custom/model.php +++ b/module/custom/model.php @@ -372,6 +372,7 @@ class customModel extends model } $this->loadModel('setting')->setItem($settingKey, $menu); + $this->loadModel('score')->score('ajax', 'customMenu'); } /** diff --git a/module/doc/model.php b/module/doc/model.php index 499aeb7f9e..b453f3976b 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -431,6 +431,7 @@ class docModel extends model $docContent->doc = $docID; $docContent->files = join(',', array_keys($files)); $this->dao->insert(TABLE_DOCCONTENT)->data($docContent)->exec(); + $this->loadModel('score')->score('doc', 'create', $docID); return array('status' => 'new', 'id' => $docID); } return false; diff --git a/module/entry/control.php b/module/entry/control.php index 06b94cf723..64bfeefe00 100644 --- a/module/entry/control.php +++ b/module/entry/control.php @@ -43,10 +43,10 @@ class entry extends control { if($_POST) { - $entryID = $this->entry->create(); + $id = $this->entry->create(); if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); - $this->loadModel('action')->create('entry', $entryID, 'created'); + $this->loadModel('action')->create('entry', $id, 'created'); $this->send(array('result' => 'success', 'message' => $this->lang->entry->saveSuccess, 'locate' => inlink('browse'))); } @@ -57,26 +57,26 @@ class entry extends control /** * Edit an entry. * - * @param int $entryID + * @param int $id * @access public * @return void */ - public function edit($entryID) + public function edit($id) { if($_POST) { - $changes = $this->entry->update($entryID); + $changes = $this->entry->update($id); if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); if($changes) { - $actionID = $this->loadModel('action')->create('entry', $entryID, 'edited'); + $actionID = $this->loadModel('action')->create('entry', $id, 'edited'); $this->action->logHistory($actionID, $changes); } $this->send(array('result' => 'success', 'message' => $this->lang->entry->saveSuccess, 'locate' => inlink('browse'))); } - $entry = $this->entry->getById($entryID); + $entry = $this->entry->getById($id); $this->view->title = $this->lang->entry->edit . $this->lang->colon . $entry->name; $this->view->entry = $entry; $this->display(); @@ -85,30 +85,40 @@ class entry extends control /** * Delete an entry. * - * @param int $entryID + * @param int $id * @access public * @return void */ - public function delete($entryID) + public function delete($id) { - $this->entry->delete(TABLE_ENTRY, $entryID); + $this->entry->delete(TABLE_ENTRY, $id); if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); $this->send(array('result' => 'success')); } /** - * Show access logs of entry. + * Browse logs of an entry. * - * @param int $entryID + * @param int $id + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID * @access public * @return void */ - public function log($entryID) + public function log($id, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) { - $entry = $this->entry->getById($entryID); + $this->app->loadClass('pager', $static = true); + $pager = new pager($recTotal, $recPerPage, $pageID); + + $entry = $this->entry->getByID($id); $this->view->title = $this->lang->entry->log . $this->lang->colon . $entry->name; - $this->view->actions = $this->loadModel('action')->getList('entry', $entryID); + $this->view->logs = $this->entry->getLogList($id, $orderBy, $pager); + $this->view->entry = $entry; + $this->view->orderBy = $orderBy; + $this->view->pager = $pager; $this->display(); } } diff --git a/module/entry/lang/zh-cn.php b/module/entry/lang/zh-cn.php index c9bcf07f03..1c0a8ab3b2 100644 --- a/module/entry/lang/zh-cn.php +++ b/module/entry/lang/zh-cn.php @@ -22,6 +22,8 @@ $lang->entry->createdBy = '由谁创建'; $lang->entry->createdDate = '创建时间'; $lang->entry->editedby = '最后编辑'; $lang->entry->editedDate = '编辑时间'; +$lang->entry->date = '请求时间'; +$lang->entry->url = '请求地址'; $lang->entry->apiIndex = '应用入口'; $lang->entry->saveSuccess = '保存成功'; @@ -30,6 +32,6 @@ $lang->entry->confirmDelete = '您确认要删除该应用吗?'; $lang->entry->note = new stdClass(); $lang->entry->note->name = '授权应用名称'; $lang->entry->note->code = '授权应用代号,必须为字母或数字的组合'; -$lang->entry->note->ip = "允许访问应用的ip,多个ip用逗号隔开。支持IP段,如192.168.1.*"; +$lang->entry->note->ip = "允许访问API的应用ip,多个ip用逗号隔开。支持IP段,如192.168.1.*"; $lang->entry->note->allIP = '无限制'; $lang->entry->note->api = 'moduleName、methodName以及参数列表替换成实际的值'; diff --git a/module/entry/model.php b/module/entry/model.php index 092c8c0556..08d41f8737 100644 --- a/module/entry/model.php +++ b/module/entry/model.php @@ -48,6 +48,25 @@ class entryModel extends model return $this->dao->select('*')->from(TABLE_ENTRY)->where('deleted')->eq('0')->orderBy($orderBy)->page($pager)->fetchAll('id'); } + /** + * Get log list of an entry . + * + * @param int $id + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getLogList($id, $orderBy = 'date_desc', $pager = null) + { + return $this->dao->select('*')->from(TABLE_LOG) + ->where('objectType')->eq('entry') + ->andWhere('objectID')->eq($id) + ->orderBy($orderBy) + ->page($pager) + ->fetchAll('id'); + } + /** * Create an entry. * diff --git a/module/entry/view/log.html.php b/module/entry/view/log.html.php index d005085aa2..bbbe144a51 100644 --- a/module/entry/view/log.html.php +++ b/module/entry/view/log.html.php @@ -1,32 +1,45 @@ - * @package entry + * @package log * @version $Id$ - * @link http://www.ranzhico.com + * @link http://www.zentao.net */ ?> - - + +
+
+ entry->common);?> + name;?> + entry->log;?> +
+
+
- - - + id}&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";?> + + + - + $log):?> - - - + + + + + + + +
action->date;?>action->actor;?>entry->desc;?>entry->id);?>entry->date);?>entry->url);?>
date;?>actor);?>extra;?>date;?>url;?>
show();?>
diff --git a/module/product/model.php b/module/product/model.php index c6c579931d..fbf7193973 100644 --- a/module/product/model.php +++ b/module/product/model.php @@ -209,7 +209,14 @@ class productModel extends model return $this->dao->select('*')->from(TABLE_PRODUCT) ->where('deleted')->eq(0) ->beginIF($status == 'noclosed')->andWhere('status')->ne('closed')->fi() - ->beginIF($status != 'all' and $status != 'noclosed')->andWhere('status')->in($status)->fi() + ->beginIF($status != 'all' and $status != 'noclosed' and $status != 'involved')->andWhere('status')->in($status)->fi() + ->beginIF($status == 'involved') + ->andWhere('PO', true)->eq($this->app->user->account) + ->orWhere('QD')->eq($this->app->user->account) + ->orWhere('RD')->eq($this->app->user->account) + ->orWhere('createdBy')->eq($this->app->user->account) + ->markRight(1) + ->fi() ->beginIF($limit > 0)->limit($limit)->fi() ->orderBy('`order` desc') ->fetchAll('id'); diff --git a/module/project/model.php b/module/project/model.php index a5ff1bcb47..cb89ef9044 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -601,6 +601,8 @@ class projectModel extends model */ public function getList($status = 'all', $limit = 0, $productID = 0, $branch = 0) { + if($status == 'involved') return $this->getInvolvedList($status, $limit, $productID, $branch); + if($productID != 0) { return $this->dao->select('t2.*')->from(TABLE_PROJECTPRODUCT)->alias('t1') @@ -629,6 +631,49 @@ class projectModel extends model } } + /** + * Get project lists. + * + * @param string $status involved + * @param int $limit + * @param int $productID + * @param int $branch + * @access public + * @return array + */ + public function getInvolvedList($status = 'involved', $limit = 0, $productID = 0, $branch = 0) + { + if($productID != 0) + { + return $this->dao->select('t2.*')->from(TABLE_PROJECTPRODUCT)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->leftJoin(TABLE_TEAM)->alias('t3')->on('t3.project=t2.id') + ->where('t1.product')->eq($productID) + ->andWhere('t2.deleted')->eq(0) + ->andWhere('t2.iscat')->eq(0) + ->beginIF($branch)->andWhere('t1.branch')->eq($branch)->fi() + ->andWhere('t2.openedBy', true)->eq($this->app->user->account) + ->orWhere('t3.account')->eq($this->app->user->account) + ->markRight(1) + ->orderBy('order_desc') + ->beginIF($limit)->limit($limit)->fi() + ->fetchAll('id'); + } + else + { + return $this->dao->select('t1.*, IF(INSTR(" done", t1.status) < 2, 0, 1) AS isDone')->from(TABLE_PROJECT)->alias('t1') + ->leftJoin(TABLE_TEAM)->alias('t2')->on('t2.project=t1.id') + ->where('t1.iscat')->eq(0) + ->andWhere('t1.openedBy', true)->eq($this->app->user->account) + ->orWhere('t2.account')->eq($this->app->user->account) + ->markRight(1) + ->andWhere('t1.deleted')->eq(0) + ->orderBy('t1.order_desc') + ->beginIF($limit)->limit($limit)->fi() + ->fetchAll('id'); + } + } + /** * Get projects lists grouped by product. * @@ -680,7 +725,7 @@ class projectModel extends model public function getProjectStats($status = 'undone', $productID = 0, $branch = 0, $itemCounts = 30, $orderBy = 'order_desc', $pager = null) { /* Init vars. */ - $projects = $this->getList($status, 0, $productID, $branch); + $projects = $this->getList($status, 0, $productID, $branch); foreach($projects as $projectID => $project) { if(!$this->checkPriv($project)) unset($projects[$projectID]); diff --git a/module/project/view/view.html.php b/module/project/view/view.html.php index aa3a862486..8fb16ea929 100644 --- a/module/project/view/view.html.php +++ b/module/project/view/view.html.php @@ -126,7 +126,7 @@ { if($product->type !== 'normal') { - $branchName = isset($branchGroups[$productID][$product->branch]) ? '/' . $branchGroups[$productID][$product->branch] : '' + $branchName = isset($branchGroups[$productID][$product->branch]) ? '/' . $branchGroups[$productID][$product->branch] : ''; echo html::a($this->createLink('product', 'browse', "productID=$productID&branch=$product->branch"), $product->name . $branchName); } else diff --git a/module/score/config.php b/module/score/config.php index ad0ee7bf97..cbfd3b1739 100644 --- a/module/score/config.php +++ b/module/score/config.php @@ -1,47 +1,45 @@ score = new stdClass(); -$config->score->model['user']['login'] = array('num'=>3, 'time'=>24, 'score'=>1, 'other'=>''); +$config->score->model['user']['login'] = array('num' => 3, 'time' => 24, 'score' => 1, 'other' => ''); +$config->score->model['user']['changePassword'] = array('num' => 1, 'time' => 0, 'score' => 10, 'other' => array(1 => 2, 2 => 5)); +$config->score->model['user']['editProfile'] = array('num' => 1, 'time' => 0, 'score' => 10, 'other' => ''); +$config->score->model['tutorial']['keepAll'] = array('num' => 1, 'time' => 0, 'score' => 100, 'other' => ''); +$config->score->model['ajax']['selectTheme'] = array('num' => 1, 'time' => 0, 'score' => 10, 'other' => ''); +$config->score->model['ajax']['selectLang'] = array('num' => 1, 'time' => 0, 'score' => 10, 'other' => ''); +$config->score->model['ajax']['showSearchMenu'] = array('num' => 1, 'time' => 0, 'score' => 10, 'other' => ''); +$config->score->model['ajax']['dragSelected'] = array('num' => 1, 'time' => 0, 'score' => 20, 'other' => ''); +$config->score->model['ajax']['lastNext'] = array('num' => 1, 'time' => 0, 'score' => 20, 'other' => ''); +$config->score->model['ajax']['switchToDataTable'] = array('num' => 1, 'time' => 0, 'score' => 1, 'other' => ''); +$config->score->model['ajax']['submitPage'] = array('num' => 1, 'time' => 0, 'score' => 1, 'other' => ''); +$config->score->model['ajax']['customMenu'] = array('num' => 1, 'time' => 0, 'score' => 1, 'other' => ''); +$config->score->model['doc']['create'] = array('num' => 0, 'time' => 0, 'score' => 5, 'other' => ''); +$config->score->model['todo']['create'] = array('num' => 5, 'time' => 24, 'score' => 1, 'other' => ''); +$config->score->model['story']['create'] = array('num' => 0, 'time' => 0, 'score' => 1, 'other' => ''); +$config->score->model['story']['close'] = array('num' => 0, 'time' => 0, 'score' => 1, 'other' => array('createID' => 2));//每个需求被完成关闭,需求的创建者额外增加2分,关闭者增加1分 - -$config->score->model['tutorial']['keepAll'] = array(1, 0, 100, ''); -$config->score->model['my']['changePassword'] = array(1, 0, 10, array(1 => 2, 2 => 5)); -$config->score->model['my']['editProfile'] = array(1, 0, 10, ''); - $config->score->model['block']['admin'] = array(1, 0, 20, ''); -$config->score->model['ajax']['selectTheme'] = array(1, 0, 10, ''); -$config->score->model['ajax']['selectLang'] = array(1, 0, 10, ''); -$config->score->model['ajax']['showSearchMenu'] = array(1, 0, 10, ''); -$config->score->model['ajax']['dragSelected'] = array(1, 0, 20, ''); -$config->score->model['ajax']['lastNext'] = array(1, 0, 20, ''); -$config->score->model['ajax']['switchToDataTable'] = array(1, 0, 1, ''); -$config->score->model['ajax']['submitPage'] = array(1, 0, 1, ''); - $config->score->model['bug']['saveTplModal'] = array(1, 0, 20, ''); -$config->score->model['custom']['ajaxMenu'] = array(1, 0, 1, ''); $config->score->model['search']['saveQuery'] = array(1, 0, 1, ''); $config->score->model['search']['saveQueryAdvanced'] = array(1, 0, 1, ''); -$config->score->model['my']['todo'] = array(5, 24, 1, ''); +$config->score->model['task']['create'] = array(0, 0, 1, '');//任务 +$config->score->model['bug']['create'] = array(0, 0, 1, '');//bug 有效之后,额外增加严重程度积分:s1 + 3, s2 + 2, s3 + 1 -$config->score->model['story']['create'] = array(0, 0, 1, '');//需求 -$config->score->model['task']['create'] = array(0, 0, 1, '');//任务 -$config->score->model['bug']['create'] = array(0, 0, 1, '');//bug 有效之后,额外增加严重程度积分:s1 + 3, s2 + 2, s3 + 1 -$config->score->model['doc']['create'] = array(0, 0, 5, '');//文档 $config->score->model['testcase']['create'] = array(0, 0, 1, '');//用例 //每完成一个任务,增加初始积分1 + 工时积分round(工时 /10 * 预计 / 消耗) + 优先级积分(p1 2, p2, 1) 如果任务取消了,没有积分。 -$config->score->model['task']['finish'] = array(0, 0, 1, array('time'=>'#time#/10 * #estimate# / #consumed#','pri'=>array(0=>0,1=>2,2=>1,3=>0)));//关闭一个任务,关闭者增加一个积分。 +$config->score->model['task']['finish'] = array(0, 0, 1, array('time' => '#time#/10 * #estimate# / #consumed#', 'pri' => array(0 => 0, 1 => 2, 2 => 1, 3 => 0)));//关闭一个任务,关闭者增加一个积分。 $config->score->model['task']['close'] = array(0, 0, 1, '');//关闭一个任务,关闭者增加一个积分。 $config->score->model['bug']['resolve'] = array(0, 0, 1, '');//解决一个bug,额外增加解决bug积分:s1 + 3, s2 + 2, s3 + 1 $config->score->model['testcase']['runCase'] = array(0, 0, 1, '');//每执行一次用例,加1分 @@ -50,4 +48,3 @@ $config->score->model['project']['build'] = array(0, 0, 10, '');//创建一 $config->score->model['project']['create'] = array(0, 0, 10, '');//创建一个项目,创建者增加10个积分 $config->score->model['productplan']['create'] = array(0, 0, 10, '');//创建一个计划,创建者增加10个积分 $config->score->model['release']['create'] = array(0, 0, 10, '');//创建一个发布,创建者增加10个积分 -$config->score->model['story']['close'] = array(0, 0, 1, array('createID'=>2));//每个需求被完成关闭,需求的创建者额外增加2分,关闭者增加1分 diff --git a/module/score/control.php b/module/score/control.php index 67bb245892..797f197249 100644 --- a/module/score/control.php +++ b/module/score/control.php @@ -40,8 +40,6 @@ class score extends control $pager = new pager($recTotal, $recPerPage, $pageID); $scores = $this->score->getScores($pager); - $this->loadModel('score')->score('user','login'); - $this->view->title = $this->lang->score->common; $this->view->user = $this->loadModel('user')->getById($this->app->user->account); $this->view->pager = $pager; @@ -52,14 +50,13 @@ class score extends control /** * Ajax action score * - * @param string $method + * @param string $method $.get(createLink('score', 'ajax', "method=selectLang")); * * @access public * @return void */ public function ajax($method = '') { - //处理由ajax提交过来的任务,主要是一次性任务 在请求模型的时候model=ajax, - $this->loadModel('score')->score('ajax','login'); + $this->loadModel('score')->score('ajax', $method); } } \ No newline at end of file diff --git a/module/score/lang/zh-cn.php b/module/score/lang/zh-cn.php index 6fb608bd3c..f5bff2ea6c 100644 --- a/module/score/lang/zh-cn.php +++ b/module/score/lang/zh-cn.php @@ -18,10 +18,27 @@ $lang->score->desc = '描述'; $lang->score->models['task'] = '任务'; $lang->score->models['tutorial'] = '新手教程'; -$lang->score->models['system'] = '系统'; $lang->score->models['user'] = '用户'; +$lang->score->models['ajax'] = 'UI'; +$lang->score->models['doc'] = '文档'; +$lang->score->models['todo'] = '待办'; +$lang->score->models['story'] = '需求'; -$lang->score->methods['task']['create'] = '创建任务'; -$lang->score->methods['tutorial']['finish'] = '任务完成'; -$lang->score->methods['system']['bug'] = '长得丑'; -$lang->score->methods['user']['login'] = '登录'; \ No newline at end of file + +$lang->score->methods['task']['create'] = '创建任务'; +$lang->score->methods['tutorial']['keepAll'] = '任务完成'; +$lang->score->methods['user']['login'] = '登录'; +$lang->score->methods['user']['changePassword'] = '修改密码'; +$lang->score->methods['user']['editProfile'] = '修改个人资料'; +$lang->score->methods['ajax']['selectTheme'] = '切换主题'; +$lang->score->methods['ajax']['selectLang'] = '切换语言'; +$lang->score->methods['ajax']['showSearchMenu'] = '搜索高级用法'; +$lang->score->methods['ajax']['customMenu'] = '自定义菜单'; +$lang->score->methods['ajax']['dragSelected'] = '列表页面拖动选中'; +$lang->score->methods['ajax']['lastNext'] = '快捷键翻页'; +$lang->score->methods['ajax']['switchToDataTable'] = '使用高级表格'; +$lang->score->methods['ajax']['submitPage'] = '修改分页数量'; +$lang->score->methods['doc']['create'] = '创建文档'; +$lang->score->methods['todo']['create'] = '创建待办'; +$lang->score->methods['story']['create'] = '创建需求'; +$lang->score->methods['story']['close'] = '需求关闭'; diff --git a/module/score/model.php b/module/score/model.php index 20a40538a0..76ca138580 100644 --- a/module/score/model.php +++ b/module/score/model.php @@ -36,21 +36,40 @@ class scoreModel extends model public function score($model = '', $method = '', $param = '') { if(empty($this->config->score->model[$model][$method])) return true; + $rule = $this->config->score->model[$model][$method]; + $desc = $this->lang->score->methods[$model][$method]; switch($model) { case 'user': - $desc = $this->lang->score->methods[$model][$method].'IP:'.helper::getRemoteIp(); - $this->saveScore($this->app->user->account, $this->config->score->model[$model][$method], $model, $method, $desc); + if($method == 'login') $desc = $this->lang->score->methods[$model][$method] . 'IP:' . helper::getRemoteIp(); + if($method == 'changePassword') + { + if(!empty($rule['other'][$param])) $rule['score'] = $rule['score'] + $rule['other'][$param]; + $desc = $this->lang->score->methods[$model][$method]; + } break; - case 'ajax': + case 'doc': + if($method == 'create') $desc = $this->lang->score->models[$model] . 'ID:' . $param; break; - case 'tutorial': + case 'todo': + if($method == 'create') $desc = $this->lang->score->methods[$model][$method] . 'ID:' . $param; break; - case 'my': - break; - case 'all': + case 'story': + $desc = $this->lang->score->methods[$model][$method] . 'ID:' . $param; + if($method == 'close') + { + $createUser = $this->dao->findById($param)->from(TABLE_STORY)->fetch(); + if(!empty($createUser)) + { + $newRule = $rule; + $newRule['score'] = $rule['other']['createID']; + $this->saveScore($createUser->openedBy, $newRule, $model, $method, $desc); + unset($newRule); + } + } break; } + $this->saveScore($this->app->user->account, $rule, $model, $method, $desc); } /** @@ -71,12 +90,12 @@ class scoreModel extends model { if(empty($rule['time'])) { - $count = $this->dao->slect('id')->from(TABLE_SCORE)->where('account')->eq($account)->andWhere('model')->eq($model)->andWhere('method')->eq($method)->count('id'); + $count = $this->dao->select('id')->from(TABLE_SCORE)->where('account')->eq($account)->andWhere('model')->eq($model)->andWhere('method')->eq($method)->count(); if($count >= $rule['num']) return true; } else { - $count = $this->dao->select('id')->from(TABLE_SCORE)->where('account')->eq($account)->andWhere('time')->between(date('Y-m-d 0:0:0'), date('Y-m-d 23:59:59'))->andWhere('model')->eq($model)->andWhere('method')->eq($method)->count('id'); + $count = $this->dao->select('id')->from(TABLE_SCORE)->where('account')->eq($account)->andWhere('time')->between(date('Y-m-d 0:0:0'), date('Y-m-d 23:59:59'))->andWhere('model')->eq($model)->andWhere('method')->eq($method)->count(); if($count >= $rule['num']) return true; } } diff --git a/module/story/model.php b/module/story/model.php index da7345bef5..8bc89b4a2f 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -228,6 +228,7 @@ class storyModel extends model } } $this->setStage($storyID); + $this->loadModel('score')->score('story', 'create',$storyID); return array('status' => 'created', 'id' => $storyID); } return false; @@ -342,6 +343,7 @@ class storyModel extends model $this->dao->insert(TABLE_STORYSPEC)->data($specData)->exec(); $actionID = $this->action->create('story', $storyID, 'Opened', ''); + $this->loadModel('score')->score('story', 'create',$storyID); $mails[$i] = new stdclass(); $mails[$i]->storyID = $storyID; $mails[$i]->actionID = $actionID; @@ -783,6 +785,7 @@ class storyModel extends model ->batchCheck($this->config->story->close->requiredFields, 'notempty') ->checkIF($story->closedReason == 'duplicate', 'duplicateStory', 'notempty') ->where('id')->eq($storyID)->exec(); + if($this->post->closedReason == 'done') $this->loadModel('score')->score('story', 'close', $storyID); return common::createChanges($oldStory, $story); } @@ -846,6 +849,7 @@ class storyModel extends model { die(js::error('story#' . $storyID . dao::getError(true))); } + if($story->stage == 'released') $this->loadModel('score')->score('story', 'close', $storyID); } return $allChanges; diff --git a/module/todo/model.php b/module/todo/model.php index 7f5bc11384..163892faaa 100644 --- a/module/todo/model.php +++ b/module/todo/model.php @@ -46,6 +46,7 @@ class todoModel extends model { $todoID = $this->dao->lastInsertID(); $this->file->updateObjectID($this->post->uid, $todoID, 'todo'); + $this->loadModel('score')->score('todo','create',$todoID); return $todoID; } } @@ -91,7 +92,9 @@ class todoModel extends model echo js::error(dao::getError()); die(js::reload('parent')); } - $this->loadModel('action')->create('todo', $this->dao->lastInsertID(), 'opened'); + $todoID = $this->dao->lastInsertID(); + $this->loadModel('action')->create('todo', $todoID, 'opened'); + $this->loadModel('score')->score('todo', 'create', $todoID); } else { diff --git a/module/tutorial/control.php b/module/tutorial/control.php index 20663b8b5b..3e9b81ee45 100644 --- a/module/tutorial/control.php +++ b/module/tutorial/control.php @@ -52,7 +52,11 @@ class tutorial extends control { if($_POST && isset($_POST['finish'])) $finish = $_POST['finish']; - if($finish == 'keepAll') $this->send(array('result' => 'fail', 'message' => $this->lang->tutorial->ajaxSetError)); + if($finish == 'keepAll') + { + $this->loadModel('score')->score('tutorial','keepAll'); + $this->send(array('result' => 'fail', 'message' => $this->lang->tutorial->ajaxSetError)); + } $account = $this->app->user->account; $this->session->set('tutorialMode', false); diff --git a/module/user/model.php b/module/user/model.php index 7d6db0fc7f..c5485c2c08 100644 --- a/module/user/model.php +++ b/module/user/model.php @@ -408,7 +408,7 @@ class userModel extends model } } if(!empty($user->password) and $user->account == $this->app->user->account) $this->app->user->password = $user->password; - + $this->loadModel('score')->score('user','editProfile'); if(!dao::isError()) { $this->loadModel('mail'); @@ -535,10 +535,10 @@ class userModel extends model dao::$errors['originalPassword'][] = $this->lang->user->error->originalPassword; return false; } - $this->dao->update(TABLE_USER)->data($user)->autoCheck()->where('id')->eq((int)$userID)->exec(); $this->app->user->password = $user->password; - $this->app->user->modifyPassword = false;; + $this->app->user->modifyPassword = false; + $this->loadModel('score')->score('user','changePassword',$this->computePasswordStrength($this->post->password1)); } /** diff --git a/module/webhook/control.php b/module/webhook/control.php index 026df9fb09..bab999ee9e 100644 --- a/module/webhook/control.php +++ b/module/webhook/control.php @@ -144,8 +144,7 @@ class webhook extends control $snoopy = $this->app->loadClass('snoopy'); foreach($dataList as $data) { - $webhook = zget($webhooks, $data->webhook, ''); - $httpCode = 0; + $webhook = zget($webhooks, $data->webhook, ''); if($webhook) { $contentType = zget($this->config->webhook->contentTypes, $webhook->contentType, 'application/json'); @@ -153,7 +152,7 @@ class webhook extends control $this->saveLog($data->webhook, $data->action, $webhook->url, $contentType, $data->data, $result); } - if($httpCode == 200) $this->dao->update(TABLE_WEBHOOKDATA)->set('status')->eq('sended')->where('id')->eq($data->id)->exec(); + $this->dao->update(TABLE_WEBHOOKDATA)->set('status')->eq('sended')->where('id')->eq($data->id)->exec(); } $this->dao->delete()->from(TABLE_WEBHOOKDATA)->where('status')->eq('sended')->exec(); diff --git a/module/webhook/lang/zh-cn.php b/module/webhook/lang/zh-cn.php index be16f050e3..2e95a320d8 100644 --- a/module/webhook/lang/zh-cn.php +++ b/module/webhook/lang/zh-cn.php @@ -22,8 +22,12 @@ $lang->webhook->product = '关联产品'; $lang->webhook->project = '关联项目'; $lang->webhook->action = '触发动作'; $lang->webhook->desc = '描述'; +$lang->webhook->createdBy = '由谁创建'; +$lang->webhook->createdDate = '创建时间'; +$lang->webhook->editedby = '最后编辑'; +$lang->webhook->editedDate = '编辑时间'; $lang->webhook->data = '数据'; -$lang->webhook->status = '状态'; +$lang->webhook->result = '结果'; $lang->webhook->sendTypeList['sync'] = '同步'; $lang->webhook->sendTypeList['async'] = '异步'; diff --git a/module/webhook/view/log.html.php b/module/webhook/view/log.html.php index 813b6cbaa4..8d2add7770 100644 --- a/module/webhook/view/log.html.php +++ b/module/webhook/view/log.html.php @@ -13,7 +13,7 @@
- type}"), $webhook->type ? $lang->webhook->dingding : $lang->webhook->common);?> + type}"), $webhook->type == 'dingding' ? $lang->webhook->dingding : $lang->webhook->common);?> name;?> webhook->log;?>
@@ -26,7 +26,7 @@ webhook->url);?> webhook->action);?> webhook->contentType);?> - webhook->status);?> + webhook->result);?> diff --git a/www/api.php b/www/api.php new file mode 100644 index 0000000000..47b3c0f838 --- /dev/null +++ b/www/api.php @@ -0,0 +1,53 @@ + + * @package ZenTaoPMS + * @version $Id: index.php 5036 2013-07-06 05:26:44Z wyd621@gmail.com $ + * @link http://www.zentao.net + */ +/* Set the error reporting. */ +error_reporting(0); + +/* Start output buffer. */ +ob_start(); + +/* Load the framework. */ +include '../framework/router.class.php'; +include '../framework/control.class.php'; +include '../framework/model.class.php'; +include '../framework/helper.class.php'; + +/* Log the time and define the run mode. */ +$startTime = getTime(); + +/* Instance the app. */ +$app = router::createApp('pms', dirname(dirname(__FILE__)), 'router'); + +/* Run the app. */ +$common = $app->loadCommon(); + +/* Check entry. */ +$common->checkEntry(); + +/* Set default params. */ +$config->requestType = 'GET'; +$config->default->view = 'json'; + +$app->parseRequest(); +$common->checkPriv(); +$app->loadModule(); + +$output = json_decode(ob_get_clean()); +$output = json_encode($output->data); + +unset($_SESSION['ENTRY_CODE']); +unset($_SESSION['VALID_ENTRY']); + +/* Flush the buffer. */ +echo helper::removeUTF8Bom($output); diff --git a/www/js/my.full.js b/www/js/my.full.js index fb7a494fb7..d654fa9788 100644 --- a/www/js/my.full.js +++ b/www/js/my.full.js @@ -415,6 +415,7 @@ function setTreeBox() function selectLang(lang) { $.cookie('lang', lang, {expires:config.cookieLife, path:config.webRoot}); + $.get(createLink('score', 'ajax', "method=selectLang")); location.href = removeAnchor(location.href); } @@ -427,6 +428,7 @@ function selectLang(lang) function selectTheme(theme) { $.cookie('theme', theme, {expires:config.cookieLife, path:config.webRoot}); + $.get(createLink('score', 'ajax', "method=selectTheme")); location.href = removeAnchor(location.href); }