1. 程式人生 > >淘淘商城——內容管理

淘淘商城——內容管理

上文我們一起學習了內容分類管理,雖說實現了展示內容分類和新增節點這兩個功能,但重新命名節點和刪除節點這兩個功能還未開發,主要是時間太緊了,以後我一定會完善這些功能,讀者如果有興趣,也可以實現這些功能,希望大家都能學有所成。廢話扯了一大堆,進入主題,本文我們將一起學習內容管理。

內容列表查詢

首先,我們先來看看內容管理後臺頁面,如下圖所示,可以看到頁面分為兩部分,即分為左側內容分類和右側內容列表兩個部分。
為什麼內容管理頁面左側的內容分類樹形列表直接就是好的呢?其實我們看看程式碼就知道了,我們訪問的入口是index.jsp頁面,這個頁面有”內容管理”模組,當我們點選內容管理時,就會去請求content.jsp頁面。
這裡寫圖片描述


我們再來看看content.jsp頁面的程式碼,如下圖所示。可以看到上面那個div就是展示我們的內容分類列表的,發起的請求與我們上文中為實現展示內容分類功能發起的請求完全一樣,因此這裡不用我們做任何處理就已經可以使用了。下面的div就是內容管理後臺頁面的右部分,用來顯示內容列表,頁面載入的時候,會發起url:'/content/query/list',queryParams:{categoryId:0}這樣的請求,這個請求會去查詢所有內容分類下的所有內容。內容列表的展示其實跟商品列表的展示及其相似,大家可以參考我之前的這篇文章進行學習,不同的地方是內容列表要根據左邊樹形節點的id的變化而變化。
這裡寫圖片描述
那麼內容列表又是如何跟左邊的內容分類聯絡起來的呢?我們看下面的js程式碼,如下圖所示。
這裡寫圖片描述

  • $(function(){...});函式是在頁面載入完之後觸發執行的js程式碼。
  • var tree = $("#contentCategoryTree");顯然是獲取內容分類樹。
  • var datagrid = $("#contentList");是獲取內容列表。
  • onClick : function(node){...}這段程式碼的意思是當我們點選左邊內容分類樹的某個節點時,會做一下判斷,判斷是不是葉子節點,如果是葉子節點那麼就給categoryId賦值為這個葉子節點的id並且會重新載入內容列表,也就意味著重新發起url:'/content/query/list'請求,只是這時的queryParams引數中categoryId的值變成了單個葉子節點的id。

搞清了內容列表的展示原理後,照理說我們現在就應該馬上實現內容列表展示的功能,但因為時間太緊,不打算實現該功能,留待以後開發。
未完,待續。。。

新增內容

我們還得從頁面程式碼說起,新增內容是在content.jsp頁面當中定義的,我們可以看到內容列表中有”toolbar:contentListToolbar”這麼一句程式碼,這句程式碼的意思是定義了工具欄,工具欄中有多個功能。
這裡寫圖片描述
我們來看看工具欄的程式碼,裡面有新增、編輯、刪除三個操作,如下所示:

var contentListToolbar = [{
    text:'新增',
    iconCls:'icon-add',
    handler:function(){
        var node = $("#contentCategoryTree").tree("getSelected");
        if(!node || !$("#contentCategoryTree").tree("isLeaf",node.target)){
            $.messager.alert('提示','新增內容必須選擇一個內容分類!');
            return ;
        }
        TT.createWindow({
            url : "/content-add"
        }); 
    }
},{
    text:'編輯',
    iconCls:'icon-edit',
    handler:function(){
        var ids = TT.getSelectionsIds("#contentList");
        if(ids.length == 0){
            $.messager.alert('提示','必須選擇一個內容才能編輯!');
            return ;
        }
        if(ids.indexOf(',') > 0){
            $.messager.alert('提示','只能選擇一個內容!');
            return ;
        }
        TT.createWindow({
            url : "/content-edit",
            onLoad : function(){
                var data = $("#contentList").datagrid("getSelections")[0];
                $("#contentEditForm").form("load",data);

                // 實現圖片
                if(data.pic){
                    $("#contentEditForm [name=pic]").after("<a href='"+data.pic+"' target='_blank'><img src='"+data.pic+"' width='80' height='50'/></a>"); 
                }
                if(data.pic2){
                    $("#contentEditForm [name=pic2]").after("<a href='"+data.pic2+"' target='_blank'><img src='"+data.pic2+"' width='80' height='50'/></a>");                  
                }

                contentEditEditor.html(data.content);
            }
        });     
    }
},{
    text:'刪除',
    iconCls:'icon-cancel',
    handler:function(){
        var ids = TT.getSelectionsIds("#contentList");
        if(ids.length == 0){
            $.messager.alert('提示','未選中商品!');
            return ;
        }
        $.messager.confirm('確認','確定刪除ID為 '+ids+' 的內容嗎?',function(r){
            if (r){
                var params = {"ids":ids};
                $.post("/content/delete",params, function(data){
                    if(data.status == 200){
                        $.messager.alert('提示','刪除內容成功!',undefined,function(){
                            $("#contentList").datagrid("reload");
                        });
                    }
                });
            }
        });
    }
}];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

