1. 程式人生 > >Easyui動態顯示列的應用例項

Easyui動態顯示列的應用例項

1、前言
專案中一個考勤資訊功能,考勤資訊的資料表結構如下:

CREATE TABLE `t_attendance` (
  `id` varchar(50) NOT NULL,
  `beautician_id` varchar(50) NOT NULL COMMENT '美容師id',
  `att_date` date DEFAULT NULL COMMENT '考勤日期',
  `att_type` tinyint(4) DEFAULT NULL COMMENT '考勤型別:1:出勤;2:出勤半天;3:請假;4:遲到;5:曠工;6:休假;',
  `late_min` int
(11) DEFAULT NULL COMMENT '遲到分鐘數', `leavebill_min` int(11) DEFAULT NULL COMMENT '請假分鐘數', `summary` text COMMENT '備註', `create_date` date DEFAULT NULL COMMENT '建立日期', `update_date` date DEFAULT NULL COMMENT '修改日期', `update_id` varchar(50) DEFAULT NULL COMMENT '修改id', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT
CHARSET=utf8 COMMENT='考勤資訊'

考勤表資料如下圖:

這裡寫圖片描述

客戶要求實現的介面樣式如下圖:

這裡寫圖片描述

說明:根據年月查詢店鋪員的考勤資訊,每個月份的天數是不一樣的,5月份31天,6月份30天,2月份根據年份的不同,天數也不一樣。所以上圖的datagrid列表中的列是動態變化的。

A、該功能需求用的技術、知識點
1、MySql行轉列、group_concat(此處可參考本人之前blog MySql行轉列、group_concat使用)
2、js中動態建立datagrid列
3、EasyUi日期控制元件datebox設定,只顯示年月,也只能選擇年月。該問題檢視本人的blog

EasyUi日期控制元件datebox設定,只顯示年月,也只能選擇年月
4、EasyUi點選單元格檢視、編輯員工某一天的考勤資訊

2、程式碼實現
1、圖中datagrid的列分兩種,員工姓名是frozenColumns,
列,其他動態列是columns。

att.jsp頁面程式碼片段

//獲取年月日期框的年月值
var attYearMonthStr = $("#attYearMonth").datebox("getValue");

//${headerString}是獲取跳轉到att.jsp頁面時後臺丟取的列集合資料字串
//${headerString}字串的內容為'2017-06-01,2017-06-02 ...省略 2017-06-30'
var headerString = '${headerString}';

//將字串轉換為datagrid的column的data,然後在頁面中可以直接用colObjArr
var colObjArr = covertHeader(headerString);

//建立考勤datagrid
var attDataGrid = $('#attDataGrid').datagrid({
    url : '${pageContext.request.contextPath}/shop/att/queryAtts.do?attYearMonth=' +attYearMonthStr ,
    fit : true,
    fitColumns : false,
    border : false,
    idField : 'id',
    remoteSort: false,
    singleSelect:true,
    checkOnSelect : true,
    selectOnCheck : true,
    nowrap : true,
    showPageList:false,
    frozenColumns : [ [ {
        field : 'id',
        title : '編號',
        width : 120,
        hidden : true
    },{
        field : 'name',
        title : '員工姓名',
        width : 120,
        align:'center'
    }
    ]],
    //使用後臺丟取的資料動態載入動態列
    columns:[colObjArr],
    //下面的是測試資料,(也可以理解為示例資料)
    /* columns:[ [ {
        field : '2017-06-01',
        title : '2017-06-01',
        width : 100,
        align:'center',
        formatter: function (value, rowData, rowIndex) {
            if(value == null){
                return "";
            }else if(value == '出勤'){
                return value;
            }else{
                return  '<font color="red">'+value+'</font>';
            }
         }
    },{
        field : '2017-06-02',
        title : '2017-06-02',
        width : 100,
        align:'center',
        formatter: function (value, rowData, rowIndex) {
         if(value == null){
            return "";
         }else if(value == '出勤'){
            return value;
         }else{
            return  '<font color="red">'+value+'</font>';
        }
     }
  }]], */
   toolbar : '#attToolbar',
   onLoadSuccess : function() {                             
      $(this).datagrid('clearChecked');
      $(this).datagrid('clearSelections');
   },
   onSelect : function(rowIndex, rowData){

   },
   onClickRow: function (rowIndex, rowData) {
      $(this).datagrid('unselectRow', rowIndex);
   },
   //單擊單元格
  onClickCell:function(rowIndex, field, value){
        //根據rowIndex獲取datagrid的行
        var row = $('#attDataGrid').datagrid('getData').rows[rowIndex];
        //通過row獲取員工id
        var beauticianId = row.id;
        //獲取列頭,實際上就是員的考勤日期
        var attDate = field; 
        //彈出考勤設定頁面
        showAtt(beauticianId,attDate);
       }
    }
});
 covertHeader轉換函式:
 根據列資料動態生成datagrid的列data。
