• 需求背景

    • 禅道开源版本对线上问题处理流程支持不是很友好,有很多限制,公司决定投入人力进行二次开发。

      需求清单

  • Bug Status 扩容

    • 禅道原生只有 已激活,已解决,已关闭三种状态。无法满足线上问题扭转需求。
    • 扩容后为
      • active,resolved,closed,fixed,in_process,postpone

        二开思路

        DB 方面

  • -> 找到 维护bug信息的表,在禅道中为 zt_bug 。观察 status字段,发现其为enum,即枚举格式,需要对其进行修改,就是需要增加枚举的值。 ``sql -- 测试环境集成 增量sql 2021.1.29 ALTER tablezt_bug` modify column status ENUM (“active”,”resolved”,”closed”,”postpone”,”in process”,”fixed”) default ‘active’;

  1. <a name="H1BXw"></a>
  2. ## 后端方面
  3. - 首先要根据url访问路径大致确认要修改的代码在源代码的 module所处位置。
  4. - 直接看实例
  5. - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1608527/1612442940853-d5eb9383-17fd-42ba-a546-348f129b9282.png#align=left&display=inline&height=1678&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1678&originWidth=2786&size=1160216&status=done&style=none&width=2786)
  6. [http://localhost:8888/www/bug-edit-1406.html](http://localhost:8888/www/bug-edit-1406.html)<br />这样一个链接,首先可以确定到 module 为 bug,涉及到的视图文件名为 edit 。
  7. <a name="b5xmS"></a>
  8. ### 找到模块
  9. - 进入到源码目录下,找bug module
  10. - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1608527/1612442314067-34c1e170-3911-4341-bb7b-aebd47d0efed.png#align=left&display=inline&height=646&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1292&originWidth=630&size=354173&status=done&style=none&width=315)
  11. - 目录解释
  12. - bug - > module 名
  13. - css - > 层叠样式表文件
  14. - js -> js方法代码
  15. - lang -> 该模块主要使用的字段存放
  16. - view -> 该模块的视图文件存放
  17. - model -> 该模块主要的后端方法存放
  18. <a name="lyYy5"></a>
  19. ### 找到视图文件
  20. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1608527/1612443053403-853fa51b-716b-451a-9973-cfe03bc0b959.png#align=left&display=inline&height=685&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1370&originWidth=756&size=689026&status=done&style=none&width=378)
  21. - 在视图文件中去寻找自己要修改的目标字段,比如本例中的bug_status
  22. - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1608527/1612443220588-588a400a-e346-4f86-8b7b-814b7cc39939.png#align=left&display=inline&height=1012&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1012&originWidth=2852&size=1730946&status=done&style=none&width=2852)
  23. <a name="hE17C"></a>
  24. ### 修改字库
  25. - 找到这蹩脚的bug状态字段支持,按照扩展的规则另起目录文件进行编辑。
  26. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1608527/1612443312567-510f5d6b-e806-4d4f-b0c1-4349312b4f84.png#align=left&display=inline&height=1212&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1212&originWidth=1546&size=1865820&status=done&style=none&width=1546)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/1608527/1612443356329-2f03f150-b70c-48db-a46d-6de9ac0bcc3f.png#align=left&display=inline&height=480&margin=%5Bobject%20Object%5D&name=image.png&originHeight=480&originWidth=1742&size=587213&status=done&style=none&width=1742)
  27. <a name="W0py1"></a>
  28. ### 修改方法
  29. - 因为是对bug的状态进行修改,也就是通常后端中常见的update方法。
  30. - 找到方法之后,就需要研读代码。读懂代码最好的方式是打断点进行debug,一个bug D上一天,虽愚也会有所闻的。
  31. - 按照 规定 在 zentaopms/module/bug/ext/model/update.php 下进行修改,没有的话请创建,这是前面几张文章提到的开发规范
  32. ```php
  33. <?php
  34. // 对 bug/model.php 中的update方法进行拓展
  35. /**
  36. * Update a bug.
  37. *
  38. * @param int $bugID
  39. * @access public
  40. * @return void
  41. */
  42. public function update($bugID)
  43. {
  44. // get oldBugInfo
  45. $oldBug = $this->dao->select('*')->from(TABLE_BUG)->where('id')->eq((int)$bugID)->fetch();
  46. if(!empty($_POST['lastEditedDate']) and $oldBug->lastEditedDate != $this->post->lastEditedDate)
  47. {
  48. dao::$errors[] = $this->lang->error->editedByOther;
  49. return false;
  50. }
  51. $now = helper::now();
  52. $bug = fixer::input('post')
  53. ->cleanInt('product,module,severity,project,story,task,branch')
  54. ->stripTags($this->config->bug->editor->edit['id'], $this->config->allowedTags)
  55. ->setDefault('product,module,project,story,task,duplicateBug,branch', 0)
  56. ->setDefault('openedBuild', '')
  57. ->setDefault('plan', 0)
  58. ->setDefault('deadline', '0000-00-00')
  59. ->setDefault('resolvedDate', '0000-00-00 00:00:00')
  60. ->setDefault('lastEditedBy', $this->app->user->account)
  61. ->add('lastEditedDate', $now)
  62. ->setIF(strpos($this->config->bug->edit->requiredFields, 'deadline') !== false, 'deadline', $this->post->deadline)
  63. ->join('openedBuild', ',')
  64. ->join('mailto', ',')
  65. ->join('linkBug', ',')
  66. ->setIF($this->post->assignedTo != $oldBug->assignedTo, 'assignedDate', $now)
  67. ->setIF($this->post->resolvedBy != '' and $this->post->resolvedDate == '', 'resolvedDate', $now)
  68. ->setIF($this->post->resolution != '' and $this->post->resolvedDate == '', 'resolvedDate', $now)
  69. ->setIF($this->post->resolution != '' and $this->post->resolvedBy == '', 'resolvedBy', $this->app->user->account)
  70. ->setIF($this->post->closedBy != '' and $this->post->closedDate == '', 'closedDate', $now)
  71. ->setIF($this->post->closedDate != '' and $this->post->closedBy == '', 'closedBy', $this->app->user->account)
  72. ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'assignedTo', 'closed')
  73. ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'assignedDate', $now)
  74. ->setIF($this->post->resolution != '' or $this->post->resolvedDate != '', 'status', 'resolved')
  75. ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'status', 'closed')
  76. ->setIF(($this->post->resolution != '' or $this->post->resolvedDate != '') and $this->post->assignedTo == '', 'assignedTo', $oldBug->openedBy)
  77. ->setIF(($this->post->resolution != '' or $this->post->resolvedDate != '') and $this->post->assignedTo == '', 'assignedDate', $now)
  78. ->setIF($this->post->resolution == '' and $this->post->resolvedDate =='', 'status', 'active')
  79. ->setIF($this->post->resolution != '', 'confirmed', 1)
  80. // 对原有的update方法进行拓展,支持新增的两个bug_status
  81. ->setIF($this->post->status == 'in process', 'status', 'in process')
  82. ->setIF($this->post->status == 'postpone', 'status', 'postpone')
  83. ->setIF($this->post->status == 'fixed', 'status', 'fixed')
  84. // FIXME 支持修改新增的字段
  85. ->setIF($this->post->story != false and $this->post->story != $oldBug->story, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story))
  86. ->setIF(!$this->post->linkBug, 'linkBug', '')
  87. ->remove('comment,files,labels,uid,contactListMenu')
  88. ->get();
  89. $bug = $this->loadModel('file')->processImgURL($bug, $this->config->bug->editor->edit['id'], $this->post->uid);
  90. $this->dao->update(TABLE_BUG)->data($bug)
  91. ->autoCheck()
  92. ->batchCheck($this->config->bug->edit->requiredFields, 'notempty')
  93. ->checkIF($bug->resolvedBy, 'resolution', 'notempty')
  94. ->checkIF($bug->closedBy, 'resolution', 'notempty')
  95. ->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty')
  96. ->where('id')->eq((int)$bugID)
  97. ->exec();
  98. if(!dao::isError())
  99. {
  100. if(!empty($bug->resolvedBy)) $this->loadModel('score')->create('bug', 'resolve', $bugID);
  101. $this->file->updateObjectID($this->post->uid, $bugID, 'bug');
  102. return common::createChanges($oldBug, $bug);
  103. }
  104. }
  • 上面的代码是已经修改了的代码,其中 this->post->status 是前端页面发送回来的bug_status 相关信息,因为php的语法有些特殊,所以看起来有些奇怪。

    前端方面

    思路

  • 从思路上来讲

    • 前端发送给后端的数据
    • 前端需要进行展示的字段支持 — 也就是模块下的lang文件。
    • 前端需要进行控制的字段,涉及到php控制的一些方法,这些在后续文章中陆续分享。
    • 本篇中涉及到前端的部分比较简单,所以略述,详细的爬坑记录等待下次

      涉及修改文件总结

  • 前端 module/bug/ext/view/edit.html.php

  • 后端 module/bug/ext/model/update.php
  • 字库 module/bug/lang/zh-cn.php