實現一個基於 SharePoint 2013 的 Timecard 應用(中)

門戶視圖

隨着 Timecard 列表的增多,如何查找和管理這許多的 Timecard 也就成了問題。尤爲對於團隊經理而言,他除了本身填寫的 Timecard,還要審覈團隊成員的 Timecard 任務更重。php

 

這裏我把實際的需求簡化成爲 2 個主要的視圖(但可以提供的效果和實際需求實際上是很是接近的):web

  1. Time Window 視圖
    這個視圖列出當前用戶在全部能夠填寫的時間窗口中是否提交了 Timecard,起到提醒的做用。
    image
  2. Timecard 視圖
    這個視圖列出在 Timecard 網站中,全部當前用戶參與(包括提交和審批 Timecard)的項目/組織中的 Timecard 的審批狀態。方便了解本身的 Timecard 填報進展、方便團隊經理查找尚未審批的 Timecard。
    image

 

技術方案

2個門戶視圖有不少種技術方案來實現。promise

  • Content Query Web Part 或者 Content Search Web Part。實現第二個視圖還勉強能夠,注意,只是勉強。實現第一個視圖須要 Group Count 功能,直接歇菜。Pass。
  • 可視化 Web Part。C# 開發,服務器(場)部署。能夠利用服務器端的緩存技術來提升性能。不過,調試是個噩夢,不信你能夠搬着指頭數數你重啓一次 Web Front 須要多少秒。
  • Sandbox Web Part。C# 開發,網站部署。具備上面服務器場方案的優勢外也避免了它的缺點。不過 SharePoint 2013 叫你們不要用。
  • SharePoint Hosted App。JavaScript 開發,服務器(場)發佈、網站部署。須要額外配置一個專用的 app 域名和證書。其實這個方案不錯,擴展性也很好。可是相比下面的方案,實現顯得複雜了點兒。(另外,若是有時間折騰,其實 Provider Hosted App 也能夠考慮,這個甚至容許你用 PHP 來寫。是那些不喜歡(不肯意喜歡)SharePoint 而又不得不用 SharePoint 的人的不二之選)。順帶提一句,全部 App 方案都有一個巨大初始的優點:調試。直接用 VS 調 JavaScript,那是至關喜聞樂見的。爲何說是「初始」的優點呢?由於一旦基本的 SharePoint 操做你都調得差很少了(熟練掌握)的時候,這個優點就慢慢消失了,那個時候,你的 JavaScript 代碼其實已經不容易出現沒法在 failure 函數裏面捕獲的錯誤了。
  • Embedded JavaScript,在網頁上面嵌 JavaScript 代碼。實現起來最簡單,最好維護,對服務器端壓力也最小,不刷屏,保護視力。就以上門戶視圖的需求來看,我選擇這個方案。並且,這個方案的代碼,搬到 SharePoint Hosted App 也不浪費的。

 

技術實現

JavaScript (SharePoint CSOM)開發,最煩的是其異步回調的機制。全部向服務器發送的操做,都要在回調函數裏面收結果,而後你才能繼續下一步的業務邏輯。緩存

目前我找到的比較容易減輕這個症狀的方案,是用 Deferred。先將調用服務器的操做用 Deferred 包裝,而後用 $.when 來調用並捕獲其返回結果。這樣,至少形式上看上去,後續的業務邏輯操做是緊跟在前面一步的服務器調用後面的,看上去就舒服多了。服務器

也有不少 JavaScript 的函數庫提供了這個問題的解決方案,但在試用以後,我都放棄了。簡單的問題仍是用簡單的方案吧。app

 

爲了說明這個實現方法,咱們先看一個空的 Deferred 包裝的 SharePoint 調用:異步

   1: return $.Deferred(function (dtd) {
   2:     var web = context.get_web();
   3:     sp.context.load(web);
   4:     var failure_callback = Function.createCallback(onSharePointFailed, dtd);
   5:     sp.context.executeQueryAsync(
   6:         function () {
   7:             var title = web.get_title();
   8:             dtd.resolve();
   9:         },
  10:         Function.createDelegate(this, failure_callback));
  11: }).promise();

 

上面的例子中,context 是在調用前初始化好了的 SharePoint Context 全局變量,而 onSharePointFailed 則是預先定義的出錯回調函數。ide

經過上面這樣的形式,就完成了一個最簡單的 Deferred 封裝。函數

 

爲了使用上面的封裝,咱們先要將其放入一個函數中去:性能

   1: var spGetWeb = function () {
   2:     var web = context.get_web();
   3:     context.load(web);
   4:     var failure_callback = Function.createCallback(sp.Failed, dtd);
   5:     sp.context.executeQueryAsync(
   6:         function () {
   7:             var title = web.get_title();
   8:             dtd.resolve();
   9:         },
  10:         Function.createDelegate(this, failure_callback));
  11:     }).promise();
  12: }

 

好了,下面就能夠開始調用了(這只是個例子,真的要調用,仍是要作不少準備的,好比初始化 context 等等):

   1: $.when(spGetWeb())
   2:     .done(function(){
   3:         message.succeed("Web is ready.");
   4:         $.when(spGetList("Time Window"))
   5:             .done(function(){...})
   6:             .fail(function(){...});
   7:     })
   8:     .fail(function(){
   9:         message.error("Can't get the web.");
  10:     }}

 

 

上面的例子中,先調用了 spGetWeb,在成功之後(done),接着又調用了 spGetList。這樣,原先像麪條同樣散落的回調業務邏輯,能夠用比較人性化的方式呈現了,咱們也好少死幾個腦細胞。

 

下面的視頻是實現的效果:

 

 

署名-非商業使用-禁止演繹

相關文章
相關標籤/搜索