Node專案之需求收集平臺

魯鵬發表於2016-12-16

邊學習邊實踐,斷斷續續一個月時間,也基本完成了需求收集平臺。學習了好多新的知識點,同時,也在這個專案裡做了一些嘗試,主要Get的技能是jQuery以及Ajax,所以這個專案大部分功能都是依靠非同步載入的方式來實現的。

PS. 回頭再看了下上面寫的評分系統,真是不忍直視,正在計劃重寫評分系統。

Node專案 | LP's Blog

(一)基本介紹

上個月只大概花了幾個小時就完成簡單的評分系統,非常簡單的第一個專案。然而在寫這個需求收集平臺的時候,考慮的問題很多,需求也變了好幾回(自己定需求自己開發也是醉了),而且剛開始學習使用jQuery框架來實現頁面互動,所以直到現在還沒有完整的完成所有功能。這個需求收集平臺相對於第一個專案有如下方面的改進:

  • 適當新增了部分CSS程式碼,不再只是使用原生bootstrap樣式而不寫一句css程式碼
  • 全面使用jQuery來實現介面互動(現學現賣)
  • 大幅使用ajax來非同步獲取響應,而不再是沒寫一句js程式碼
  • 每個頁面不再是獨立的一個檔案,適當的使用了分塊拼湊的方式,但仍然使用ejs(下次該換了它)
  • 使用bootstrap-table以及bootstrap-fileinput等等外掛實現部分功能
  • 資料依然使用的MySQL,只是根據表分檔案編寫,不再混為一談

整個專案到目前為止,前前後後也差不多1個月時間了,邊學習邊開發,個人感覺進步還是比較明顯的,個人技能的主要更新都在jQuery上了,從開始做這個專案的時候,才剛開始學習jQuery,在進行這個專案的這個月,也看完了《鋒利的jQuery》一書,收穫頗豐,書中學習的好多內容也在這個專案中得到了實踐。下面簡單介紹一下整個專案的介面以及基本功能。

前臺

前臺目前就兩個介面,一個是首頁index.ejs,一個是需求新增頁面add.ejs,簡單的兩個介面需求變更了好幾次,前期沒有提前設計出來,都是靠想象來寫前端程式碼,故而總是寫完後看著不爽就換了。最終形成下面的樣子,也不想再變動了。

首頁:index.ejs

點選條目的時候,會非同步載入詳細內容以及回覆內容等等。

新增頁面:add.ejs

bootstrap-fileinput外掛上傳圖片樣式

功能方面:

  • 首頁上點選訊息行專案非同步請求獲取詳情內容以及回覆
  • 首頁aside邊欄頁面載入完成後非同步獲取實時內容
  • 新增頁動態獲取需求分類以及對應的詳細分類值
  • 新增頁aside邊欄在點選詳細分類後觸發獲取可能要提交的問題
  • 引入bootstrap-fileinput外掛美化圖片上傳樣式

後臺

整個後臺看上去就一個頁面admin.ejs,不同的設定頁面都是通過bootstrap-table非同步載入json的方式來顯示的,其中包括基本資訊的設定、部門分類設定,需求分類設定以及使用者賬號密碼設定。其實也可以理解為有4個單獨的頁面,只是URL是不變的,全部通過非同步載入的方式來處理。

後臺首頁:admin.ejs

使用bootstrap原生modal實現的效果:

功能方面:

  • 使用bootstrap-table外掛來實現整體的功能框架
  • 輔助使用bootstrap一些原生javascript外掛來展示部分效果,如modal

做這個專案的時間跨度已經將近一個月時間,其中不乏各種需求變更,遲遲得不到自己想要的效果,很多時候都是夢想很美好,現實很殘酷(PS. 能力有限)。雖然現在好多的功能還沒有寫完,但是大體的樣式以及要實現的功能已經定型了,不想再改了,善始善終,接下來的時間就是完成它了。

完成之前在這裡簡單記錄一下,也算做是自己學習Node Web的一個專案實踐吧。關於這個專案的一些細節單獨再整理文章進行介紹。

(二)上傳外掛使用

該專案前臺表單上使用的是bootstrap-fileinput的樣式,bootstrap-fileinput是挺強大的一個檔案上傳外掛,注意是檔案上傳,不僅僅只是針對圖片上傳,初次接觸它光是調成自己想要的樣式也是花了半天時間呢,下面簡單介紹一下需求收集平臺這個專案使用的這個外掛一些細節問題。

對了,別忘了詳細看下官方說明文件:Bootstrap File Input - © Kartik,英文的,看著頭疼也要看下去。

1. 提交模式

首先文件簡要對比了一下兩種上傳模式,一是表單方式提交,一是Ajax方式提交。從下圖可以看出官方顯然是推薦你使用Ajax方式上傳的,很明顯使用Ajax方式上傳更加自由,並且能獲取更多的功能。

