關於博客中使用的Guns版本問題請先閱讀 Guns二次開發目錄
緊接上一篇博客 Guns二次開發(七):商品分類管理之【查】字訣(2)
6、查詢功能的實現代碼
接下來附上本篇所講的查詢功能的所有前端和後端實現代碼,不包含測試的sql數據,因爲前面已經粘貼過了。文件的目錄結果是:
(1)PageInfo.java
package cn.stylefeng.guns.elephish.bean;
import lombok.Data;
/**
* 自定義分頁的一些屬性
* Created by hqq on 2020/4/16.
*/
@Data
public class PageInfo {
private Integer currentPage=1;//要查詢第幾頁,默認是1,防止空指針
private Integer totalPage=1;//總頁數
private Integer totalCount=1;//總記錄數
private Integer limit=1;//每頁查詢的條數,默認每頁查詢1條,防止空指針
private Integer size=0;//本頁查詢到的實際條數
}
(2)QueryParam.java
package cn.stylefeng.guns.elephish.bean;
import lombok.Data;
/**
* 封裝條件查詢的參數
* Created by hqq on 2020/4/18.
*/
@Data
public class QueryParam {
private String name;//按名稱查詢
private Integer depth;//按照層級查詢
private int status;//按照狀態查詢,大於0時才表示選擇了該條件
private boolean searchChild=false;//是否查詢子類,默認不查詢,節省開銷
}
(3)CategoryController.java
package cn.stylefeng.guns.elephish.controller;
import cn.stylefeng.guns.core.common.constant.factory.PageFactory;
import cn.stylefeng.guns.elephish.bean.PageInfo;
import cn.stylefeng.guns.elephish.bean.QueryParam;
import cn.stylefeng.guns.elephish.wrapper.CategoryWrapper;
import cn.stylefeng.roses.core.base.controller.BaseController;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.plugins.Page;
import org.beetl.core.misc.BeetlUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.beans.factory.annotation.Autowired;
import cn.stylefeng.guns.core.log.LogObjectHolder;
import org.springframework.web.bind.annotation.RequestParam;
import cn.stylefeng.guns.elephish.model.Category;
import cn.stylefeng.guns.elephish.service.ICategoryService;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 分類管理控制器
*
* @author fengshuonan
* @Date 2020-04-13 11:02:46
*/
@Controller
@RequestMapping("/category")
public class CategoryController extends BaseController {
private Logger logger = LoggerFactory.getLogger(getClass());
private String PREFIX = "/elephish/category/";
@Autowired
private ICategoryService categoryService;
/**
* 跳轉到添加分類管理
*/
@RequestMapping("/category_add")
public String categoryAdd() {
return PREFIX + "category_add.html";
}
/**
* 跳轉到修改分類管理
*/
@RequestMapping("/category_update/{categoryId}")
public String categoryUpdate(@PathVariable Integer categoryId, Model model) {
Category category = categoryService.selectById(categoryId);
model.addAttribute("item",category);
LogObjectHolder.me().set(category);
return PREFIX + "category_edit.html";
}
/**
* 跳轉到分類管理首頁
*/
@RequestMapping("")
public String index() {
return PREFIX + "category.html";
}
/**
* 獲取分類管理列表
*/
@RequestMapping(value = "/list")
@ResponseBody
public Object list(QueryParam queryParam,PageInfo pageInfo) {
List<Map<String, Object>> list = categoryService.listCategory(queryParam,pageInfo);
//因爲是自定義分頁,所以返回的數據格式需要做特殊封裝,主要是兩個屬性名的定義要固定
JSONObject jo=new JSONObject();//也可以使用 Map<String,Object>
//屬性名必須是【data】,對應的值是List<Map<String, Object>>格式
jo.put("data",new CategoryWrapper(list).wrap());
jo.put("pageInfo",pageInfo);//屬性名必須是 pageInfo,
return jo;
}
/**
* 新增分類管理
*/
@RequestMapping(value = "/add")
@ResponseBody
public Object add(Category category) {
categoryService.insert(category);
return SUCCESS_TIP;
}
/**
* 刪除分類管理
*/
@RequestMapping(value = "/delete")
@ResponseBody
public Object delete(@RequestParam Integer categoryId) {
categoryService.deleteById(categoryId);
return SUCCESS_TIP;
}
/**
* 修改分類管理
*/
@RequestMapping(value = "/update")
@ResponseBody
public Object update(Category category) {
categoryService.updateById(category);
return SUCCESS_TIP;
}
/**
* 分類管理詳情
*/
@RequestMapping(value = "/detail/{categoryId}")
@ResponseBody
public Object detail(@PathVariable("categoryId") Integer categoryId) {
return categoryService.selectById(categoryId);
}
}
(4)CategoryServiceImpl.java
package cn.stylefeng.guns.elephish.service.impl;
import cn.stylefeng.guns.elephish.bean.PageInfo;
import cn.stylefeng.guns.elephish.bean.QueryParam;
import cn.stylefeng.guns.elephish.model.Category;
import cn.stylefeng.guns.elephish.dao.CategoryMapper;
import cn.stylefeng.guns.elephish.service.ICategoryService;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* <p>
* 服務實現類
* </p>
*
* @author hqq
* @since 2020-04-13
*/
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements ICategoryService {
@Autowired
private CategoryMapper categoryMapper;
@Override
public List<Map<String, Object>> listCategory(QueryParam queryParam, PageInfo pageInfo) {
//設置排序
String sortField = "sort";//排序字段
boolean isAsc = true;//是否正序排序
//構建查詢條件
Wrapper<Category> wrapper = buildWrapper(queryParam, sortField,isAsc);
Page<Map<String,Object>> page=new Page<>(pageInfo.getCurrentPage(),pageInfo.getLimit());
List<Map<String, Object>> maps = categoryMapper.selectMapsPage(page, wrapper);
//設置總頁數
int total = (int) page.getTotal();
pageInfo.setTotalPage((int)Math.ceil(1.0*total/pageInfo.getLimit()));//總頁數
pageInfo.setTotalCount(total);//總記錄數
if(maps.isEmpty()){
return maps;
}
//設置查詢到的本頁記錄數,因爲默認值爲0,所以大於0的時候才需要設置
pageInfo.setSize(maps.size());
//如果不查詢子類菜單,直接返回
if(!queryParam.isSearchChild()){
return maps;
}
//遍歷查詢其子類
List<Map<String, Object>> list = new ArrayList<>();
for(int i = 0; i<maps.size();i++){
findChildCategory(list, maps.get(i),sortField,isAsc,queryParam.getStatus());
}
return list;
}
/**
* 封裝 category 的查詢條件,
* 注意:這些查詢條件是針對頂級菜單的,
* 子級菜單的查詢條件只有一個parent_id和排序方式
* @param queryParam
* @return
*/
private Wrapper<Category> buildWrapper(QueryParam queryParam,String sortField,boolean isAsc){
int status = queryParam.getStatus();
Wrapper<Category> wrapper = new EntityWrapper<>();
//設置排序字段和排序方式
wrapper.orderBy(sortField,isAsc);
//是否按照層級查詢
Integer depth =queryParam.getDepth();
if(depth != null){
wrapper.eq("depth", depth);
}
//是否按照分類名稱查詢
if(StringUtils.isNotBlank(queryParam.getName())){
wrapper.like("name",queryParam.getName());
}else{
//只有不按分類名稱查詢,並且沒有指定深度,才設置默認的parentId爲0
if(depth == null){
wrapper.eq("parent_id", 0);
}
}
//是否按照狀態查詢
if(status> 0){
if(!(status==PRODUCT_CATEGORY_STATUS_START || status==PRODUCT_CATEGORY_STATUS_STOP)){
//ILLEGAL_STATUS_VALUE(400,"狀態字段的值異常"),
throw new ServiceException(BizExceptionEnum.ILLEGAL_STATUS_VALUE);
}
wrapper.eq("status",queryParam.getStatus());
}else{
//否則,只查詢未刪除的記錄
wrapper.in("status",new Integer[]{PRODUCT_CATEGORY_STATUS_START,PRODUCT_CATEGORY_STATUS_STOP});
}
return wrapper;
}
/**
* 遞歸算法,算出子級菜單
*/
private List<Map<String, Object>> findChildCategory(List<Map<String, Object>> result,
Map<String, Object> category,String sortField, boolean isAsc, int status){
result.add(category);
//封裝子級菜單的查詢條件,
// 子級菜單的查詢條件只有一個parent_id和排序方式
Wrapper<Category> wrapper = new EntityWrapper<>();
wrapper.orderBy(sortField,isAsc)
.eq("parent_id", new Integer(category.get("id").toString()));
if(status>0){
wrapper.eq("status",status);
}else{
//否則,只查詢未刪除的記錄
wrapper.in("status",new Integer[]{PRODUCT_CATEGORY_STATUS_START,PRODUCT_CATEGORY_STATUS_STOP});
}
//查找子節點,遞歸算法一定要有一個退出的條件
List<Map<String, Object>> childList = categoryMapper.selectMaps(wrapper);
for (Map<String, Object> temp : childList) {
findChildCategory(result,temp,sortField,isAsc, status);
}
return result;
}
}
(5)CategoryWrapper.java
package cn.stylefeng.guns.elephish.wrapper;
import cn.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import cn.stylefeng.guns.elephish.constants.WrapperDictNameConstant;
import cn.stylefeng.roses.core.base.warpper.BaseControllerWrapper;
import java.util.List;
import java.util.Map;
/**
* 商品分類管理的包裝類
*
* Created by hqq on 2020/4/15.
*/
public class CategoryWrapper extends BaseControllerWrapper {
public CategoryWrapper(List<Map<String, Object>> multi) {
super(multi);
}
/**
* 此處自定義添加需要包裝的字段的字典信息
*/
@Override
protected void wrapTheMap(Map<String, Object> map) {
//狀態名稱
map.put("statusName", ConstantFactory.me().getDictById(
WrapperDictNameConstant.MALL_CATEGORY_STATUS_ID, map.get("status").toString()));
}
}
(6)bootstrap-treetable.js
/**
* 查找當前這個節點的所有節點(包含子節點),並進行摺疊或者展開操作
*
* @param item 被點擊條目的子一級條目
* @param target 整個bootstrap tree table實例
* @param globalCollapsedFlag 如果爲true,則表示當前操作是收縮(摺疊),如果是false,表示當前操作是展開
* @param options 存放了一些常量,例如展開和收縮的class
*/
function extracted($, item, target, globalCollapsedFlag, options) {
var itemCodeName = $(item).find("td[name='"+options.code+"']").text();
// var itemCodeName = $(item).find("td[name='code']").text();
var subItems = target.find("tbody").find(".tg-" + itemCodeName);//下一級,改爲下所有級別
if (subItems.size() > 0) {
$.each(subItems, function (nIndex, nItem) {
extracted($, nItem, target, globalCollapsedFlag, options);
});
}
$.each(subItems, function (pIndex, pItem) {
//如果是展開,判斷當前箭頭是開啓還是關閉
var expander = $(item).find("td[name='name']").find(".treetable-expander");
if (!globalCollapsedFlag) {
var hasExpander = expander.hasClass(options.expanderExpandedClass);
if (hasExpander) {
$(pItem).css("display", "table");
} else {
$(pItem).css("display", "none");
}
} else {
//如果是摺疊,就把當前開着的都摺疊掉
$(pItem).css("display", "none");
expander.removeClass(options.expanderExpandedClass);
expander.addClass(options.expanderCollapsedClass);
}
});
}
(function ($) {
"use strict";
$.fn.bootstrapTreeTable = function (options, param) {
var allData = null;//用於存放格式化後的數據
// 如果是調用方法
if (typeof options == 'string') {
return $.fn.bootstrapTreeTable.methods[options](this, param);
}
// 如果是初始化組件
options = $.extend({}, $.fn.bootstrapTreeTable.defaults, options || {});
// 是否有radio或checkbox
var hasSelectItem = false;
var target = $(this);
// 在外層包裝一下div,樣式用的bootstrap-table的
var _main_div = $("<div class='bootstrap-tree-table fixed-table-container'></div>");
target.before(_main_div);
_main_div.append(target);
target.addClass("table table-hover treetable-table table-bordered");
if (options.striped) {
target.addClass('table-striped');
}
// 工具條在外層包裝一下div,樣式用的bootstrap-table的
if (options.toolbar) {
var _tool_div = $("<div class='fixed-table-toolbar'></div>");
var _tool_left_div = $("<div class='bs-bars pull-left'></div>");
_tool_left_div.append($(options.toolbar));
_tool_div.append(_tool_left_div);
_main_div.before(_tool_div);
}
// 格式化數據,優化性能
target.formatData = function (data) {
var _root = options.rootCodeValue ? options.rootCodeValue : null
$.each(data, function (index, item) {
// 添加一個默認屬性,用來判斷當前節點有沒有被顯示
item.isShow = false;
// 這裏兼容幾種常見Root節點寫法
// 默認的幾種判斷
var _defaultRootFlag = item[options.parentCode] == '0'
|| item[options.parentCode] == 0
|| item[options.parentCode] == null
|| item[options.parentCode] == '';
if (!item[options.parentCode] || (_root ? (item[options.parentCode] == options.rootCodeValue) : _defaultRootFlag)) {
if (!allData["_root_"]) {
allData["_root_"] = [];
}
allData["_root_"].push(item);
} else {
if (!allData["_n_" + item[options.parentCode]]) {
allData["_n_" + item[options.parentCode]] = [];
}
allData["_n_" + item[options.parentCode]].push(item);
}
});
}
// 得到根節點
target.getRootNodes = function () {
return allData["_root_"];
};
// 遞歸獲取子節點並且設置子節點
target.handleNode = function (parentNode, lv, tbody) {
var _ls = allData["_n_" + parentNode[options.code]];
var tr = target.renderRow(parentNode, _ls ? true : false, lv);
tbody.append(tr);
if (_ls) {
$.each(_ls, function (i, item) {
target.handleNode(item, (lv + 1), tbody)
});
}
};
// 繪製行
target.renderRow = function (item, isP, lv) {
// 標記已顯示
item.isShow = true;
var tr = $('<tr class="tg-' + item[options.parentCode] + '"></tr>');
var _icon = options.expanderCollapsedClass;
if (options.expandAll) {
tr.css("display", "table");
_icon = options.expanderExpandedClass;
} else if (options.expandFirst && lv <= 2) {
tr.css("display", "table");
_icon = (lv == 1) ? options.expanderExpandedClass : options.expanderCollapsedClass;
} else {
tr.css("display", "none");
_icon = options.expanderCollapsedClass;
}
$.each(options.columns, function (index, column) {
// 判斷有沒有選擇列
if (index == 0 && column.field == 'selectItem') {
hasSelectItem = true;
var td = $('<td style="text-align:center;width:36px"></td>');
if (column.radio) {
var _ipt = $('<input name="select_item" type="radio" value="' + item[options.id] + '"></input>');
td.append(_ipt);
}
if (column.checkbox) {
var _ipt = $('<input name="select_item" type="checkbox" value="' + item[options.id] + '"></input>');
td.append(_ipt);
}
tr.append(td);
} else {
var td = $('<td title="' + item[column.field] + '" name="' + column.field + '" style="' + ((column.width) ? ('width:' + column.width) : '') + '"></td>');
// 增加formatter渲染
if (column.formatter) {
td.html(column.formatter.call(this, item[column.field], item, index));
} else {
td.text(item[column.field]);
}
if (options.expandColumn == index) {
if (!isP) {
td.prepend('<span class="treetable-expander"></span>')
} else {
td.prepend('<span class="treetable-expander ' + _icon + '"></span>')
}
for (var int = 0; int < (lv - 1); int++) {
td.prepend('<span class="treetable-indent"></span>')
}
}
tr.append(td);
}
});
return tr;
}
// 加載數據
target.load = function (parms) {
// 加載數據前先清空
allData = {};
// 加載數據前先清空
target.html("");
// 構造表頭
var thr = $('<tr></tr>');
$.each(options.columns, function (i, item) {
var th = null;
// 判斷有沒有選擇列
if (i == 0 && item.field == 'selectItem') {
hasSelectItem = true;
th = $('<th style="width:36px"></th>');
} else {
th = $('<th style="' + ((item.width) ? ('width:' + item.width) : '') + '"></th>');
}
th.text(item.title);
thr.append(th);
});
var thead = $('<thead class="treetable-thead"></thead>');
thead.append(thr);
target.append(thead);
// 構造表體
var tbody = $('<tbody class="treetable-tbody"></tbody>');
target.append(tbody);
// 添加加載loading
var _loading = '<tr><td colspan="' + options.columns.length + '"><div style="display: block;text-align: center;">正在努力地加載數據中,請稍候……</div></td></tr>'
tbody.html(_loading);
// 默認高度
if (options.height) {
tbody.css("height", options.height);
}
$.ajax({
type: options.type,
url: options.url,
data: parms ? parms : options.ajaxParams,
dataType: "JSON",
success: function (result, textStatus, jqXHR) {
//### 開始修改guns原來的bootstrap-treetable.js ###
var data =result ;
//判斷是否是標準的列表查詢,這個很重要,
// 因爲我是直接在bootstrap-treetable.js修改的,
//新作的修改必須保證原來的功能不受影響。
if(result && typeof(result.pageInfo)!='undefined'){
data = result.data;
PageTool.buildPageDiv(result.pageInfo);
}
//### 結束脩改gun v5.1-final 原來的bootstrap-treetable.js ###
// 加載完數據先清空
tbody.html("");
if (!data || data.length <= 0) {
var _empty = '<tr><td colspan="' + options.columns.length + '"><div style="display: block;text-align: center;">沒有找到匹配的記錄</div></td></tr>'
tbody.html(_empty);
return;
}
target.formatData(data);
// 開始繪製
var rootNode = target.getRootNodes();
if (rootNode) {
$.each(rootNode, function (i, item) {
target.handleNode(item, 1, tbody);
});
}
// 下邊的操作主要是爲了查詢時讓一些沒有根節點的節點顯示
$.each(data, function (i, item) {
if (!item.isShow) {
var tr = target.renderRow(item, false, 1);
tbody.append(tr);
}
});
target.append(tbody);
//動態設置表頭寬度
thead.css("width", tbody.children(":first").css("width"));
// 行點擊選中事件
target.find("tbody").find("tr").click(function () {
if (hasSelectItem) {
var _ipt = $(this).find("input[name='select_item']");
if (_ipt.attr("type") == "radio") {
_ipt.prop('checked', true);
target.find("tbody").find("tr").removeClass("treetable-selected");
$(this).addClass("treetable-selected");
} else {
if (_ipt.prop('checked')) {
_ipt.prop('checked', false);
$(this).removeClass("treetable-selected");
} else {
_ipt.prop('checked', true);
$(this).addClass("treetable-selected");
}
}
}
});
// 小圖標點擊事件--展開縮起
target.find("tbody").find("tr").find(".treetable-expander").click(function () {
var tr = $(this).parent().parent();
var _code = tr.find("input[name='select_item']").val();
if (options.id == options.code) {
_code = tr.find("input[name='select_item']").val();
} else {
_code = tr.find("td[name='" + options.code + "']").text();
}
var _ls = target.find("tbody").find(".tg-" + _code);//下一級,改爲下所有級別
if (_ls && _ls.length > 0) {
var _flag = $(this).hasClass(options.expanderExpandedClass);
$.each(_ls, function (index, item) {
//查找當前這個節點的所有節點(包含子節點),如果是摺疊都顯示爲不顯示,如果是展開,則根據當前節點的狀態
extracted($, item, target, _flag, options);
$(item).css("display", _flag ? "none" : "table");
});
if (_flag) {
$(this).removeClass(options.expanderExpandedClass)
$(this).addClass(options.expanderCollapsedClass)
} else {
$(this).removeClass(options.expanderCollapsedClass)
$(this).addClass(options.expanderExpandedClass)
}
}
});
},
error: function (xhr, textStatus) {
var _errorMsg = '<tr><td colspan="' + options.columns.length + '"><div style="display: block;text-align: center;">' + xhr.responseText + '</div></td></tr>'
tbody.html(_errorMsg);
debugger;
},
});
}
if (options.url) {
target.load();
} else {
// 也可以通過defaults裏面的data屬性通過傳遞一個數據集合進來對組件進行初始化....有興趣可以自己實現,思路和上述類似
}
return target;
};
// 組件方法封裝........
$.fn.bootstrapTreeTable.methods = {
// 返回選中記錄的id(返回的id由配置中的id屬性指定)
// 爲了兼容bootstrap-table的寫法,統一返回數組,這裏只返回了指定的id
getSelections: function (target, data) {
// 所有被選中的記錄input
var _ipt = target.find("tbody").find("tr").find("input[name='select_item']:checked");
var chk_value = [];
// 如果是radio
if (_ipt.attr("type") == "radio") {
var _data = {id: _ipt.val()};
var _tds = _ipt.parent().parent().find("td");
_tds.each(function (_i, _item) {
if (_i != 0) {
_data[$(_item).attr("name")] = $(_item).text();
}
});
chk_value.push(_data);
} else {
_ipt.each(function (_i, _item) {
var _data = {id: $(_item).val()};
var _tds = $(_item).parent().parent().find("td");
_tds.each(function (_ii, _iitem) {
if (_ii != 0) {
_data[$(_iitem).attr("name")] = $(_iitem).text();
}
});
chk_value.push(_data);
});
}
return chk_value;
},
// 刷新記錄
refresh: function (target, parms) {
if (parms) {
target.load(parms);
} else {
target.load();
}
},
// 組件的其他方法也可以進行類似封裝........
};
$.fn.bootstrapTreeTable.defaults = {
id: 'id',// 選取記錄返回的值
code: 'id',// 用於設置父子關係
parentCode: 'parentId',// 用於設置父子關係
rootCodeValue: null,//設置根節點code值----可指定根節點,默認爲null,"",0,"0"
data: [], // 構造table的數據集合
type: "GET", // 請求數據的ajax類型
url: null, // 請求數據的ajax的url
ajaxParams: {}, // 請求數據的ajax的data屬性
expandColumn: null,// 在哪一列上面顯示展開按鈕
expandAll: true, // 是否全部展開
expandFirst: false, // 是否默認第一級展開--expandAll爲false時生效
striped: false, // 是否各行漸變色
columns: [],
toolbar: null,//頂部工具條
height: 0,
expanderExpandedClass: 'glyphicon glyphicon-chevron-down',// 展開的按鈕的圖標
expanderCollapsedClass: 'glyphicon glyphicon-chevron-right'// 縮起的按鈕的圖標
};
})(jQuery);
(7)category.js
/**
* 分類管理管理初始化
*/
var Category = {
id: "CategoryTable", //表格id
seItem: null, //選中的條目
table: null,
layerIndex: -1
};
/**
* 初始化表格的列
*/
Category.initColumn = function () {
return [
{field: 'selectItem', radio: true},
{title: '分類名稱', field: 'name', visible: true, align: 'center', valign: 'middle'},
{title: '分類編號', field: 'id', visible: true, align: 'center', valign: 'middle'},
{title: '分類父編號', field: 'parentId', visible: true, align: 'center', valign: 'middle'},
// {title: '當前類別的所有父類別id,包含多層級別的父類別id,方便查找', field: 'parentIds', visible: true, align: 'center', valign: 'middle'},
{title: '層級', field: 'depth', align: 'center', valign: 'middle', sortable: true},
{title: '排序', field: 'sort', visible: true, align: 'center', valign: 'middle'},
{title: '狀態', field: 'statusName', visible: true, align: 'center', valign: 'middle'},
{title: '創建時間', field: 'createTime', visible: true, align: 'center', valign: 'middle',
formatter: function (value, row, index) {
return typeof(value)=="undefined"?"":moment(+value).format('YYYY-MM-DD HH:mm:ss');
}
},
{title: '更新時間', field: 'updateTime', visible: true, align: 'center', valign: 'middle',
formatter: function (value, row, index) {
return typeof(value)=="undefined"?"":moment(+value).format('YYYY-MM-DD HH:mm:ss');
}
}
];
};
/**
* 檢查是否選中
*/
Category.check = function () {
var selected = $('#' + this.id).bootstrapTable('getSelections');
if(selected.length == 0){
Feng.info("請先選中表格中的某一記錄!");
return false;
}else{
Category.seItem = selected[0];
return true;
}
};
/**
* 點擊添加分類管理
*/
Category.openAddCategory = function () {
var index = layer.open({
type: 2,
title: '添加分類管理',
area: ['800px', '420px'], //寬高
fix: false, //不固定
maxmin: true,
content: Feng.ctxPath + '/category/category_add'
});
this.layerIndex = index;
};
/**
* 打開查看分類管理詳情
*/
Category.openCategoryDetail = function () {
if (this.check()) {
var index = layer.open({
type: 2,
title: '分類管理詳情',
area: ['800px', '420px'], //寬高
fix: false, //不固定
maxmin: true,
content: Feng.ctxPath + '/category/category_update/' + Category.seItem.id
});
this.layerIndex = index;
}
};
/**
* 刪除分類管理
*/
Category.delete = function () {
if (this.check()) {
var ajax = new $ax(Feng.ctxPath + "/category/delete", function (data) {
Feng.success("刪除成功!");
Category.table.refresh();
}, function (data) {
Feng.error("刪除失敗!" + data.responseJSON.message + "!");
});
ajax.set("categoryId",this.seItem.id);
ajax.start();
}
};
/**
* 查詢分類管理列表
*/
Category.search = function () {
Category.table.refresh({query: Category.formParams()});
};
/**
rootCodeValue: null,//設置根節點code值----可指定根節點,默認爲null,"",0,"0"
id : "id", // 選取記錄返回的值
code : "id", // 用於設置父子關係
parentCode : "parentId", // 用於設置父子關係
type: 'get', // 請求方式(*)
url: "./data.json", // 請求後臺的URL(*)
ajaxParams : {}, // 請求數據的ajax的data屬性
expandColumn : 0, // 在哪一列上面顯示展開按鈕
expandAll : false, // 是否全部展開
expandFirst : true, // 是否默認第一級展開--expandAll爲false時生效
toolbar: null,//頂部工具條
height: 0,
expanderExpandedClass : 'glyphicon glyphicon-chevron-down',// 展開的按鈕的圖標
expanderCollapsedClass : 'glyphicon glyphicon-chevron-right',// 縮起的按鈕的圖標
**/
$(function () {
var defaultColunms = Category.initColumn();
var table = new BSTreeTable(Category.id, "/category/list", defaultColunms);
table.setExpandColumn(1);//設置第一列展示下拉列表
table.setIdField("id");//分類編號
table.setCodeField("id");//分類父編號,用於設置父子關係
table.setParentCodeField("parentId");//分類父編號,用於設置父子關係
table.setExpandAll(true);
//設置請求時的參數
var queryData = Category.formParams();
queryData['limit'] = 5;//
// alert(JSON.stringify(queryData));
table.setData(queryData);
table.init();
Category.table = table;
//設置每頁的查詢的默認條數
$("#limit").val(5);
});
/**
* 查詢表單提交參數對象
* @returns {{}}
*/
Category.formParams = function() {
var queryData = {};
queryData['name'] = $("#byName").val().trim();//名稱條件
queryData['depth'] = $("#byDepth").val();//層級條件
queryData['status'] = $("#byStatus").val();//狀態條件
queryData['searchChild'] = $("#searchChild").val();//是否查詢子菜單
queryData['limit'] = $("#limit").val();//設置每頁查詢條數
return queryData;
}
/**
* 【分類名稱】輸入框失去焦點事件
*/
$("#byName").on('blur',function(){
setSearchChildSelected();
});
/**
*【深度】輸入框失去焦點事件
*/
$("#byDepth").on('blur',function(){
setSearchChildSelected();
});
/**
* 設置【是否查詢子菜單】選擇框是否可用
*/
function setSearchChildSelected() {
var byName = $("#byName").val().trim();
var byDepth = $("#byDepth").val().trim();
if(byName && !byDepth){
//當選擇分類名稱查詢,不選擇層級查詢時,默認無法查詢子類菜單,這樣是爲了防止查重和查出不必要的數據
$("#searchChild").val("false");
$("#searchChild").attr("disabled",true);
}else{
//其它情況,都可以自主覺得是否查詢子菜單
$("#searchChild").val("true");
$("#searchChild").attr("disabled",false);
}
}
(8)moment.js
這個文件請按照上一篇博客 Guns二次開發(七):商品分類管理之【查】字訣(2) 中的方法獲取,無法引入到此處,因爲字數太多。
(9)paging.js
/**
* 本分頁功能是在bootrap-treetable.js基礎上實現的
* 使用說明:
* (1)使用之前,請先配套獲取修改後的 bootstrap-treetable.js,並替換掉guns v5.1-final
* 原來的bootstrap-treetable.js,
* guns原js修改的地方也才幾行代碼,你也可以自己修改,而不用獲取本處提供的
* (2)將本文件 paging.js 引入到你需要分頁的html頁面中
* (3)在你需要插入【分頁條】的地方(html頁面中的某處位置)引入這段div :<div id="pageDiv"></div>
* (4)接口返回的數據需時json格式的,並且必須保證用以下兩個字段封裝對應的數據:
"data" : 列表所需要的實體類數據,用list集合封裝
"pageInfo" : 分頁信息
注:
data 集合中實體類需符合原 guns v5.1-final 【菜單管理】列表查詢功能的標準;
pageInfo 需包含以下5個字段:{
currentPage : 要查詢第幾頁,默認是1,防止空指針
totalPage :總頁數,默認值0
totalCount : 總記錄數,默認值0
limit :每頁查詢的條數,默認值每頁查詢1條,防止空指針
size : 本頁實際查詢到的條數
}
*
*/
var PageTool = {
};
/**
* 自定義的分頁之構建構建div裏面的內容
*
* 記住,使用之前,必須要在你需要顯示頁碼條的位置引入這段div標籤:
* <div id="pageDiv"></div>
*/
// function buildPageDiv(pageInfo) {
PageTool.buildPageDiv = function (pageInfo) {
// alert(JSON.stringify(pageInfo));
//先清空之前的內容
$("#pageDiv").empty();
var currentPage=pageInfo.currentPage;//當前頁
var totalPage=pageInfo.totalPage;//總頁數
var totalCount=pageInfo.totalCount;//符合條件的總條數(不包含子菜單)
var size=pageInfo.size;//本頁查詢到記錄數(不包含子菜單)
var limit=pageInfo.limit;//每頁查詢的記錄數
//在strong標籤中加入一個參數,用戶頁面刷新按鈕獲取當前頁信息時使用
var pageDiv = "<br/><strong id='currentPageStrong' currentPage='"+currentPage+"' style='color:red'>" +
"注意:此處的分頁只相對同級別的父類菜單而言," +
"所有子類菜單的記錄數不在分頁之內</strong><br/><ul class='pagination'>";
<!-- 首頁,如果當前頁是第一頁,則設置首頁不可用-->
if(currentPage==1){
pageDiv +="<li><a href='javascript:void(0)' disabled='true' style='color:black;font-weight:bold;'>首頁</a></li>";
}else{
pageDiv += "<li><a href='javascript:void(0)' οnclick='PageTool.pageSkip(this)' currentPage='1'>首頁</a></li>";
}
<!-- 上一頁,先判斷是不是第一頁,第一頁,就沒有上一頁 -->
if(currentPage > 1){
pageDiv += "<li><a href='javascript:void(0)' οnclick='PageTool.pageSkip(this)'" +
" currentPage='"+(currentPage - 1)+"'>上一頁</a></li>";
}
<!-- #####展示頁碼功能 開始#####-->
<!-- 定義兩個模板變量 -->
var begin=1;
var end=5;
if(totalPage <= 5){
//當總的頁數小於等於5的情況
begin=1 ;
end=totalPage;
}else{
// 總頁碼大於5的情況
<!-- 如果當前頁碼爲 1 - 3,那麼 我們顯示前面5個頁碼,也就是1-5 -->
if(currentPage<=3){
begin=1 ;
end=5;
}else if(currentPage >= totalPage-2 ){
<!-- 如果當前頁碼爲 末尾的3個,也就是 currentPage >=totalPage - 2 ,那麼 就顯示末尾5個頁碼 -->
begin=totalPage-4 ;
end=totalPage;
}else{
<!-- 其他中間的頁碼,顯示 currentPage - 2 到 currentPage + 2 -->
begin=currentPage-2 ;
end=currentPage+2;
}
}
<!-- 遍歷頁碼 -->
for(var i=begin; i <= end; i++){
if(currentPage == i){
<!-- 如果頁碼是當前頁,則設置標籤不可用 -->
pageDiv += "<li><a href='javascript:void(0)' disabled='true' style='color:black;font-weight:bold;'>"+i+"</a></li>";
}else{
<!-- 如果頁碼不是當前頁,則加連接 -->
pageDiv += "<li><a href='javascript:void(0)' οnclick='PageTool.pageSkip(this)' currentPage='"+i+"'>"+i+"</a></li>";
}
}
<!-- #####展示頁碼功能 結束#####-->
<!-- 下一頁,先判斷是不是最後一頁,最後一頁,就沒有下一頁 -->
if(currentPage < totalPage ){
pageDiv += "<li><a href='javascript:void(0)' οnclick='PageTool.pageSkip(this)' currentPage='"+(currentPage + 1)+"'>下一頁</a></li>";
}
<!-- 最後一頁 -->
if(currentPage==totalPage) {
pageDiv += "<li><a href='javascript:void(0)' disabled='true' style='color:black;font-weight:bold;'>末頁</a></li>";
}else{
pageDiv += "<li><a href='javascript:void(0)' οnclick='PageTool.pageSkip(this)' currentPage='"+(totalPage)+"'>末頁</a></li>";
}
pageDiv +=" 當前第 "+(currentPage)+" 頁," +
"顯示第 "+((currentPage-1)*limit+1)+" 到 "+((currentPage-1)*limit+1+size)+" 條記錄" +
" 總共 "+totalPage+" 頁,總共 "+totalCount+" 記錄數," +
"可直接搜索第<input value='"+currentPage+"' id='pageNow' style='width:40px;text-align:center;'/> 頁" +
"<input type='button' class='btn btn-primary' currentPage='button' οnclick='PageTool.pageSkip(this)' value='點擊跳轉'></ul>";
$("#pageDiv").append(pageDiv);
// alert(pageDiv);
}
/**
* 點擊指定頁碼刷新數據
*/
PageTool.pageSkip =function(obj) {
var currentPage = obj.attributes["currentPage"].nodeValue;
//如果是直接指定頁碼跳轉的請求,則要從input標籤中獲取值
if(currentPage == "button"){
currentPage = $("#pageNow").val();
}
//如果最終沒有值,設置默認值爲1
if(!currentPage){
currentPage = 1;
}
//先獲取公共的參數
var queryData = Category.formParams();
//添加私有參數
queryData['currentPage'] = currentPage;//當前再第幾頁
//刷新table數據
Category.table.refresh({query: queryData});
}
(11)category.html
@layout("/common/_container.html"){
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5 id="pageInfo">分類管理</h5>
</div>
<div class="ibox-content">
<div class="row row-lg">
<div class="col-sm-12">
<div class="row">
<div class="col-sm-2">
<#NameCon id="byName" name="分類名稱" />
</div>
<div class="col-sm-2">
<#NameCon id="byDepth" name="層級" />
</div>
<div class="col-sm-2">
<#SelectCon id="byStatus" name="狀態" >
<option value="0">全部</option>
<option value="1">正常</option>
<option value="2">已廢棄</option>
</#SelectCon>
</div>
</div>
<div class="row">
<div class="col-sm-2">
<#SelectCon id="searchChild" name="是否查詢子菜單" >
<option value="true" selected="selected" >是</option>
<option value="false">否</option>
</#SelectCon>
</div>
<div class="col-sm-2">
<#NameCon id="limit" name="每頁查詢條數"/>
</div>
<div class="col-sm-3">
<#button name="搜索" icon="fa-search" clickFun="Category.search()"/>
</div>
</div>
<br/>
<div class="hidden-xs" id="CategoryTableToolbar" role="group">
@if(shiro.hasPermission("/category/add")){
<#button name="添加" icon="fa-plus" clickFun="Category.openAddCategory()"/>
@}
@if(shiro.hasPermission("/category/update")){
<#button name="修改" icon="fa-edit" clickFun="Category.openCategoryDetail()" space="true"/>
@}
@if(shiro.hasPermission("/category/delete")){
<#button name="刪除" icon="fa-remove" clickFun="Category.delete()" space="true"/>
@}
</div>
<#table id="CategoryTable"/>
</div>
</div>
<!--定義一個空的div標籤,用於分頁內容的位置-->
<br>
<div id="pageDiv"></div>
</div>
</div>
</div>
</div>
<!-- 自定義分頁引入 -->
<script src="${ctxPath}/static/modular/elephish/common/paging.js"></script>
<script src="${ctxPath}/static/modular/elephish/category/category.js?j=${date().time}"/>
@}
至此,商品分類模塊的查詢功能實現。
該系列更多文章請前往 Guns二次開發目錄