[Trac 經驗談之(1)雜談篇](http://blog.csdn.net/lanphaday/article/details/6609256)
[Trac 經驗談之(2)雜談篇補遺](http://blog.csdn.net/lanphaday/article/details/6658032)
[Trac 經驗談之(3)工作流篇](http://blog.csdn.net/lanphaday/article/details/6620098)
[Trac 經驗談之(4)報表篇](http://blog.csdn.net/lanphaday/article/details/6641391)
[Trac 經驗談之(5)插件篇](http://blog.csdn.net/lanphaday/article/details/6654027)
[Trac 經驗談之(6 完)插件篇補遺](http://blog.csdn.net/lanphaday/article/details/7100118)
# Trac 經驗談之(4)報表篇
賴勇浩([http://laiyonghao.com](http://laiyonghao.com))
最近又花時間折騰了一下 Trac 的用戶體驗,hack 了一個插件來實現屬主(owner)的選擇,重點是能夠顯示用戶填入的中文昵稱,這樣大家找起人來方便。不過今天我們不談這個,花開兩朵,各表一枝,繼續談計劃好的報表篇。
Trac 的報表功能是很強大、很靈活的,除了本身提供的各種報表,還可以由用戶自由定制。我不知道別人怎么定義 Trac 的報表這個術語,不過我是把 Trac 的路線圖(RoadMap)和查看任務單(Report,這個翻譯有點操蛋)都看作報表的,下面我們分別來談一談。
### 路線圖(RoadMap)
路線圖中的重要概念就是里程碑(MileStone),里程碑可以指定一個逾期日,和一個完成日,分別表示預期完成時間和實際完成時間,通過這兩個時間,可以看出是否存在延期或提前。每一個任務單(ticket)都有一個里程碑字段可供設定它所屬的里程碑,樂觀地說,如果能夠把項目的需求、缺陷和改進都分析、細化到多個 ticket 中去,并設定好里程碑,那么整個項目的計劃書就躍然紙上了。
在項目的推進中,不停地解決一些任務單,也不斷地有新的任務單增加進來,也不停地有一些任務單被轉移到其它里程碑中去,所以事實上里程碑里的任務單是不停地變化的。那如何才能快速、直觀地了解里程碑的進度和健康程度呢?路線圖報表就是用來解決這個問題的。

如上圖,可以看到有 3 個里程碑,以及屬于這些里程碑的任務單的狀態。通過頁面右上角的設置,還可以查看到已經完成的里程碑和做一些增進體驗的設置,如隱藏沒有截止日期的里程碑。這些里程碑的任務單狀態分組是已經定制過的,所以可以看到已關閉、測試中和開發中三個狀態的任務單數量,通過點擊狀態分組,可以進入此分組的任務單報表。定制狀態分組通過編輯 trac.ini 來完成,首先確保 trac.ini 中有如下一節:
~~~
[milestone]
stats_provider = DefaultTicketGroupStatsProvider
~~~
然后加入一個名為 milestone-groups 的節,我所用的定義如下:
~~~
[milestone-groups]
closed = closed
closed.order = 1
closed.query_args = group=resolution
closed.overall_completion = true
closed.label = 已關閉
resolved = resolved
resolved.order = 2
resolved.css_class = new
resolved.label = 測試中
active = *
active.order = 3
active.css_class = open
active.label = 開發中
~~~
其中 closed、resolved 和 active 都可以隨意定義,它們表示分組名(groupname)。每一個分組名的值是一個以逗號(,)分格的列表,每一個元素都是一個狀態名;也可以使用一次星號(*),它匹配了所有尚未指定的狀態。每一個分組都有 order、query_args、overall_completion、label 和 css_class 五個屬性供你設定,它們的意義如下:
1. order:決定了進度條中的顯示次序,越小的數值越排在前面;
1. label:顯示的名字;
1. css_class:css樣式類名,可以通過增加 table.progress td.<class>這種形式的 selector 來定義;
1. query_args:前文說過點擊進度條色塊或 label 會打開一個任務單查詢報表,這個參數的結果會附到那個報表的 url 之后,用來定制報表的,比如重載分組方式,可以使用 closed.query_args = group=resolution;
1. overall_completion:一個布爾值參數,標識在計算完成度時此組是否作為已完成狀態的組。
### 查看任務單(Report)
### 內建報表
Trac 內建了 8 個基礎報表,基本滿足了一般項目的需要。不過商業項目畢竟不比開源項目,老板或項目經理往往想要更方便地方式來了解項目或里程碑的進展情況,這時候就需要定制報表。不過在此之前,我們先來了解一下內建的 8 個報表的功能先:
1. 活躍的任務單(active tickets):非 closed 狀態的任務單
1. 活躍的任務單按版本劃分(active tickets by version):分組方式為版本
1. 活躍的任務單按里程碑劃分(active tickets by milestone):分組方式為里程碑
1. 已接受的活躍任務單按屬主劃分(accepted, active tickets by owner):accepted 狀態的任務單,分組方式為屬主
1. 全描述的已接受的活躍任務單按屬主劃分(accepted, active tickets by owner(full description)):accepted 狀態的任務單,分組方式為屬主,顯式完整的描述字段
1. 所有任務單(含已關閉的)按里程碑劃分(all tickets by milestone (including closed)):分組方式為里程碑的所有任務單(包括已關閉的)
1. 我的任務單(my tickets):屬主為我的任務單
1. 活躍的任務單,我的優先(active tickets, mine first):所有任務單,但屬主為我的排在前面。
為了方便查看我們的業務進展情況,我在此外還定制了 5 個報表,如下:
1. 最近變更的活躍任務單:獲得最近的項目動向
1. 活躍用戶單(按屬主劃分):獲得對組員工作壓力得信息
1. 我發起的任務單:獲得我發起的任務單現在的情況
1. 已解決的任務單:了解進入 resolved 狀態但還沒有通過 QA 人員檢測的任務單
1. 已關閉任務單:獲得已關閉任務單的情況,如了解它們的解決方案
新建的報表默認排在基礎報表之后,為獲得更好體驗,你可以改變這些報表在數據庫里的 ID 來重新排序,比如:
~~~
update report set id=5 where id=3;
~~~
執行以后就可以把原來排得較后的報表排到前面(不過 ID 是 PRIMARY KEY,所以需要注意它的唯一性)。
### 定制查詢
Trac 的報表定制性很強,而且提供了圖形界面的定制查詢和基于 SQL Query 語句的新建報表,在這里我們先來談一下較基礎的定制查詢,然后再深入到 SQL Query 語句及其注意事項。
點擊報表(report)頁面上部左右側的定制查詢連接就可以進入定制查詢頁面,一般地,已經在過濾器中加了屬主和狀態兩個字段,并且下方也顯示了當前的過濾結果,如下圖:

過濾器字樣下方的減號(-)按鈕可以用來刪除這個過濾器,每一個過濾字段都可以通過選擇或填寫來方便地設定過濾條件。在過濾器下面的“和”及“或”兩個下拉框可以用來添加新的過濾字段,如類型、報告人等。
列字樣的多選框用來選擇需要在報表中顯示的列,還有比較關鍵的是“結果分組”參數,可以按不同的 ticket 字段來分組,一般選擇屬主或狀態。
選好參數以后,可以點擊“更新結果”按鈕查看效果,如果覺得滿意,那么可以點擊頁面下方的“保存查詢”把這個報表添加到報表頁面了。
### 新建報表
定制查詢雖然方便,但失去了一些靈活性,Trac Reports 能夠讓用戶使用標準 SQL SELECT 語句進行報表定制。點擊報表頁面下方的“新建報表”按鈕,可以進入 SQL 或 TracQuery 的編輯頁面,定義好標題和它的描述,然后把 SQL 語句填入查詢框,再保存報表即可。如“按優先級和時間排序的所有活躍任務單”報表的查詢如下:
~~~
SELECT id AS ticket, status, severity, priority, owner,
time AS created, summary FROM ticket
WHERE status IN ('new', 'assigned', 'reopened')
ORDER BY priority, time
~~~
使用這種復雜的方式,是為了獲得更豐富的能力,比如在查詢中使用變量。這個規則解決,以$開頭的單詞將被看作變量,如:
~~~
SELECT id AS ticket,summary FROM ticket WHERE priority=$PRIORITY
~~~
這個 $PRIORITY 就是變量,它的值由報表頁面的 URL 傳進來:
~~~
http://trac.edgewall.org/reports/14?PRIORITY=high
~~~
除了定量,還有一些默認的特殊變量(或稱為常量),現在只有一個,$USER,使用這些特殊變量時需要改變 URL,Trac 自動地傳遞它的值,如查詢屬主為自己的任務單:
~~~
SELECT id AS ticket,summary FROM ticket WHERE owner=$USER
~~~
除此之外,Trac 還有自己的黑魔法——對一些字段自動格式化,主要有:
- ticket:修飾為帶 ticket url 超鏈接
- created, modified, date, time:把字段格式化為日期和(或)時間
- description:使用 wiki 引擎處理
還有 ID 和 realm 字段,不過這兩個字段得不多,就不介紹了。除了字段自動格式化,還可以定制列格式、改變報表行的布局等。
### wiki中的報表
有時候我們需要在 wiki 頁面中引用一些報表,這時候可以使用 TracQuery(它也可以替代 SQL 用在新建報表中)。它是 Trac 用來顯示符合特定需要的任務單的。比如你可以在 wiki 中寫入如下語句:
~~~
[query:status=new|assigned|reopened&version=1.0 對應1.0版的活躍任務單]
~~~
那么 wiki 引擎將把它渲染為一個指向 http://www.example.com/trac/query?status=new&status=assigned&status=reopened&version=1.0&order=priority 的超鏈接(錨文本是對應1.0版的活躍任務單),可以看到這個 URL 的參數正是 Query 語句的值。
Trac 強大的 wiki 引擎還可以使用 [[TicketQuery]] 宏把整個報表嵌入到 wiki 中,如:
~~~
[[TicketQuery(max=3,status=closed,order=id,desc=1,format=table,col=resolution|summary|owner|reporter,rows=description)]]
~~~
以上宏表示顯示按 ID 倒序排前 3 的已關閉的任務單,每條任務單顯示處理結果(resolution)、概述(summary)、屬主(owner)和報告人(report),然后再另起一行顯示任務單的描述(description)。
to be continued...