2. 匯入檔案

然後需要匯入必要的CSS以及JS檔案,以下這些是必須要匯入的,別除錯了半天才發現外掛都沒有匯入就搞笑了。

  1. bootstrap.css
  2. bootstrap.js
  3. jquery.js
  4. bootstrap-fileinput/css/fileinput.css
  5. bootstrap-fileinput/js/fileinput.js
  6. bootstrap-fileinput/js/locales/zh.js (中文語言檔案,可選擇是否匯入)

自己對號入座,尋找對應的檔案,以上6個必須要匯入,bootstrap-fileinput/js/plugins/目錄裡還有一些外掛視具體實現的功能匯入。

3. 基本使用

接下來就是外掛的使用了,起初我就是為了改善一下file型別的表單的樣式,預設的檔案上傳樣式實在不忍直視。

在不引入bootstrap-fileinput外掛相關檔案的時候,如下html程式碼:

<form method="POST" action="#">
    <div class="form-group">
        <label for="file">檔案輸入</label>
        <input type="file" name="file" id='myfile'>
    </div>
    <input type="submit" name="submit" value='提交' class="btn btn-primary">
</form>

顯示的效果是這樣的:

在引入bootstrap-fileinput外掛後,同樣的html程式碼,顯示效果是這樣的:

引入基本檔案後,在頁面底端新增一行js程式碼$('#myfile').fileinput();,就能出現不一樣的效果。完整的HTML程式碼如下:

<!DOCTYPE html>
<html>
<head>
  <title>fileinput-example</title>
  <meta charset="utf-8">
  <link rel="stylesheet" type="text/css" href="css/bootstrap.css">
  <link rel="stylesheet" type="text/css" href="css/fileinput.css">
  <script type="text/javascript" src="js/jquery.js"></script>
  <script type="text/javascript" src="js/bootstrap.js"></script>
  <script type="text/javascript" src="js/fileinput.js"></script>
  <script type="text/javascript" src="js/zh.js"></script>
</head>
<body>
  <div class="container">
    <div class="row">
      <div class="col-lg-6">
        <h1>fileinput-example</h1>
        <form method="POST" action="#">
          <div class="form-group">
            <label for="file">檔案輸入</label>
            <input type="file" name="file" id='myfile'>
          </div>
          <input type="submit" name="submit" value='提交' class="btn btn-primary">
        </form>
      </div>
    </div>
  </div>
  <script type="text/javascript">
    $('#myfile').fileinput();
  </script>
</body>
</html>

接下來,上傳幾個檔案試試預設的樣式是啥樣。

  • 上傳一個圖片試試

  • 上傳一個檔案試試

看起來是不是還可以,該專案最終顯示成如下樣子:

功能上做了一些限制,比如允許上傳多張照片,但只允許上傳3張,每個照片最大隻能是1MB。要想實現一些控制,那麼就要了解下面的一些引數。

4. 控制引數

在官方的說明文件裡都有介紹,但是很多情況,雖然有說明但也不一定能看懂,對於該外掛的功能我也不併不是很熟悉,我只是實現了我想要的效果,有興趣的可以自行學習。

下面是該專案中配置的一些引數:

$("#input-id").fileinput({
    showUpload: false,
    previewFileType: 'any',
    language: 'zh',
    browseLabel: '圖片多選',
    browseClass: 'btn btn-default',
    allowedFileTypes: ['image'], // 限制檔案型別為圖片
    allowedFileExtensions: ['jpg', 'png'], // 限制檔案字尾名為jpg,png,gif
    maxFileCount: 3,  // 限制最多3張圖片
    maxFileSize: 1024, // 限制圖片大小,最大1024KB
    allowedPreviewTypes: ['image'], // 允許預覽的檔案型別
    initialCaption: '可以選擇最多3張圖片,格式為png或者jpg,大小不超過1M', //     初始化說明框框,比如該專案上預設顯示:可以選擇最多3張圖片,格式為png或者jpg,大小不超過1M
    layoutTemplates: {
      main1: '{preview}\n' +
      '<div class="input-group {class}">\n' +
      '   <div class="input-group-btn">\n' +
      '       {browse}\n' +
      '       {remove}\n' +
      '   </div>\n' +
      '   {caption}\n' +
      '</div>',
      footer: '<div class="file-thumbnail-footer">\n' +
      '    <div class="file-caption-name">{caption}{size}</div>\n' +
      '</div>'
    }
  }); // 修改預設樣式,比如按鈕移到左側,預覽視窗中圖片的腳標等等(這裡只顯示檔名,如下圖)

這裡只是簡單介紹了一下bootstrap-fileinput外掛的簡單功能,更多功能的學習還是要靠自己的研究,特別是Ajax上傳功能。作者研究深度有限,暫不做過多介紹了,有機會的話,再做深入學習並分享。

