甘特圖的資料結構分為兩部分,任務的資料和任務依賴關系的資料。這種設計大幅度的降低了資料之間的耦合關系,也更加接近于我們平時的資料庫設計,降低了和資料庫接口之間的難度。
先看一個任務的資料結構簡單的XML的例子。
1. <Tasks>
2. <Task>
3. <Id>1</Id>
4. <Name>Planning</Name>
5. <StartDate>2010-01-18T00:00:00-08:00</StartDate>
6. <EndDate>2010-02-02T00:00:00-08:00</EndDate>
7. <PercentDone>40</PercentDone>
8. <ParentId>null</ParentId>
9. <IsLeaf>false</IsLeaf>
10. <Responsible></Responsible>
11. </Task><Task>
12. <Id>11</Id>
13. <Name>Investigate</Name>
14. <StartDate>2010-01-18T00:00:00-08:00</StartDate>
15. <EndDate>2010-01-28T00:00:00-08:00</EndDate>
16. <PercentDone>30</PercentDone>
17. <ParentId>1</ParentId>
18. <IsLeaf>true</IsLeaf>
19. <Responsible></Responsible>
20. </Task>
21. </Tasks>
一個任務可以有很多屬性,但是必須包括以下的資料,甘特圖才能夠顯示出來。
l 'Id', 任務Id
l 'Name', 任務名稱
l 'StartDate', 開始時間
l 'EndDate', 結束時間
l 'PercentDone',完成的百分比
l 'ParentId', 父任務
l 'IsLeaf', 是否是葉節點
任務跟任務之間的可以有四種關系:完成-完成(FF) 0,完成-開始(FS) 1,開始-完成(SF) 2,開始-開始(SS) 3。當有前置任務時,根據不同的任務相關性類型,将會顯示四種不同的任務箭頭連線。
依賴關系的資料結構非常簡單,隻包括三個屬性
l From,前置任務的ID
l To,任務的ID
l Type,任務跟任務之間的可以有四種關系:完成-完成(FF) 0,完成-開始(FS) 1,開始-完成(SF) 2,開始-開始(SS) 3。
以下是一個任務的資料結構簡單的XML的例子。
1. <Links>
2. <Link>
3. <From>12</From>
4. <To>17</To>
5. <Type>2</Type>
6. </Link>
7. <Link>
8. <From>20</From>
9. <To>19</To>
10. <Type>2</Type>
11. </Link>
12. </Links>
以上的例子都是基于XML的。 也就是說,甘特圖可以讀取靜态的XML,或者是ASP.NET、Java等後端程式生成的XML。除了XML,Extjs甘特圖也支援更多的資料結構和資料格式。事實上,使用者可以任意組織存儲自己的項目資料,無論是服務端是.NET還是JAVA,無論資料庫是ORACLE還是MYSQL,無論資料傳輸方式是JSON 還是XML, Web Service,Rest等等。Extjs自身提供的強大Datareader,可以滿足各種不同的需求。
加載資料
我們在來看看我們的DataStore是如何寫的。除了定義資料結構以外,我們還定義了一個叫做Proxy的對象。
1. var taskStore = new Ext.ux.maximgb.tg.AdjacencyListStore({
2. proxy : new Ext.data.HttpProxy({
3. url : 'tasks.xml',
4. method:'GET'
5. }),
6. ...
7. });
在以上的例子中我們定義了一個HttpProxy, DataProxy 字面解釋就是資料代理,也可以了解為資料源,也即從哪兒或如何得到需要交給DataReader 解析的資料。資料代理(源)基類由Ext.data.DataProxy 定義,在DataProxy的基礎,ExtJS 提供了Ext.data.MemoryProxy、Ext.data.HttpProxy、Ext.data.ScriptTagProxy等三個分别用于從用戶端記憶體資料、Ajax 讀取伺服器端的資料及從跨域伺服器中讀取資料等三種實作。
DependencyStore的配置和這裡的類似,我們就不再敖述。隻給出一個簡單的代碼片段。
上一節我們講述了如何顯示甘特圖,當使用者增加删除了一些任務,或者改變了任務之間的依賴關系,我們如何将改動後的資料送出到伺服器,在伺服器中儲存到資料庫或檔案系統中呢?
答案非常簡單,隻要實作Data Store的四個接口(增删改查)就可以了。我們先來看一段代碼。
1. proxy : new Ext.data.HttpProxy({
2. disableCaching : false,
3. api: {
4. read : 'webservices/Tasks.asmx/Get',
5. create: 'webservices/Tasks.asmx/Create',
6. destroy: 'webservices/Tasks.asmx/Delete',
7. update: 'webservices/Tasks.asmx/Update'
8. }
9. }),
在以上的代碼中,分别定義了四個不同的url,分别對應着增删改查四個操作的URL位址。例如,使用者修改了一個任務,甘特圖控件就會将修改後的資料送出到webservices/Tasks.asmx/Update。 其他的操作同理。下面我們以修改為例,看看在ASP.NET的伺服器端是如何擷取修改後的資料的。
1. [WebMethod]
2. [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
3. public Object Update(Task[] jsonData)
4. {
5. DataClasses1DataContext _db = new DataClasses1DataContext();
6. try
7. {
8. foreach (Task data in jsonData)
9. {
10. Task t = _db.Tasks.SingleOrDefault(b => b.Id == data.Id);
11. if (t != null)
12. {
13. t.Name = data.Name;
14. t.IsLeaf = data.IsLeaf;
15. t.ParentId = data.ParentId;
16. t.PercentDone = data.PercentDone;
17. t.StartDate = data.StartDate;
18. t.EndDate = data.EndDate;
19. t.Priority = data.Priority;
20. }
21. }
22. _db.SubmitChanges(ConflictMode.ContinueOnConflict);
23. }
24. catch (Exception ex)
25. {
26. int a = 0;
27. }
28. return new { success = true };
29. }
在以上的例子中,我們建立一個Web Service來實作增删改查,這個Web Servic裡面有一個Update的方法。請注意在該方法的前面,有[ScriptMethod(ResponseFormat = ResponseFormat.Json)]這樣一個申明。他說明這個Web Service送出的資料是一個JSON資料。
函數Update的參數是一個Task的數組,我們隻需要周遊這個數組,就可以将所有的被修改的任務資料提取出來,然後根據不同的業務邏輯,更新資料庫或檔案系統。