//動態新增列,將字串轉換為datagrid的column的data
 function covertHeader(headerString){
        //datagrid的columns集合
        var colObjArr = new Array();
        if(headerString){
            var headArr = headerString.split(',');
            for(var i = 0;i < headArr.length; i++) {
                var fieldName = headArr[i];
                //建立一個column列物件
                var colObj = new Object();
                //設定field屬性
                colObj['field'] = fieldName;
                //設定title屬性
                colObj['title'] = fieldName;
                colObj['width'] = '120';
                colObj['align'] = 'center';
                colObj['formatter'] = function(value,rowData,rowIndex){
                    if(value == null){
                        return "";
                    }else if(value == '出勤'){
                        return value;
                    }else{
                        return  '<font color="red">'+value+'</font>';
                    }
                };
                //將建立的column列物件新增到columns集合
                colObjArr.push(colObj); 
            }
        }

        return colObjArr;
    }

controller跳轉到att.jsp頁面的程式碼

/**
  * 跳轉考勤資訊頁面
  * @return
  */
  @RequestMapping("/goToAttJsp")
  public String goToAttJsp(HttpServletRequest request){
     try {
        //獲取當前月的第一天
        Date beginDate = DateUtil.getCurrentMonthFirstDay();
        //獲取當前月的天數
        int days = DateUtil.getCurrentMonthDaysCount();
        //當前月的日期集合
        String[] dateArr = new String[days];
        for (int i = 0; i < dateArr.length; i++) {
            //當月的第一天加i
            Date tempDate = DateUtil.dateAddToDate("d", i, beginDate, "yyyy-MM-dd"); 
            //將當月的第i天新增到當月的日期集合中
            dateArr[i] = DateUtil.datetoStr(tempDate, "yyyy-MM-dd");
        }

       //動態拼裝datagrid列頭資訊
       String headerString = StringUtil.join(dateArr, ",");
       request.setAttribute("headerString", headerString);
       return "/views/shop/att/att";
     } catch (Exception e) {
         log.error("跳轉考勤資訊頁面失敗",e);
     }
     return "/error/500";
}

考勤列表datagrid通過url /shop/att/queryAtts.do載入資料的程式碼:
controller資料:

/**
  * 查詢某店鋪的某個月份的所有考勤資訊
  * @param attYearMonth 考勤年月
  * @param request
  * @return
  */
  @ResponseBody
  @RequestMapping("/queryAtts")
  public List<Map<String,Object>> queryAtts(String attYearMonth){
    try {
      //根據動態列封裝的動態資料
      List<Map<String,Object>> result = new ArrayList<Map<String,Object>>();
      //查詢某個店鋪某個月的考勤資訊
      List<Object[]> rows = attendanceService.queryAttendances(Constant.SHOP_ID, attYearMonth);
      if(rows != null && rows.size() > 0){
        for(Object[] row : rows){
           //考勤id  
           String id = row[0].toString();
           //員工姓名
           String name = row[1].toString();
           //員工某個月份考勤日期集合字串
           String att_dates = row[2].toString();
           //員工某個月份考勤型別集合字串
           String att_types = row[3] == null ? "" : row[3].toString();
           //員工某個月份遲到分鐘數集合字串
           String late_mins = row[4] == null ? "" : row[4].toString();
           //員工某個月份請假分鐘數集合字串
           String leavebill_mins = row[5] == null ? "" : row[5].toString();

           Map<String,Object> map = new HashMap<String,Object>();
           map.put("id", id);
           map.put("name", name);
           if(StringUtil.notNull(att_dates)){
             //員工某個月份考勤日期集合陣列
             String[] attDateArr = att_dates.split(",");
             //員工某個月份考勤型別集合陣列
             String[] attTypeArr = att_types.split(",");
             //員工某個月份遲到分鐘數集合陣列
             String[] lateMinAtt = late_mins.split(",");
             //員工某個月份請假分鐘數集合陣列
             String[] leavebillMinAtt = leavebill_mins.split(",");

             for (int i = 0; i < attDateArr.length; i++) {

                                if(StringUtil.notNull(attTypeArr[i])){
          //考勤型別
          int attType = Integer.parseInt(attTypeArr[i]);
          //考勤資訊
          String attInfo = getAttInfo(attType);
          if(attType == 3){
             //請假分鐘數
             attInfo += " :" + leavebillMinAtt[i] + "分";
         }else if(attType == 4){
             //遲到分鐘數
             attInfo += " :" + lateMinAtt[i] + "分";
          }
          //設定員工某一天的考勤資訊
          map.put(attDateArr[i], attInfo);
              }
             }
           }

         result.add(map);
        }
      }
      return result;
   } catch (Exception e) {
       log.error("查詢某店鋪的某個月份的所有考勤資訊失敗",e);
   }
   return null;
}

