• 魔改!让“禅道”拥有 抄送列表


    禅道是第一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法scrum,内置了产品管理和项目管理。
    官方传送门:https://www.zentao.net/
    禅道有多个版本:专业版、企业版、集团版、开源版。
    在使用禅道开源版的过程中,发现了一个问题(不确定是不是使用方式不对),就是禅道的抄送数据并没有在列表中可以展现。

    所以摸索了一下实现了以下功能:

    1. 产品->需求列表加入“抄送给我”的需求列表
    2. 测试->BUG列表加入“抄送给我”的BUG列表

    1. 参考文档

    禅道使用自主开发的zentaophp框架开发,内置了完整的扩展机制(非简单的钩子),用户可以非常方便的对禅道进行彻底的二次开发。
    zentaophp开发手册地址:https://devel.easycorp.cn/book/zentaophphelp/about-10.html
    zentaophp二次开发文档地址:https://devel.easycorp.cn/book/extension/intro-45.html

    2. 流程分析

    zentaophp的请求分发是按url地址来划分的,比如/product-browse-1.html这个请求。
    其中:product是一个模块,而browse是这个模块control的一个接口。
    以BUG列表为例:
    control的browse接口接收到http请求后调用model的getBugs方法拉取bugs数据,然后将数据填充到/view/browse.html.php视图中显示出来。

    bug

    需求的流程大致是一样的,不过需求的入口是product模块,然后通过调用story拉取数据。

    3. 拓展功能

    zentaoPHP框架每个模块按照mvc进行划分,有自己的control(控制层)、 model(模型层)和view(视图层),并且提供了非常便利的拓展方式。
    想要拓展自己的功能只需要将拓展代码放在每个模块的ext目录下即可,可以看一下效果图:
    拓展前:
    old
    拓展后:
    new

    a. 对视图层进行拓展

    为了不改变禅道的源码,对视图层的拓展钩子进行扩展,钩子脚本的命名规则为方法名. 扩展名.html.hook.php。
    所以对应的拓展页面名称为:browse.mailto.html.hook.php,存放路径为:module/bug/ext/view。内容如下:

    <script>
      <?php
      $mail_to_type = 'mailtome';
      $mail_to_label = "<span class='text'>抄送给我</span>";
      $mail_to_active = $mail_to_type == $browseType ? 'btn-active-text' : '';
      $mail_to_uri = html::a($this->createLink('bug', 'browse', "productid=$productID&branch=$branch&browseType=$mail_to_type"), $mail_to_label, "", "class='btn btn-link $mail_to_active'");
      $mail_to_uri = str_replace(array("
    ", "
    ", "
    "), "", $mail_to_uri);
      ?>
      $('#bysearchTab')
        .parent()
        .find('a:eq(3)')
        .after("<?php echo $mail_to_uri ?>");
    </script>
    

    通过zentaoPHP的js模块生成a标签,如果将a标签用jQuery插入到指定的位置。

    b. 对模型层进行拓展

    上面视图层拓展中,“抄送给我”调用的还是bug模块的browse接口,所以不需要对control进行拓展,只需要重写model的getBugs方法,添加对browseType=‘mailtome’的数据进行处理即可。

    重写getBugs方法,拓展文件名称以getBugs方法名称命名,路径为module/bug/ext/model/,内容如下:

    <?php
    public function getBugs($productID, $projects, $branch, $browseType, $moduleID, $queryID, $sort, $pager)
    {
      if($browseType == 'mailtome')
      {
        /* Set modules and browse type. */
        $modules    = $moduleID ? $this->loadModel('tree')->getAllChildId($moduleID) : '0';
        $browseType = ($browseType == 'bymodule' and $this->session->bugBrowseType and $this->session->bugBrowseType != 'bysearch') ? $this->session->bugBrowseType : $browseType;
        $bugs = array();
        $bugs = $this->getMailToMeBugs($productID, $branch, $modules, $projects, $sort, $pager);
        return $this->checkDelayBugs($bugs);
      } 
      else 
      {
        return parent::getBugs($productID, $projects, $branch, $browseType, $moduleID, $queryID, $sort, $pager);
      }
    }
    ?>
    

    这里,如果$browseType='mailtome'的话,就调用getMailToMeBugs这个方法,否则调用父级的getBugs方法。
    getMailToMeBug这个方法是自己拓展的,所有需要在module/bug/ext/model/路径下创建对应的php,内容如下:

    <?php
    public function getMailToMeBugs($productID, $branch, $modules, $projects, $orderBy, $pager)
    {
        return $this->dao->select('*')->from(TABLE_BUG)
          ->where('project')->in(array_keys($projects))
          ->andWhere('product')->eq($productID)
          ->beginIF($branch)->andWhere('branch')->in($branch)->fi()
          ->beginIF($modules)->andWhere('module')->in($modules)->fi()
          ->andWhere('deleted')->eq(0)
          ->andWhere('mailto', true)->like('%,' . $this->app->user->account . ',%')
          ->orWhere('mailto')->like('%,' . $this->app->user->account)
          ->markRight(1)
          ->andWhere('status')->eq('active')
          ->orderBy($orderBy)->page($pager)->fetchAll();
    }
    ?>
    

    根据禅道的抄送入库规则“,账号”,只需要查询“,账号,”“,账号”的数据即可,这里只查询状态为激活的BUG。

    c. 拓展需求“抄送给我”列表

    需求“抄送给我”的拓展方式跟BUG“抄送给我”的拓展方式是一样的,需要注意的是需求入口是product模块,拉取的数据是story模块。

    story拓展的model代码:

    <?php
    public function getByMailTo($productID, $branch, $modules, $orderBy, $pager)
    {
      $stories = $this->dao->select('*')->from(TABLE_STORY)
        ->where('product')->in($productID)
        ->andWhere('deleted')->eq(0)
        ->beginIF($branch)->andWhere("branch")->eq($branch)->fi()
        ->beginIF($modules)->andWhere("module")->in($modules)->fi()
        ->andWhere('mailto', true)->like('%,' . $this->app->user->account . ',%')
        ->orWhere('mailto')->like('%,' . $this->app->user->account)
        ->markRight(1)
        ->andWhere('stage')->ne('closed')
        ->orderBy($orderBy)
        ->page($pager)
        ->fetchAll();
      return $this->mergePlanTitle($productID, $stories, $branch);
    }
    ?>
    

    下面是拓展后的效果:

    story

    至此,就可以在禅道上查看“抄送给我”的需求和BUG了。

    我是写java的,不会php代码,这里的代码都是根据开发手册依葫芦画瓢的。

    =========================================================
    源码可关注公众号 “HiIT青年” 发送 “zentao” 获取。

    HiIT青年
    关注公众号,阅读更多文章。

  • 相关阅读:
    FaWave(发微)Chrome上的多微博全能插件
    ASP.NET MVC3 on Mono的折腾(二):Linux(openSUSE)下的部署
    ASP.NET MVC 的统一异常处理有多难?(衍生的意图,出错后如何保持表单的状态?)
    Visual Studio 2010 Addin 获得当前项目的类型实例
    ASP.NET 4.0 一些隐性的扩展
    在程序中动态执行T4模板,如何传参数给T4模板?
    DataContext是否可以静态化?
    迟到的2010总结
    ASP.NET MVC表单的组件化
    ASP.NET MVC 2:实体外部元数据扩展
  • 原文地址:https://www.cnblogs.com/itqn/p/13374930.html
Copyright © 2020-2023  润新知