我對新增操作作如下講解:

  • text指定我們看到的圖示後面的文字。
  • iconCls指定新增圖示。
  • handler:function()是當我們點選”新增”按鈕時觸發的函式。
  • var node = $("#contentCategoryTree").tree("getSelected");的意思是得到使用者選中的內容分類節點。
  • if(!node || !$("#contentCategoryTree").tree("isLeaf",node.target)){的意思是如果選中的不是節點或者該節點不是葉子節點,那麼這時就彈出一個”新增內容必須選擇一個內容分類!”的提示框。如果點選的是葉子節點的話,會呼叫common.js檔案當中定義的TT的createWindow方法初始化一個彈出框,彈出框中顯示的頁面是由引數url: “/content-add”指定的,也就是content-add.jsp頁面。

下面我們便來看下content-add.jsp頁面,表格中的欄位名稱與我們的資料庫中表的欄位是一致的,這樣我們便可以直接使用逆向工程生成的程式碼了。
這裡寫圖片描述
當以上頁面載入完之後,會觸發$(function(){...}方法,下面我來詳細分析一下該方法中的程式碼。

  • contentAddEditor = TT.createEditor("#contentAddForm [name=content]");的意思是初始化一個富文字編輯器。
  • TT.initOnePicUpload();的意思是初始化單張圖片上傳按鈕,也就是說一次只能選擇一張圖片(因為我們的pic和pic2欄位各自對應一張圖片路徑)。
  • $("#contentAddForm [name=categoryId]").val($("#contentCategoryTree").tree("getSelected").id);這行程式碼的意思是把使用者選擇的內容分類節點的id賦值給隱藏域<input type="hidden" name="categoryId"/>,這樣我們在提交表單的時候便把內容分類id也一併提交了。

當我們點選提交超連結提交表單的時候,就會觸發submitForm : function ()方法,下面我也來詳細分析一下該方法中的程式碼。

  • if(!$('#contentAddForm').form('validate')){的意思是如果表單輸入不合法,那麼會提示”表單還未填寫完!”。
  • contentAddEditor.sync();的意思是如果表單填寫合法,那麼富文字編輯器將與表單中的隱藏域欄位(<textarea>欄位)進行內容同步。
  • $.post("/content/save")的意思是發起url為/content/save的請求。
  • $("#contentAddForm").serialize()將表單中的資料序列化為key-value形式的字串。
  • function(data){...}指回調函式,if(data.status == 200){的意思是如果返回的狀態為200的話說明內容新增成功了,$("#contentList").datagrid("reload");意思是內容新增成功後,內容列表要進行重新載入。TT.closeCurrentWindow();的意思是關閉彈出視窗。

當我們點選重置超連結重置表單時,就會觸發clearForm : function()方法。$('#contentAddForm').form('reset');的意思是將剛才表單中輸入的內容清空。
分析了以上js程式碼,下面我們來實現新增內容這個功能。首先我們來編寫Service層的程式碼。在taotao-content-interface工程下的com.taotao.content.service包中新建一個介面——ContentService.java,並在介面中新增一個insertContent方法,如下圖所示。
這裡寫圖片描述
接著我們來實現上面的介面,我們在taotao-content-service工程的com.taotao.content.service.impl包下新建一個ContentServiceImpl實現類,該類實現ContentService介面,如下圖所示。
這裡寫圖片描述
為方便大家複製,將該實現類程式碼貼出,如下:

/**
 * 內容管理Service
 * <p>Title: ContentServiceImpl</p>
 * <p>Description: </p>
 * <p>Company: www.itcast.cn</p> 
 * @version 1.0
 */
Service
public class ContentServiceImpl implements ContentService {

    @Autowired
    private TbContentMapper contentMapper;

    @Override
    public TaotaoResult insertContent(TbContent content) {
        // 補全pojo的屬性
        content.setCreated(new Date());
        content.setUpdated(new Date());
        // 向內容表中插入資料
        contentMapper.insert(content);
        return TaotaoResult.ok();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

下面我們釋出一下該服務的這個介面,我們在taotao-content-service工程的spring目錄下的applicationContext-service.xml配置檔案中新增如下配置:

<dubbo:service interface="com.taotao.content.service.ContentService" ref="contentServiceImpl" timeout="300000" />
  • 1

這裡寫圖片描述
然後我們再來編寫表現層的程式碼。首先我們需要在taotao-manager-web工程的springmvc.xml配置檔案中新增對ContentService的引用,即要向springmvc.xml配置檔案中新增如下配置:

<dubbo:reference interface="com.taotao.content.service.ContentService" id="contentService" />
  • 1

這裡寫圖片描述
接著我們需要在taotao-manager-web工程中新增ContentController類來實現新增內容這個功能。其中@RequestMapping("/content/save")註解中的url是從content-add.jsp頁面當中貼上過來的。
這裡寫圖片描述
在啟動測試之前,我們需要先打包taotao-content到本地maven倉庫。由於新增內容這個功能涉及到了taotao-manager和taotao-content這兩個服務和taotao-manager-web,所以我們依次啟動taotao-manager和taotao-content,然後是taotao-manager-web,啟動成功之後,然後去新增一個內容,新增介面如下圖所示。
這裡寫圖片描述
點選”提交”之後,我們可以發現tb_content表中便有了我們剛才新增的內容,如下圖所示。
這裡寫圖片描述

編輯內容

由於時間緊張,在此並不實現該功能,留待以後開發。未完,待續。。。敬請期待。

刪除內容

由於時間緊張,在此並不實現該功能,留待以後開發。未完,待續。。。敬請期待。