service層程式碼:
sql語句中使用了行轉列以及group_concat

/**
 * 
 * @Description 查詢某店鋪的某個月份的所有考勤資訊
 * @param shopId 店鋪id
 * @param attYearMonth 查詢考勤的年月
 * @return
 * @throws Exception
 */
@SuppressWarnings("unchecked")
@Override
public List<Object[]> queryAttendances(String shopId, String attYearMonth) throws Exception {
    //月初1號
    //attYearMonth = "2017-06";
    Date beginDate = DateUtil.strToDate(attYearMonth + "-01", "yyyy-MM-dd");
    //月末最後一天(月初1號加一個月)
    Date endDate = DateUtil.getLastDayByYearMonth(attYearMonth);
    StringBuffer sb = new StringBuffer(" select t.beautician_id,b.name as bname, ");
    sb.append(" GROUP_CONCAT(t.att_date) as att_dates, ");
    sb.append(" GROUP_CONCAT(IFNULL(t.att_type,' ')) as att_types, ");
    sb.append(" GROUP_CONCAT(IFNULL(t.late_min,' ')) as late_mins, ");
    sb.append(" GROUP_CONCAT(IFNULL(t.leavebill_min,' ')) as leavebill_mins, ");
    sb.append(" GROUP_CONCAT(t.summary) as summarys ");
    sb.append(" from t_attendance t,t_beautician b ");
    sb.append(" where t.beautician_id = b.id ");
    sb.append(" and t.att_date >= ? ");
    sb.append(" and t.att_date <= ? ");
    sb.append(" group by t.beautician_id ");
    return (List<Object[]>)baseDao.queryBySql(sb.toString(), beginDate,endDate);
}

3、點查詢按鈕動態生成列的方式(此方式與上面的跳轉到att.jsp頁面生成動態列的方式不同)

/**
 * 查詢考勤資訊
 */
 function getAtts(){
    var attYearMonthStr = $("#attYearMonth").datebox("getValue");
    //通ajax從後臺動態獲取動態列的字串
    $.ajax({
        type:"POST",
        dataType : "json",
        async: false,
        url : '${pageContext.request.contextPath}/shop/att/queryHeader.do',
        data : {attYearMonth:attYearMonthStr},
        success : function(json){
            //從後臺獲取的動態列的字串
            var headerStr = json.obj;
            //將字串轉換為datagrid的column的data
            var colObjArr = covertHeader(headerStr);

            //動態載入動態列
            var options={};  
            options.columns = [colObjArr];

            $('#attDataGrid').datagrid(options);    
            //動態列重新載入後重新整理datagrid
            $('#attDataGrid').datagrid('reload');   
        },
        error:function(){
            messagerShow('提示', json);
        }
 });

4、EasyUi點選單元格檢視、編輯員工某一天的考勤資訊

下面的程式碼也在考勤列表(上面att.jsp頁面程式碼片段)中

//單擊單元格
  onClickCell:function(rowIndex, field, value){
        //根據rowIndex獲取datagrid的行
        var row = $('#attDataGrid').datagrid('getData').rows[rowIndex];
        //通過row獲取員工id
        var beauticianId = row.id;
        //獲取列頭,實際上就是員的考勤日期
        var attDate = field; 
        //彈出考勤設定頁面
        showAtt(beauticianId,attDate);
       }
    }

5、小結:上面的程式碼是一個初步的實現,可以進一步優化的地方有,動態生成列的兩個地方都是從後臺獲取資料,可以改為根據databox年月框的值,在頁面前端動態生成動態列的資料。後面有時間會將前端動態生成列的程式碼補上。