(三)使用cookie實現點贊功能

又是一個臨時YY出來想要新增的功能,需求收集平臺旨在收集使用者的需求,然後給出基本的答覆以及更新需求狀態,但是針對那些重複的需求,也就沒有必要要求不同的使用者重複的去提交,但是又為了讓收集者知道哪些需求是使用者頻繁提出的,這樣就要求有個類似於點讚的功能,如果看到相同的需求,不需要重新新增一條需求,只需要在該需求上點個贊即可。

首先從使用者的角度簡單分析一下這個功能:

  1. 需要給每個需求條目新增點贊按鈕來觸發點贊動作
  2. 點過讚的條目與沒有點過讚的條目樣式要不一樣
  3. 不允許重複點贊
  4. 點贊可以取消

再來分析一下系統如何實現:

  1. 資料庫:後臺表需要有記錄每個需求條目點贊數量的欄位,新增完成後初始值為1,點贊+1,取消點贊-1
  2. 重複點贊:這個問題實現的方法其實挺多,比較靈活。比較常見的一種實現方法應該是通過使用者名稱來查重,該使用者針對一個需求條目只能點贊一次,如果點過贊再次點選則為取消點贊。

但是這個專案剛開始並沒有考慮設計使用者登陸功能,因為需求收集可能就是一個開放的平臺,在公司內網環境下,都可以通過需求收集平臺來提交使用者的問題或者建議,並不需要登陸。於是這裡我想到是否可以通過cookie的方式來實現這個功能,正好最近學習jQuery看到cookie那塊。

大體思路:
1. 頁面載入後,檢查需求條目是否有對應的cookie,如果沒有即沒有點過贊,設定樣式A;如果找到對應的cookie,證明已經點過贊,設定樣式B; 2. 點選動作同理,同樣是判斷是否有對應條目的cookie,有的話,點選即為-1;沒有的話,點選即為+1;

想到就動手實踐了,首先下載carhartl/jquery-cookie外掛,並在專案中引入以備後用。

前臺樣式如下動畫:

第一次點贊+1,背景變成淺紅色;再次點贊-1,樣式恢復;並且點贊後,重新整理頁面後依然是點贊狀態。接下來看看js是怎麼實現的:

/* 已經贊過的message 樣式設定,防止重新整理頁面後樣式恢復原樣 */
  $('.message-list-item').each(function(){
    var mid = $(this).attr('mid');
    var cookie = $.cookie('haveUp'+mid);
    if(cookie && cookie == 2){ // 2代表贊過,1代表沒有贊過
      $(this).find('div.up').addClass('up-yes'); // up-yes為紅色背景樣式
    }
  });
/* up a message 贊一個需求 */
  $('.qa-rank .up').click(function () {
    var messageId = $(this).attr('data-messageId');
    var $plus = $('<span id="plus"><strong>+1</strong></span>');
    var $minus = $('<span id="minus"><strong>-1</strong></span>');
    var $this = $(this);
    var bool = $.cookie('haveUp'+messageId); // 是否Up
    if(!bool || bool == 1){ // 贊一個需求
      $plus.insertAfter($this).css({
        'position': 'relative',
        'z-index': '1',
        'color': '#C30'
      }).animate({
        top: -30 + 'px',
        left: +30 + 'px'
      }, 'slow',function(){
        $(this).fadeIn('slow').remove();
      });
      $.ajax({
        url: '/ajax/up/' + messageId,
        method: 'POST',
        global: false,
        success: function (result) {
          $this.addClass('up-yes');
          $.cookie('haveUp'+messageId, 2, {path: '/', expires: 1});
        }
      });
      return false;
    }else{
      $minus.insertAfter($this).css({  // 取消贊
        'position': 'relative',
        'z-index': '1',
        'color': '#5cb85c'
      }).animate({
        top: -30 + 'px',
        left: +30 + 'px'
      }, 'slow',function(){
        $(this).fadeIn('slow').remove();
      });
      $.ajax({
        url: '/ajax/cancel/'+ messageId,
        method: 'POST',
        global: false,
        success: function(result){
          $this.removeClass('up-yes');
          $.cookie('haveUp'+messageId, 1, {path: '/'});
        }
      });
      return false;
    }
  });

程式碼邏輯很簡單,主要就是判斷是否點贊,如果點讚了,那麼建立id為minus的span節點插入到DOM中,然後給個動畫效果;如果沒有點贊,那麼建立id為plus的span節點插入到DOM中,同樣給個動畫效果;同時,通過ajax非同步請求資料到後臺更新資料庫中的點贊數量。

好了,這個小功能算是基本實現了,思路是不是對的暫不清楚,如果不對,請指正,學習就是不斷嘗試的過程。後面再繼續介紹該專案的一些內容。

相關文章