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设置,只显示年月,也只能选择年月。该问题查看本人的blogEasyUi日期控件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年月框的值,在页面前端动态生成动态列的数据。后面有时间会将前端动态生成列的代码补上。

猜你喜欢

转载自blog.csdn.net/ytangdigl/article/details/73380684