浏览代码

Merge remote-tracking branch 'origin/developerH' into developer

# Conflicts:
#	src/main/resources/mappings/modules/order/OrderMapper.xml
huangzhiguo 2 年之前
父节点
当前提交
039926b087
共有 27 个文件被更改,包括 4991 次插入54 次删除
  1. 19 0
      src/main/java/com/caimei/modules/order/entity/NewOrder.java
  2. 2 2
      src/main/java/com/caimei/modules/user/dao/CmBehaviorRecordDao.java
  3. 30 0
      src/main/java/com/caimei/modules/user/dao/CmPortraitDao.java
  4. 69 0
      src/main/java/com/caimei/modules/user/entity/ArrDate.java
  5. 9 0
      src/main/java/com/caimei/modules/user/entity/CmBehaviorRecord.java
  6. 20 0
      src/main/java/com/caimei/modules/user/entity/CmClubRemarks.java
  7. 197 0
      src/main/java/com/caimei/modules/user/entity/CmPortrait.java
  8. 30 0
      src/main/java/com/caimei/modules/user/entity/OrderPortrait.java
  9. 294 0
      src/main/java/com/caimei/modules/user/service/ClubPortraitService.java
  10. 2 2
      src/main/java/com/caimei/modules/user/service/CmBehaviorRecordService.java
  11. 44 0
      src/main/java/com/caimei/modules/user/web/CmUserBehaviorRecordController.java
  12. 127 2
      src/main/java/com/caimei/modules/user/web/newUser/AgencyController.java
  13. 38 45
      src/main/resources/mappings/modules/user/CmBehaviorRecordMapper.xml
  14. 94 0
      src/main/resources/mappings/modules/user/CmPortraitMapper.xml
  15. 7 0
      src/main/webapp/WEB-INF/views/modules/user/behaviorRecordList.jsp
  16. 7 0
      src/main/webapp/WEB-INF/views/modules/user/behaviorRecordRossList.jsp
  17. 10 3
      src/main/webapp/WEB-INF/views/modules/userNew/cmAgencyList.jsp
  18. 421 0
      src/main/webapp/WEB-INF/views/modules/userNew/cmClubData.jsp
  19. 157 0
      src/main/webapp/WEB-INF/views/modules/userNew/cmClubPortrait.jsp
  20. 90 0
      src/main/webapp/static/datapicker/daterangepicker.css
  21. 2745 0
      src/main/webapp/static/datapicker/jquery.daterangepicker.js
  22. 0 0
      src/main/webapp/static/datapicker/moment-2.29.min.js
  23. 0 0
      src/main/webapp/static/datapicker/moment.min.js
  24. 34 0
      src/main/webapp/static/echarts/echarts.min.js
  25. 354 0
      src/main/webapp/static/modules/cmClubPortrait/cmClubEacths.js
  26. 136 0
      src/main/webapp/static/modules/cmClubPortrait/cmClubPortrait.css
  27. 55 0
      src/main/webapp/static/modules/cmClubPortrait/cmClubPortrait.js

+ 19 - 0
src/main/java/com/caimei/modules/order/entity/NewOrder.java

@@ -159,6 +159,9 @@ public class NewOrder extends DataEntity<NewOrder> {
 
     private Integer productCode;//订单商品是否是采美信息分帐号收款的线上支付子订单
 
+    private Integer numbers;    // 总数
+    private Double totalMoney;  // 总金额
+
 
     /**
      * 呵呵商城优惠券
@@ -1229,5 +1232,21 @@ public class NewOrder extends DataEntity<NewOrder> {
     public void setReturnGoodsStutas(Integer returnGoodsStutas) {
         this.returnGoodsStutas = returnGoodsStutas;
     }
+
+    public Integer getNumbers() {
+        return numbers;
+    }
+
+    public void setNumbers(Integer numbers) {
+        this.numbers = numbers;
+    }
+
+    public Double getTotalMoney() {
+        return totalMoney;
+    }
+
+    public void setTotalMoney(Double totalMoney) {
+        this.totalMoney = totalMoney;
+    }
 }
 

+ 2 - 2
src/main/java/com/caimei/modules/user/dao/CmBehaviorRecordDao.java

@@ -18,11 +18,11 @@ import java.util.List;
 public interface CmBehaviorRecordDao extends CrudDao<CmBehaviorRecord> {
 
     /**
-     * 查询当天以外的数据
+     * 查询符合条件数据 -- export
      * @param cmBehaviorRecord
      * @return
      */
-    List<CmBehaviorRecord> findListBefore(CmBehaviorRecord cmBehaviorRecord);
+    List<CmBehaviorRecord> exportList(CmBehaviorRecord cmBehaviorRecord);
     /**
      * 查询单条详情
      * @param cmBehaviorRecord

+ 30 - 0
src/main/java/com/caimei/modules/user/dao/CmPortraitDao.java

@@ -0,0 +1,30 @@
+package com.caimei.modules.user.dao;
+
+import com.caimei.modules.order.entity.NewOrder;
+import com.caimei.modules.user.entity.CmBehaviorRecord;
+import com.caimei.modules.user.entity.CmClubRemarks;
+import com.caimei.modules.user.entity.CmPortrait;
+import com.thinkgem.jeesite.common.persistence.CrudDao;
+import com.thinkgem.jeesite.common.persistence.annotation.MyBatisDao;
+
+import java.util.List;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2023/2/15
+ */
+@MyBatisDao
+public interface CmPortraitDao extends CrudDao<CmPortrait> {
+
+    CmPortrait selTotal(CmPortrait cmPortrait);
+
+    List<NewOrder> selOrderList(CmPortrait cmPortrait);
+
+    List<CmBehaviorRecord> selBehaviorList(CmPortrait cmPortrait);
+
+    List<CmClubRemarks> selRemarksList(CmPortrait cmPortrait);
+
+    List<CmBehaviorRecord> selBehaviorPageTypeList(CmPortrait cmPortrait);
+}

+ 69 - 0
src/main/java/com/caimei/modules/user/entity/ArrDate.java

@@ -0,0 +1,69 @@
+package com.caimei.modules.user.entity;
+
+import java.util.ArrayList;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2023/2/16
+ */
+public class ArrDate {
+
+    private ArrayList<String> name;
+    private ArrayList<Integer> value;
+
+    private ArrayList<OrderPortrait> orderList;
+    private Integer orderTotalNum;
+
+    private String startTime;
+    private String endTime;
+
+    public ArrayList<String> getName() {
+        return name;
+    }
+
+    public void setName(ArrayList<String> name) {
+        this.name = name;
+    }
+
+    public ArrayList<Integer> getValue() {
+        return value;
+    }
+
+    public void setValue(ArrayList<Integer> value) {
+        this.value = value;
+    }
+
+    public ArrayList<OrderPortrait> getOrderList() {
+        return orderList;
+    }
+
+    public void setOrderList(ArrayList<OrderPortrait> orderList) {
+        this.orderList = orderList;
+    }
+
+    public Integer getOrderTotalNum() {
+        return orderTotalNum;
+    }
+
+    public void setOrderTotalNum(Integer orderTotalNum) {
+        this.orderTotalNum = orderTotalNum;
+    }
+
+    public String getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(String startTime) {
+        this.startTime = startTime;
+    }
+
+    public String getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(String endTime) {
+        this.endTime = endTime;
+    }
+}

+ 9 - 0
src/main/java/com/caimei/modules/user/entity/CmBehaviorRecord.java

@@ -43,6 +43,7 @@ public class CmBehaviorRecord extends DataEntity<CmBehaviorRecord> {
     private String contacts;    //联系人
     private String phoneNumber; //手机号码
 
+    private Integer number;
     private Integer numbers;    //访问页面总数
     private String userIdentity; //公司类型
 
@@ -259,6 +260,14 @@ public class CmBehaviorRecord extends DataEntity<CmBehaviorRecord> {
         this.phoneNumber = phoneNumber;
     }
 
+    public Integer getNumber() {
+        return number;
+    }
+
+    public void setNumber(Integer number) {
+        this.number = number;
+    }
+
     public Integer getNumbers() {
         return numbers;
     }

+ 20 - 0
src/main/java/com/caimei/modules/user/entity/CmClubRemarks.java

@@ -143,6 +143,10 @@ public class CmClubRemarks extends DataEntity<CmClubRemarks> {
 
     private Integer reportID;
 
+    private Integer number;
+
+    private Integer numbers;
+
 
     public Integer getReportID() {
         return reportID;
@@ -425,4 +429,20 @@ public class CmClubRemarks extends DataEntity<CmClubRemarks> {
     public void setAuditName(String auditName) {
         this.auditName = auditName;
     }
+
+    public Integer getNumber() {
+        return number;
+    }
+
+    public void setNumber(Integer number) {
+        this.number = number;
+    }
+
+    public Integer getNumbers() {
+        return numbers;
+    }
+
+    public void setNumbers(Integer numbers) {
+        this.numbers = numbers;
+    }
 }

+ 197 - 0
src/main/java/com/caimei/modules/user/entity/CmPortrait.java

@@ -0,0 +1,197 @@
+package com.caimei.modules.user.entity;
+
+import com.thinkgem.jeesite.common.persistence.DataEntity;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2023/2/15
+ */
+public class CmPortrait extends DataEntity<CmPortrait> {
+
+    // 机构id
+    private Integer clubID;
+    // 机构名称
+    private String clubName;
+    // 日期类别 0日 1月 2半年 3全年
+    private Integer dateType;
+    // 开始时间
+    private String startTime;
+    // 结束时间
+    private String endTime;
+    // 统计类别 0订单 1搜索关键词 2咨询记录 3访问记录 4初始状态
+    private Integer type;
+    // 时间
+    private String accessDate;
+
+    // 订单总量
+    private Integer orderTotal;
+    // 订单总金额
+    private BigDecimal orderTotalAmount;
+    // 订单类型值value  订单类型name
+    private ArrayList<OrderPortrait> orderPortrait;
+    // 搜索关键词总数
+    private Integer totalkeywords;
+    // 搜索关键词数量
+    private ArrayList<Integer> behaviorValue;
+    // 搜索关键词
+    private ArrayList<String> behaviorType;
+    // 咨询记录总数
+    private Integer remarksTotal;
+    // 咨询记录数
+    private ArrayList<Integer> remarksValue;
+    // 咨询记录关键词
+    private ArrayList<String> remarksType;
+    // 访问记录数
+    private ArrayList<Integer> pageTypeValue;
+    // 访问词
+    private ArrayList<String> pageType;
+
+    public Integer getClubID() {
+        return clubID;
+    }
+
+    public void setClubID(Integer clubID) {
+        this.clubID = clubID;
+    }
+
+    public String getClubName() {
+        return clubName;
+    }
+
+    public void setClubName(String clubName) {
+        this.clubName = clubName;
+    }
+
+    public Integer getDateType() {
+        return dateType;
+    }
+
+    public void setDateType(Integer dateType) {
+        this.dateType = dateType;
+    }
+
+    public String getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(String startTime) {
+        this.startTime = startTime;
+    }
+
+    public String getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(String endTime) {
+        this.endTime = endTime;
+    }
+
+    public Integer getType() {
+        return type;
+    }
+
+    public void setType(Integer type) {
+        this.type = type;
+    }
+
+    public String getAccessDate() {
+        return accessDate;
+    }
+
+    public void setAccessDate(String accessDate) {
+        this.accessDate = accessDate;
+    }
+
+    public Integer getOrderTotal() {
+        return orderTotal;
+    }
+
+    public void setOrderTotal(Integer orderTotal) {
+        this.orderTotal = orderTotal;
+    }
+
+    public BigDecimal getOrderTotalAmount() {
+        return orderTotalAmount;
+    }
+
+    public void setOrderTotalAmount(BigDecimal orderTotalAmount) {
+        this.orderTotalAmount = orderTotalAmount;
+    }
+
+    public ArrayList<OrderPortrait> getOrderPortrait() {
+        return orderPortrait;
+    }
+
+    public void setOrderPortrait(ArrayList<OrderPortrait> orderPortrait) {
+        this.orderPortrait = orderPortrait;
+    }
+
+    public Integer getTotalkeywords() {
+        return totalkeywords;
+    }
+
+    public void setTotalkeywords(Integer totalkeywords) {
+        this.totalkeywords = totalkeywords;
+    }
+
+    public ArrayList<Integer> getBehaviorValue() {
+        return behaviorValue;
+    }
+
+    public void setBehaviorValue(ArrayList<Integer> behaviorValue) {
+        this.behaviorValue = behaviorValue;
+    }
+
+    public ArrayList<String> getBehaviorType() {
+        return behaviorType;
+    }
+
+    public void setBehaviorType(ArrayList<String> behaviorType) {
+        this.behaviorType = behaviorType;
+    }
+
+    public Integer getRemarksTotal() {
+        return remarksTotal;
+    }
+
+    public void setRemarksTotal(Integer remarksTotal) {
+        this.remarksTotal = remarksTotal;
+    }
+
+    public ArrayList<Integer> getRemarksValue() {
+        return remarksValue;
+    }
+
+    public void setRemarksValue(ArrayList<Integer> remarksValue) {
+        this.remarksValue = remarksValue;
+    }
+
+    public ArrayList<String> getRemarksType() {
+        return remarksType;
+    }
+
+    public void setRemarksType(ArrayList<String> remarksType) {
+        this.remarksType = remarksType;
+    }
+
+    public ArrayList<Integer> getPageTypeValue() {
+        return pageTypeValue;
+    }
+
+    public void setPageTypeValue(ArrayList<Integer> pageTypeValue) {
+        this.pageTypeValue = pageTypeValue;
+    }
+
+    public ArrayList<String> getPageType() {
+        return pageType;
+    }
+
+    public void setPageType(ArrayList<String> pageType) {
+        this.pageType = pageType;
+    }
+}

+ 30 - 0
src/main/java/com/caimei/modules/user/entity/OrderPortrait.java

@@ -0,0 +1,30 @@
+package com.caimei.modules.user.entity;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2023/2/15
+ */
+public class OrderPortrait {
+
+    private Integer value;
+
+    private String name;
+
+    public Integer getValue() {
+        return value;
+    }
+
+    public void setValue(Integer value) {
+        this.value = value;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}

+ 294 - 0
src/main/java/com/caimei/modules/user/service/ClubPortraitService.java

@@ -0,0 +1,294 @@
+package com.caimei.modules.user.service;
+
+import com.caimei.modules.order.entity.NewOrder;
+import com.caimei.modules.user.dao.CmPortraitDao;
+import com.caimei.modules.user.entity.CmBehaviorRecord;
+import com.caimei.modules.user.entity.CmClubRemarks;
+import com.caimei.modules.user.entity.CmPortrait;
+import com.caimei.modules.user.entity.OrderPortrait;
+import com.thinkgem.jeesite.common.utils.ObjectUtils;
+import com.thinkgem.jeesite.common.utils.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2023/2/15
+ */
+@Service
+public class ClubPortraitService {
+
+    @Autowired private CmPortraitDao cmPortraitDao;
+
+    /**
+     * 查询画像资料总数
+     * @param cmPortrait
+     * @return
+     */
+    public CmPortrait dataTotal(CmPortrait cmPortrait) {
+        CmPortrait cmPortraits = cmPortraitDao.selTotal(cmPortrait);
+        return cmPortraits;
+    }
+    /**
+     * 查询机构画像数据
+     * @param cmPortrait
+     * @return
+     */
+    public CmPortrait dataList(CmPortrait cmPortrait) {
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+        Date date = new Date();
+        String endTime = "";
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.add(Calendar.DAY_OF_MONTH, -1);
+        Date time = calendar.getTime();
+        endTime = dateFormat.format(time);
+        String time1 = "";
+        String time2 = "";
+        boolean expty = ObjectUtils.isEmpty(cmPortrait.getStartTime()) && ObjectUtils.isEmpty(cmPortrait.getEndTime());
+        if (expty) {
+            Date start = null;
+            String startTime = "";
+            String format = dateFormat.format(date);
+            cmPortrait.setEndTime(endTime);
+            // 日期参数为    日
+            if (0 ==  cmPortrait.getDateType() || 1 == cmPortrait.getDateType()) {
+                cmPortrait.setAccessDate(endTime);
+                cmPortrait.setStartTime(endTime);
+//                cmPortrait.setEndTime(endTime);
+            }
+            if (2 == cmPortrait.getDateType()) {
+//                cmPortrait.setEndTime(endTime);
+                calendar.setTime(time);
+                calendar.add(Calendar.MONTH, -1);
+                start = calendar.getTime();
+                startTime = dateFormat.format(start);
+                cmPortrait.setStartTime(startTime);
+            }
+            if (3 == cmPortrait.getDateType()) {
+//                cmPortrait.setEndTime(endTime);
+                calendar.setTime(time);
+                calendar.add(Calendar.MONTH, -6);
+                start = calendar.getTime();
+                startTime = dateFormat.format(start);
+                cmPortrait.setStartTime(startTime);
+            }
+            if (4 == cmPortrait.getDateType()) {
+//                cmPortrait.setEndTime(endTime);
+                calendar.setTime(time);
+                calendar.add(Calendar.YEAR, -1);
+                start = calendar.getTime();
+                startTime = dateFormat.format(start);
+                cmPortrait.setStartTime(startTime);
+            }
+        } else {
+            time1 = cmPortrait.getStartTime();
+            time2 = cmPortrait.getEndTime();
+        }
+        // 机构订单
+        if (0 == cmPortrait.getType() || 4 == cmPortrait.getType()) {
+            if ((0 ==  cmPortrait.getDateType() || 1 == cmPortrait.getDateType()) && expty) {
+                cmPortrait.setEndTime(dateFormat.format(date));
+            }
+            if (cmPortrait.getEndTime().equals(endTime)) {
+                cmPortrait.setEndTime(dateFormat.format(date));
+            }
+            int ordinary = 0, secondHand = 0, rebate = 0, partialRefund = 0, fullRefund = 0, closed = 0;
+
+            ArrayList<OrderPortrait> orderPortraits = new ArrayList<>();
+            OrderPortrait orderPortrait = new OrderPortrait();
+            List<NewOrder> orderList = cmPortraitDao.selOrderList(cmPortrait);
+            int length = orderList.size();
+            NumberFormat instance = NumberFormat.getInstance();
+            instance.setMaximumFractionDigits(2);
+            if (length != 0) {
+                for (NewOrder order : orderList) {
+                    // 普通订单
+                    if (("0".equals(order.getSecondHandOrderFlag()) || StringUtils.isEmpty(order.getSecondHandOrderFlag()))
+                            && (!"1".equals(order.getRebateFlag()) || "".equals(order.getRebateFlag()) || StringUtils.isEmpty(order.getRebateFlag()))
+                            && ((!"1".equals(order.getRefundType()) && !"2".equals(order.getRefundType())) || "".equals(order.getRefundType()) || StringUtils.isEmpty(order.getRefundType()))
+                            && !"6".equals(order.getStatus())) {
+                        ordinary++;
+                    }
+                    // 二手订单
+                    if ("1".equals(order.getSecondHandOrderFlag()) && !"1".equals(order.getRebateFlag())
+                            && (!"1".equals(order.getRefundType()) && !"2".equals(order.getRefundType())) && !"6".equals(order.getStatus())) {
+                        secondHand++;
+                    }
+                    // 返佣订单
+                    if ("1".equals(order.getRebateFlag()) &&
+                            (!"1".equals(order.getRefundType()) && !"2".equals(order.getRefundType()) || StringUtils.isEmpty(order.getRefundType())) && !"6".equals(order.getStatus())) {
+                        rebate++;
+                    }
+                    // 部分退款
+                    if ("1".equals(order.getRefundType()) && !"6".equals(order.getStatus())) {
+                        partialRefund++;
+                    }
+                    // 全部退款
+                    if ("2".equals(order.getRefundType()) && !"6".equals(order.getStatus())) {
+                        fullRefund++;
+                    }
+                    // 已关闭
+                    if ("6".equals(order.getStatus()) || StringUtils.isEmpty(order.getStatus())) {
+                        closed++;
+                    }
+                }
+                /*cmPortrait.setOrderTotalAmount(orderList.get(0).getTotalMoney());
+                cmPortrait.setOrderTotal(orderList.get(0).getNumbers());*/
+                cmPortrait.setOrderTotal(length);
+
+                orderPortrait.setValue(ordinary);
+                if (ordinary != 0) {
+                    orderPortrait.setName("普通订单 【" + instance.format((float)ordinary / (float) length * 100) + "%】 【" + ordinary + "个】");
+                } else {
+                    orderPortrait.setName("普通订单 【 0 %】 【" + ordinary + "个】");
+                }
+                orderPortraits.add(orderPortrait);
+                orderPortrait = new OrderPortrait();
+                orderPortrait.setValue(secondHand);
+                if (secondHand != 0) {
+                    orderPortrait.setName("二手订单 【" + instance.format((float)secondHand / (float) length * 100) + "%】 【" + secondHand + "个】");
+                } else {
+                    orderPortrait.setName("二手订单 【 0 %】 【" + secondHand + "个】");
+                }
+                orderPortraits.add(orderPortrait);
+                orderPortrait = new OrderPortrait();
+                orderPortrait.setValue(rebate);
+                if (rebate != 0) {
+                    orderPortrait.setName("返佣订单 【" + instance.format((float)rebate / (float) length * 100) + "%】 【" + rebate + "个】");
+                } else {
+                    orderPortrait.setName("返佣订单 【 0 %】 【" + rebate + "个】");
+                }
+                orderPortraits.add(orderPortrait);
+                orderPortrait = new OrderPortrait();
+                orderPortrait.setValue(partialRefund);
+                if (partialRefund != 0) {
+                    orderPortrait.setName("部分退款订单 【" + instance.format((float)partialRefund / (float) length * 100) + "%】 【" + partialRefund + "个】");
+                } else {
+                    orderPortrait.setName("部分退款订单 【 0 %】 【" + partialRefund + "个】");
+                }
+                orderPortraits.add(orderPortrait);
+                orderPortrait = new OrderPortrait();
+                orderPortrait.setValue(fullRefund);
+                if (fullRefund != 0) {
+                    orderPortrait.setName("全部退款订单 【" + instance.format((float)fullRefund / (float) length * 100) + "%】 【" + fullRefund + "个】");
+                } else {
+                    orderPortrait.setName("全部退款订单 【 0 %】 【" + fullRefund + "个】");
+                }
+                orderPortraits.add(orderPortrait);
+                orderPortrait = new OrderPortrait();
+                orderPortrait.setValue(closed);
+                if (closed != 0) {
+                    orderPortrait.setName("已关闭订单 【" + instance.format((float)closed / (float) length * 100) + "%】 【" + closed + "个】");
+                } else {
+                    orderPortrait.setName("已关闭订单 【 0 %】 【" + closed + "个】");
+                }
+                orderPortraits.add(orderPortrait);
+
+                cmPortrait.setOrderPortrait(orderPortraits);
+            }
+            calendar.setTime(date);
+            calendar.add(Calendar.DAY_OF_MONTH, -1);
+            time = calendar.getTime();
+            endTime = dateFormat.format(time);
+            cmPortrait.setEndTime(endTime);
+        }
+        // 搜索关键词
+        if (1 == cmPortrait.getType() || 4 == cmPortrait.getType()) {
+            List<CmBehaviorRecord> behaviorRecordList = cmPortraitDao.selBehaviorList(cmPortrait);
+            ArrayList<Integer> integers = new ArrayList<>();
+            ArrayList<String> strings = new ArrayList<>();
+            if (behaviorRecordList.size() != 0) {
+                for (CmBehaviorRecord record : behaviorRecordList) {
+                    integers.add(record.getNumber());
+                    if (!ObjectUtils.isEmpty(record.getPageLabel())) {
+                        strings.add(record.getPageLabel());
+                    } else {
+                        strings.add("未知");
+                    }
+                    cmPortrait.setTotalkeywords(behaviorRecordList.get(0).getNumbers());
+                    cmPortrait.setBehaviorValue(integers);
+                    cmPortrait.setBehaviorType(strings);
+                }
+            }
+        }
+        // 咨询记录
+        if (2 == cmPortrait.getType() || 4 == cmPortrait.getType()) {
+            if ((0 ==  cmPortrait.getDateType() || 1 == cmPortrait.getDateType()) && expty) {
+                cmPortrait.setEndTime(dateFormat.format(date));
+            }
+            if (cmPortrait.getEndTime().equals(endTime)) {
+                cmPortrait.setEndTime(dateFormat.format(date));
+            }
+            List<CmClubRemarks> remarksList = cmPortraitDao.selRemarksList(cmPortrait);
+            ArrayList<Integer> integers = new ArrayList<>();
+            ArrayList<String> strings = new ArrayList<>();
+            ArrayList<String> strRemark = new ArrayList<>();
+            int number = 0;
+            if (remarksList.size() != 0) {
+                for (CmClubRemarks remarks: remarksList) {
+                    String[] split = remarks.getRemarks().split(",");
+                    for (String str : split) {
+                        if (!strRemark.contains(str)) {
+                            strRemark.add(str);
+                        }
+                    }
+                }
+                for (String str : strRemark) {
+                    for (CmClubRemarks remarks: remarksList) {
+                        if (remarks.getRemarks().contains(str)) {
+                            number++;
+                        }
+                    }
+                    integers.add(number);
+                    if (!ObjectUtils.isEmpty(str)) {
+                        strings.add(str);
+                    } else {
+                        strings.add("未知");
+                    }
+                    number = 0;
+                }
+
+                cmPortrait.setRemarksTotal(remarksList.get(0).getNumbers());
+                cmPortrait.setRemarksValue(integers);
+                cmPortrait.setRemarksType(strings);
+            }
+            calendar.setTime(date);
+            calendar.add(Calendar.DAY_OF_MONTH, -1);
+            time = calendar.getTime();
+            endTime = dateFormat.format(time);
+            cmPortrait.setEndTime(endTime);
+        }
+        // 访问记录
+        if (3 == cmPortrait.getType() || 4 == cmPortrait.getType()) {
+            List<CmBehaviorRecord> pageTypeList = cmPortraitDao.selBehaviorPageTypeList(cmPortrait);
+            ArrayList<Integer> integers = new ArrayList<>();
+            ArrayList<String> strings = new ArrayList<>();
+            if (pageTypeList.size() != 0) {
+                for(CmBehaviorRecord record : pageTypeList) {
+                    integers.add(record.getNumbers());
+                    strings.add(record.getPageType());
+                }
+                cmPortrait.setPageTypeValue(integers);
+                cmPortrait.setPageType(strings);
+            }
+        }
+        if (!expty) {
+            cmPortrait.setStartTime(time1);
+            if ((0 ==  cmPortrait.getDateType() || 1 == cmPortrait.getDateType()) && ObjectUtils.isEmpty(cmPortrait.getStartTime())) {
+                cmPortrait.setStartTime(time2);
+            }
+            cmPortrait.setEndTime(time2);
+        }
+        return cmPortrait;
+    }
+}

+ 2 - 2
src/main/java/com/caimei/modules/user/service/CmBehaviorRecordService.java

@@ -41,7 +41,7 @@ public class CmBehaviorRecordService extends CrudService<CmBehaviorRecordDao, Cm
         return super.findPage(page,cmBehaviorRecord);
     }
 
-    public List<CmBehaviorRecord> behaviorList(CmBehaviorRecord cmBehaviorRecord) {
+    /*public List<CmBehaviorRecord> behaviorList(CmBehaviorRecord cmBehaviorRecord) {
         List<CmBehaviorRecord> list = new ArrayList<>();
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
         String format = dateFormat.format(new Date());
@@ -83,7 +83,7 @@ public class CmBehaviorRecordService extends CrudService<CmBehaviorRecordDao, Cm
             listDataMerge.clear();
         }
         return list;
-    }
+    }*/
     /**
      * 用户行为详情
      * @param page

+ 44 - 0
src/main/java/com/caimei/modules/user/web/CmUserBehaviorRecordController.java

@@ -1,5 +1,6 @@
 package com.caimei.modules.user.web;
 
+import com.caimei.modules.common.utils.ExcelUtil;
 import com.caimei.modules.order.entity.NewOrder;
 import com.caimei.modules.order.service.NewOrderService;
 import com.caimei.modules.user.dao.CmBehaviorRecordDao;
@@ -24,7 +25,9 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Description
@@ -239,4 +242,45 @@ public class CmUserBehaviorRecordController extends BaseController {
         return "modules/user/behaviorNewOrder";
     }
 
+    @RequestMapping(value = "/export")
+    public void exports(CmBehaviorRecord cmBehaviorRecord,HttpServletRequest request,HttpServletResponse response,RedirectAttributes redirectAttributes) {
+
+        String fileName = "ROSS行为记录.xls";
+        String template = Global.getConfig("export.template");
+        String templataFileName = template + "/ross_behavior.xls";
+        try {
+            Map data = new HashMap<String, Object>();
+            List<CmBehaviorRecord> exportList = null;
+            if ("1".equals(cmBehaviorRecord.getBehaviorType())) {
+                fileName = "用户行为记录.xls";
+                exportList = cmBehaviorRecordService.findPageList(new Page<>(request,response),cmBehaviorRecord).getList();
+            } else {
+                exportList = cmBehaviorRecordDao.exportList(cmBehaviorRecord);
+            }
+            for(CmBehaviorRecord record: exportList) {
+                // 计算访问时长
+                String time = cmBehaviorRecordService.calculationTime(record.getAccessDuration());
+                record.setAccessDuration(time);
+                if ("0".equals(record.getAccessClient())) {
+                    record.setAccessClient("网站");
+                } else {
+                    record.setAccessClient("小程序");
+                }
+                if ("1".equals(record.getCompanyType())) {
+                    record.setCompanyType("游客");
+                } else if ("2".equals(record.getCompanyType())) {
+                    record.setCompanyType("机构");
+                } else {
+                    record.setCompanyType("供应商");
+                }
+            }
+            data.put("list", exportList);
+            new ExcelUtil().createExcel(templataFileName, data, fileName, response);
+        } catch (Exception e) {
+            addMessage(redirectAttributes, "导出ROSS行为记录失败", e.getMessage());
+            logger.info(e.getMessage());
+            e.printStackTrace();
+        }
+
+    }
 }

+ 127 - 2
src/main/java/com/caimei/modules/user/web/newUser/AgencyController.java

@@ -21,10 +21,12 @@ import com.caimei.utils.AppUtils;
 import com.caimei.utils.DateUtils;
 import com.caimei.utils.MD5Util;
 import com.caimei.vo.JsonModel;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.google.common.collect.Maps;
 import com.thinkgem.jeesite.common.config.Global;
 import com.thinkgem.jeesite.common.persistence.Page;
 import com.thinkgem.jeesite.common.utils.Encodes;
+import com.thinkgem.jeesite.common.utils.ObjectUtils;
 import com.thinkgem.jeesite.common.utils.StringUtils;
 import com.thinkgem.jeesite.common.web.BaseController;
 import com.thinkgem.jeesite.modules.sys.security.SystemAuthorizingRealm;
@@ -100,8 +102,10 @@ public class AgencyController extends BaseController {
     private WeChatService weChatService;
     @Autowired
     private NewCmClubDao newCmClubDao;
-@Autowired
-private VisitRemarkDao visitRemarkDao;
+    @Autowired
+    private VisitRemarkDao visitRemarkDao;
+    @Autowired
+    private ClubPortraitService portraitService;
 
     @Value("${wwwServer}")
     private String domain;
@@ -1397,6 +1401,127 @@ private VisitRemarkDao visitRemarkDao;
         return map;
     }
 
+    @RequestMapping("/clubPortrait")
+    public String clubPortrait(CmPortrait cmPortrait, Model model) {
+        CmPortrait portrait = portraitService.dataTotal(cmPortrait);
+        model.addAttribute("cmPortrait",cmPortrait);
+        model.addAttribute("portrait",portrait);
+        return "modules/userNew/cmClubPortrait";
+    }
 
+    @RequestMapping("/selPortraitData")
+    @ResponseBody
+    public Map<String,Object> selPortraitData(CmPortrait cmPortrait) {
+        Map<String, Object> map = Maps.newLinkedHashMap();
+        try {
+            CmPortrait portrait = portraitService.dataList(cmPortrait);
+            ArrDate order = new ArrDate();
+            ArrDate behavior = new ArrDate();
+            ArrDate remarks = new ArrDate();
+            ArrDate pageType = new ArrDate();
+
+//            ArrayList<OrderPortrait> orderPortrait = portrait.getOrderPortrait();
+            order.setOrderList(portrait.getOrderPortrait());
+            if (portrait.getOrderTotal() == null) {
+                portrait.setOrderTotal(0);
+            }
+            order.setOrderTotalNum(portrait.getOrderTotal());
+            order.setStartTime(portrait.getStartTime());
+            order.setEndTime(portrait.getEndTime());
+            if (order.getOrderTotalNum() == 0) {
+                map.put("order",null);
+            } else {
+                map.put("order",order);
+            }
+            behavior.setName(portrait.getBehaviorType());
+            behavior.setValue(portrait.getBehaviorValue());
+            behavior.setStartTime(portrait.getStartTime());
+            behavior.setEndTime(portrait.getEndTime());
+            if (ObjectUtils.isEmpty(behavior.getValue())) {
+                map.put("behavior",null);
+            } else {
+                map.put("behavior",behavior);
+            }
+            remarks.setName(portrait.getRemarksType());
+            remarks.setValue(portrait.getRemarksValue());
+            remarks.setStartTime(portrait.getStartTime());
+            remarks.setEndTime(portrait.getEndTime());
+            if (ObjectUtils.isEmpty(remarks.getValue())) {
+                map.put("remarks",null);
+            } else {
+                map.put("remarks",remarks);
+            }
+            pageType.setName(portrait.getPageType());
+            pageType.setValue(portrait.getPageTypeValue());
+            pageType.setStartTime(portrait.getStartTime());
+            pageType.setEndTime(portrait.getEndTime());
+            if (ObjectUtils.isEmpty(pageType.getValue())) {
+                map.put("pageType",null);
+            } else {
+                map.put("pageType",pageType);
+            }
+            map.put("portrait",portrait);
+            /*map.put("behavior",behavior);
+            map.put("remarks",remarks);
+            map.put("pageType",pageType);
+            map.put("order",order);*/
+            map.put("code",0);
+        } catch (Exception e) {
+            e.printStackTrace();
+            map.put("code",-1);
+        }
+        return map;
+    }
+
+
+    @RequestMapping("/clubData")
+    public String clubData(NewCmClub newCmClub, Model model, HttpServletRequest request, HttpServletResponse response) {
+        // 查询机构基本信息
+        Page<NewCmClub> page = newCmClubService.findPage(new Page<NewCmClub>(request, response, 20), newCmClub);
+        if (page.getList().size() > 0) {
+            newCmClub = page.getList().get(0);
+        }
+        // 机构详细信息
+        CmClubinfo cmClubinfo = new CmClubinfo();
+        cmClubinfo.setClubID(newCmClub.getClubID());
+        List<CmClubinfo> cmClubinfos = cmClubinfoService.findList(cmClubinfo);
 
+        if (null != cmClubinfos && cmClubinfos.size() > 0) {
+            cmClubinfo = cmClubinfos.get(0);
+        }
+        cmClubinfo.setClubID(newCmClub.getClubID());
+        cmClubinfo.setUserID(newCmClub.getUserID());
+
+        cmClubinfo.setContractPhone(newCmClub.getContractPhone());
+        cmClubinfo.setFax(newCmClub.getFax());
+        cmClubinfo.setInfo(newCmClub.getInfo());
+        cmClubinfo.setBusinessLicenseImage(newCmClub.getBusinessLicenseImage());
+        cmClubinfo.setHeadpic(newCmClub.getHeadpic());
+        cmClubinfo.setSocialCreditCode(newCmClub.getSocialCreditCode());
+        cmClubinfo.setProvinceID(newCmClub.getProvinceID());
+        cmClubinfo.setCityID(newCmClub.getCityID());
+        cmClubinfo.setTownID(newCmClub.getTownID());
+        cmClubinfo.setAddress(newCmClub.getAddress());
+        cmClubinfo.setFirstClubType(newCmClub.getFirstClubType());
+        cmClubinfo.setSecondClubType(newCmClub.getSecondClubType());
+        cmClubinfo.setDepartment(newCmClub.getDepartment());
+        String  mainpro = newCmClub.getMainpro();
+        if (StringUtils.isNotEmpty(mainpro)) {
+            mainpro = mainpro.replaceAll("/",",");
+        }
+        cmClubinfo.setMainpro(mainpro);
+        cmClubinfo.setMedicalPracticeLicenseImg(newCmClub.getMedicalPracticeLicenseImg());
+        cmClubinfo.setContractEmail(newCmClub.getContractEmail());
+        cmClubinfo.setLinkManIdentity(newCmClub.getLinkManIdentity());
+
+        String wwwServer = Global.getConfig("wwwServer");
+        //营业执照
+        newCmClub.setBusinessLicenseImage(AppUtils.getImageURL("clubBusinessLicenseImage", newCmClub.getBusinessLicenseImage(), 0, wwwServer));
+        //门头照
+        newCmClub.setHeadpic(AppUtils.getImageURL("club", newCmClub.getHeadpic(), AppKeys.CLUB_LOGO_SIZE, wwwServer));
+
+        model.addAttribute("cmClubinfo", cmClubinfo);
+        model.addAttribute("newCmClub", newCmClub);
+        return "modules/userNew/cmClubData";
+    }
 }

+ 38 - 45
src/main/resources/mappings/modules/user/CmBehaviorRecordMapper.xml

@@ -67,66 +67,59 @@
         ORDER BY accessTime DESC
     </select>
 
-    <select id="findListBefore" resultType="com.caimei.modules.user.entity.CmBehaviorRecord">
+    <select id="exportList" resultType="com.caimei.modules.user.entity.CmBehaviorRecord">
         SELECT
-        <include refid="behaviorRecord"/>
-        ,SUM(b.accessDuration) AS accessDuration,
-        u.userIdentity,
-        u.userName,
-        c.sname AS cSname,
-        c.name,
-        c.linkMan,
-        c.contractMobile,
-        s.name AS sname,
-        s.linkMan AS slinkMan,
-        s.contractMobile AS scontractMobile,
-        c.clubID as clubID,
-        s.shopID as shopID,
-        max(b.region) as region,
-        max(accessTime) AS lastAccessTime,
-        (SELECT CASE STATUS WHEN 91 THEN '采美默认协销经理(官方账号)' ELSE linkMan END FROM serviceprovider WHERE serviceProviderID = c.spID) AS spName,
-        (SELECT COUNT(IP) FROM cm_behavior_record WHERE b.IP != '106.55.202.118' AND accessDate= #{accessDate}  GROUP BY accessDate) as numbers
-        FROM cm_behavior_record b
-        LEFT JOIN USER u ON b.userID = u.userID
-        LEFT JOIN club c ON b.userID = c.userID
-        LEFT JOIN shop s ON b.userID = s.userID
-        LEFT JOIN serviceprovider sp on c.spID = sp.serviceProviderID
+        IP,
+        userID,
+        clubID,
+        lastAccessTime,
+        companyType,
+        corporateName,
+        contacts,
+        phoneNumber,
+        spName,
+        number as numbers,
+        consultName,
+        consultMobile,
+        behaviorType,
+        productID,
+        accessTime,
+        accessDuration,
+        accessDate,
+        accessClient,
+        region
+        FROM cm_behavior_record_index
         <where>
-                b.IP != '106.55.202.118' AND b.accessDate = #{accessDate}
+            delFlag = 0
             <if test="behaviorType == 2">
-                AND b.behaviorType = #{behaviorType}
+                AND behaviorType = #{behaviorType}
             </if>
             <if test="IP != null and IP != ''">
-                AND b.IP = #{IP}
+                AND IP = #{IP}
             </if>
-            <if test="name != null and name != ''">
-                AND c.sname = #{name} or s.name = #{name}
+            <if test="corporateName != null and corporateName != ''">
+                AND corporateName like concat('%',#{corporateName},'%')
             </if>
-            <if test="userIdentity != null and userIdentity != ''">
-                <if test="userIdentity == 2">
-                    AND u.userIdentity in (2, 4)
-                </if>
-                <if test="userIdentity == 3">
-                    AND u.userIdentity = 3
-                </if>
-                <if test="userIdentity == 1">
-                    AND  b.userID = 0
-                </if>
+            <if test="companyType != null and companyType != ''">
+                AND companyType = #{companyType}
             </if>
-            <if test="userName != null and userName != ''">
-                AND u.userName = #{userName}
+            <if test="accessClient != null and accessClient != ''">
+                AND accessClient =#{accessClient}
+            </if>
+            <if test="contacts != null and contacts != ''">
+                AND contacts = #{contacts}
             </if>
-            <if test="contractMobile != null and contractMobile != ''">
-                AND (c.contractMobile = #{contractMobile} or s.contractMobile = #{contractMobile})
+            <if test="phoneNumber != null and phoneNumber != ''">
+                AND phoneNumber = #{phoneNumber}
             </if>
             <if test="spName != null and spName != ''">
-                AND sp.name = #{spName}
+                AND spName = #{spName}
             </if>
             <if test="startTime != null and startTime != '' and endTime != null and endTime != ''">
-                AND b.accessDate between #{startTime} and #{endTime}
+                AND accessDate between #{startTime} and #{endTime}
             </if>
         </where>
-        GROUP BY b.userID ORDER BY b.userID DESC
+        ORDER BY accessTime DESC
     </select>
 
     <select id="recordList" resultType="com.caimei.modules.user.entity.CmBehaviorRecord">

+ 94 - 0
src/main/resources/mappings/modules/user/CmPortraitMapper.xml

@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.caimei.modules.user.dao.CmPortraitDao">
+    <select id="selTotal" resultType="com.caimei.modules.user.entity.CmPortrait">
+        SELECT
+                (SELECT COUNT(orderID) FROM cm_order WHERE clubID = #{clubID} AND orderTime <![CDATA[ < ]]> now()) AS orderTotal,
+                (SELECT SUM(payTotalFee) FROM cm_order WHERE clubID = #{clubID} AND orderTime <![CDATA[ < ]]> now()) AS orderTotalAmount,
+                (SELECT COUNT(cbr.recordID) FROM cm_behavior_record cbr LEFT JOIN club c ON cbr.userID = c.userID WHERE cbr.pageType IN (8, 9) AND c.clubID = #{clubID} AND cbr.accessDate <![CDATA[ < ]]> now()) AS totalkeywords ,
+                (SELECT COUNT(remarks) FROM cm_club_remarks WHERE clubID = #{clubID} AND addTime <![CDATA[ < ]]> now()) AS remarksTotal
+    </select>
+    <select id="selOrderList" resultType="com.caimei.modules.order.entity.NewOrder">
+        SELECT
+               (SELECT COUNT(orderID) FROM cm_order WHERE clubID = #{clubID}) as numbers,
+                (SELECT SUM(payTotalFee) FROM cm_order WHERE clubID = #{clubID}) as totalMoney,
+               clubID,
+               secondHandOrderFlag,
+               rebateFlag,
+               refundType,
+               productTotalFee,
+               STATUS,
+               orderTime
+        FROM cm_order
+        <where>
+             clubID = #{clubID}
+             <if test="accessDate != null and accessDate != ''">
+                 AND orderTime like concat('%',#{accessDate},'%')
+             </if>
+             <if test="startTime != null and startTime != '' and endTime != null and endTime != ''">
+                 AND orderTime <![CDATA[ >= ]]> #{startTime} AND orderTime <![CDATA[ <= ]]> #{endTime}
+             </if>
+        </where>
+    </select>
+
+    <select id="selBehaviorList" resultType="com.caimei.modules.user.entity.CmBehaviorRecord">
+        SELECT
+               c.clubID,
+               COUNT(cbr.pageLabel) as number,
+               cbr.pageLabel,
+               cbr.accessDate
+        FROM cm_behavior_record cbr LEFT JOIN club c ON cbr.userID = c.userID
+        <where>
+            cbr.pageType IN (8, 9) AND c.clubID = #{clubID}
+            <if test="accessDate != null and accessDate != ''">
+                AND cbr.accessDate = #{accessDate}
+            </if>
+            <if test="startTime != null and startTime != '' and endTime != null and endTime != ''">
+                AND cbr.accessDate between #{startTime} and #{endTime}
+            </if>
+        </where>
+        GROUP BY cbr.pageLabel
+        ORDER BY COUNT(cbr.pageLabel) LIMIT 10
+    </select>
+
+    <select id="selRemarksList" resultType="com.caimei.modules.user.entity.CmClubRemarks">
+        SELECT
+            (SELECT COUNT(remarks) FROM cm_club_remarks WHERE clubID = #{clubID}) as numbers,
+               clubID,
+               COUNT(remarks) as number,
+               remarks,
+               addTime
+        FROM cm_club_remarks
+        <where>
+            clubID = #{clubID}
+            <if test="accessDate != null and accessDate != ''">
+                AND addTime like concat('%', #{accessDate},'%')
+            </if>
+            <if test="startTime != null and startTime != '' and endTime != null and endTime != ''">
+                AND addTime between #{startTime} and #{endTime}
+            </if>
+        </where>
+        GROUP BY remarks ORDER BY COUNT(remarks) LIMIT 10
+    </select>
+
+    <select id="selBehaviorPageTypeList" resultType="com.caimei.modules.user.entity.CmBehaviorRecord">
+        SELECT
+               c.clubID,
+               COUNT(cbr.pageType) as numbers,
+               cpt.pageType,
+               cbr.accessDate
+        FROM cm_behavior_record cbr
+        LEFT JOIN club c ON cbr.userID = c.userID
+        LEFT JOIN cm_page_type cpt ON cbr.pageType = cpt.id
+        <where>
+                c.clubID = #{clubID}
+            <if test="accessDate != null and accessDate != ''">
+                AND cbr.accessDate like concat('%', #{accessDate},'%')
+            </if>
+            <if test="startTime != null and startTime != '' and endTime != null and endTime != ''">
+                AND cbr.accessDate between #{startTime} and #{endTime}
+            </if>
+        </where>
+        GROUP BY cbr.pageType  ORDER BY COUNT(cbr.pageType) LIMIT 10
+    </select>
+</mapper>

+ 7 - 0
src/main/webapp/WEB-INF/views/modules/user/behaviorRecordList.jsp

@@ -73,6 +73,7 @@
                    value="${cmBehaviorRecord.endTime}"
                    onclick="WdatePicker({dateFmt:'yyyy-MM-dd',isShowClear:false});"/>
             <input id="btnSubmit" class="btn btn-primary" type="submit" value="查询"/>
+            <input id="export" class="btn btn-primary" type="button" value="导出"/>
         </div>
         <div class="clearfix"></div>
     </div>
@@ -175,6 +176,12 @@
         $("#searchForm").submit();
         return false;
     }
+    $(function () {
+        $('#export').click(function () {
+            var formData = $('#searchForm').serialize();
+            window.location.href = "${ctx}/user/behavior/record/export?behaviorType=1&" + formData;
+        })
+    })
 </script>
 </body>
 

+ 7 - 0
src/main/webapp/WEB-INF/views/modules/user/behaviorRecordRossList.jsp

@@ -73,6 +73,7 @@
                    value="${cmBehaviorRecord.endTime}"
                    onclick="WdatePicker({dateFmt:'yyyy-MM-dd',isShowClear:false});"/>
             <input id="btnSubmit" class="btn btn-primary" type="submit" value="查询"/>
+            <input id="export" class="btn btn-primary" type="button" value="导出"/>
         </div>
         <div class="clearfix"></div>
     </div>
@@ -190,6 +191,12 @@
         $("#searchForm").submit();
         return false;
     }
+    $(function () {
+        $('#export').click(function () {
+            var formData = $('#searchForm').serialize();
+            window.location.href = "${ctx}/user/behavior/record/export?behaviorType=2&" + formData;
+        });
+    })
 </script>
 </body>
 

+ 10 - 3
src/main/webapp/WEB-INF/views/modules/userNew/cmAgencyList.jsp

@@ -59,6 +59,10 @@
     <input id="pageNo" name="pageNo" type="hidden" value="${page.pageNo}"/>
     <input id="pageSize" name="pageSize" type="hidden" value="${page.pageSize}"/>
     <div class="flex-wrap">
+        <div class="item">
+            <label>机构ID:</label>
+            <form:input path="clubID"  htmlEscape="false" maxlength="50" class="input-medium"/>
+        </div>
         <div class="item">
             <label>机构名称:</label>
             <form:input path="searchName"  htmlEscape="false" maxlength="50" class="input-medium"/>
@@ -145,6 +149,7 @@
 <table id="contentTable" class="table table-striped table-bordered table-condensed">
     <thead>
     <tr>
+        <th>机构ID</th>
         <th>机构名称</th>
         <th>机构简称</th>
         <th>联系人</th>
@@ -167,6 +172,7 @@
     <tbody>
     <c:forEach items="${page.list}" var="newCmClubList">
         <tr>
+            <td>${newCmClubList.clubID}</td>
             <td>
 <%--                <c:if test="${newCmClubList.userIdentity eq 2}">--%>
                     ${newCmClubList.name}
@@ -289,6 +295,7 @@
                     ${newCmClubList.auditTime}
             </td>
             <td>
+                <a href="${ctx}/new/user/agency/clubPortrait?clubID=${newCmClubList.clubID}&clubName=${newCmClubList.name}&dateType=0&type=4">机构画像</a>
                 <shiro:hasPermission name="club:cmAgency:edit">
                     <a href="${ctx}/new/user/agency/form?id=${newCmClubList.clubID}&source=1&searchName=${newCmClub.searchName}&searchUserName=${newCmClub.searchUserName}&searchBindMobile=${newCmClub.searchBindMobile}&searchEmail=${newCmClub.searchEmail}&searchUserOrganizeID=${newCmClub.searchUserOrganizeID}&searchStatus=${newCmClub.searchStatus}&searchUserIdentity=${newCmClub.searchUserIdentity}&searchStartTime=${newCmClub.searchStartTime}&searchEndTime=${newCmClub.searchEndTime}">编辑</a>
                 </shiro:hasPermission>
@@ -318,9 +325,9 @@
                         <a href="${ctx}/user/clubTemporary/confirmRecord?confirmUserId=${newCmClubList.userID}">确认记录</a>
                     </shiro:hasPermission>
                 </c:if>
-                <shiro:hasPermission name="club:cmAgency:remarks">
-                    <a href="${ctx}/new/user/agency/remarks?clubId=${newCmClubList.clubID}">咨询记录</a>
-                </shiro:hasPermission>
+                <%--<shiro:hasPermission name="club:cmAgency:remarks">
+                    <a style="visibility: hidden" href="${ctx}/new/user/agency/remarks?clubId=${newCmClubList.clubID}">咨询记录</a>
+                </shiro:hasPermission>--%>
                 <a href="${ctx}/new/user/agency/recordLinkage?clubId=${newCmClubList.clubID}">生成行为记录链接</a>
             </td>
         </tr>

+ 421 - 0
src/main/webapp/WEB-INF/views/modules/userNew/cmClubData.jsp

@@ -0,0 +1,421 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/WEB-INF/views/include/taglib.jsp" %>
+<html>
+<head>
+    <title>机构资料</title>
+    <meta name="decorator" content="default"/>
+    <script src="/static/modules/bulkpurchase/loadAddressById.js"></script>
+    <script type="text/javascript">
+
+    </script>
+    <style>
+        #auditBox {
+            padding: 20px;
+            line-height: 30px;
+        }
+
+        #auditBox .bd-row {
+            display: flex;
+            margin-bottom: 15px;
+        }
+
+        #auditBox .bd-row > span {
+            display: inline-block;
+            width: 60px;
+        }
+
+        #auditBox .auditCheckBox {
+            width: 250px;
+        }
+
+        #auditBox .auditCheckBox label {
+            margin: 0 5px 5px 0
+        }
+
+        #auditBox .auditCheckBox input {
+            display: none;
+        }
+
+        #auditBox .auditCheckBox input + span {
+            display: inline-block;
+            line-height: 24px;
+            padding: 0 12px;
+            border: 1px solid #666;
+            border-radius: 5px;
+        }
+
+        #auditBox .auditCheckBox input:checked + span {
+            background-color: #E6633A
+        }
+
+        .detailTitle {
+            margin: 16px 0px 4px 20px;
+            font-weight: bold;
+        }
+
+        .detailLine {
+            width: 98%;
+            margin-left: 10px;
+        }
+
+        .clubInfo {
+            float: left;
+            width: 25%;
+        }
+
+        .clubInfoTitle {
+            text-align: center;
+            text-decoration: underline;
+            font-weight: bold;
+        }
+
+        th {
+            text-align: right;
+            white-space: nowrap;
+        }
+
+        td {
+            padding: 5px 0;
+        }
+
+        #headpicPreview li, #businessLicenseImagePreview li {
+            min-height: 100px;
+        }
+
+        /*----------------------------------*/
+        .the-oradio {
+            display: inline-block;
+            vertical-align: top;
+        }
+
+        .the-oradio div {
+            width: 85px;
+            display: inline-block;
+            font-size: 12px;
+            color: #666;
+        }
+
+        .med-option {
+            display: block;
+            margin: 10px 0 0 160px;
+        }
+
+        .raw-option {
+            display: block;
+            margin: 10px 0 0 160px;
+        }
+
+        .control-group .new-tag {
+            display: inline-block;
+            width: 78px;
+            height: 30px;
+            border: 1px solid #e5e5e5;
+            border-radius: 5px;
+            margin: 7px;
+            text-align: center;
+            line-height: 30px;
+            font-size: 14px;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+            cursor: pointer;
+        }
+
+        .control-group .new-tag.active {
+            border-color: #e15616;
+            color: #e15616;
+        }
+
+        #clubArea {
+            display: inline-block;
+            width: 450px;
+        }
+
+        #clubOther {
+            height: 40px;
+            line-height: 40px;
+            vertical-align: middle
+        }
+
+        #clubInput {
+            width: 159px;
+            margin: 7px;
+            display: inline-block;
+            height: 30px;
+            display: none;
+        }
+
+        .tags-operate {
+            margin-left: 160px;
+        }
+
+        .control-group .tags-operate .tag-add {
+            height: 40px;
+            line-height: 40px;
+            vertical-align: middle;
+            display: none;
+        }
+
+        .top-label {
+            width: 160px;
+            text-align: right;
+            vertical-align: top;
+            margin-top: 10px;
+        }
+    </style>
+</head>
+<body>
+<ul class="nav nav-tabs">
+    <li><a href="${ctx}/new/user/agency/">机构列表</a></li>
+    <li class="active"><a href="${ctx}/new/user/agency/clubPortrait?clubID=${newCmClub.clubID}">机构画像</a></li>
+</ul>
+<div class="ul-form">
+    <ul class="nav nav-tabs">
+        <li><a href="${ctx}/new/user/agency/clubPortrait?clubID=${newCmClub.clubID}">仪表盘</a></li>
+        <li class="active"><a href="${ctx}/new/user/agency/clubData?clubID=${newCmClub.clubID}">机构信息</a></li>
+    </ul>
+</div>
+<form:form id="inputForm" modelAttribute="cmClubinfo" action="#" method="post"
+           class="form-horizontal">
+<form:hidden path="id" value="${newCmClub.clubID}"/>
+<form:hidden path="clubInfoID"/>
+<form:hidden path="userID"/>
+<form:hidden path="clubID"/>
+<div style="max-width:1200px;padding:15px;">
+    <table border="0" cellspacing="0" cellpadding="0" width="100%">
+        <tr height="28">
+            <th width="12%">状态:</th>
+            <td width="13%">${fns:getDictLabel(newCmClub.status, 'club_status', newCmClub.status)}</td>
+            <th width="12%">注册时间:</th>
+            <td width="13%"><fmt:formatDate value="${newCmClub.registerTime}" pattern="yyyy-MM-dd HH:mm:ss"></fmt:formatDate></td>
+        </tr>
+        <tr height="28">
+            <th width="12%">机构名称:</th>
+            <td width="13%">${newCmClub.name}
+            <th width="12%">机构简称:</th>
+            <td width="13%">${newCmClub.sname}
+            <th width="12%">注册邮箱:</th>
+            <td width="13%">${newCmClub.contractEmail}
+        </tr>
+        <tr height="28">
+            <th width="12%">联系人:</th>
+            <td width="13%">${newCmClub.userName}
+            </td>
+            <th width="12%">手机号:</th>
+            <td width="13%">${newCmClub.bindMobile}
+            <th width="12%">联系人身份:</th>
+            <td width="13%">
+                <c:if test="${newCmClub.linkManIdentity eq '1'}">老板</c:if>
+                <c:if test="${newCmClub.linkManIdentity eq '2'}">采购</c:if>
+                <c:if test="${newCmClub.linkManIdentity eq '3'}">运营</c:if>
+            </td>
+        </tr>
+    </table>
+</div>
+
+<sys:message content="${message}"/>
+<hr class="detailLine">
+<div>
+    <table border="0" cellspacing="0" cellpadding="0" width="100%">
+        <tr>
+            <td colspan="2">
+                <div class="control-group">
+                    <label class="control-label"><b>地址:</b></label>
+                    <span  id="curProvince" name="curProvince" >${newCmClub.province }</span>
+                    <span  id="curCity" name="curCity" >${newCmClub.province }</span>
+                    <span  id="curTown" name="curTown" >${newCmClub.town }</span>
+                        ${newCmClub.address}
+                    <%--<div class="controls">
+                        <form:select path="provinceID" disabled="true" class="input-xlarge" id="province"
+                                     onchange="loadCity()" style="width:100px;">
+                            <form:option value="" label="省" provinceId=""/>
+                        </form:select>
+                        <form:select path="cityID" disabled="true" class="input-xlarge" id="city" onchange="loadTown()"
+                                     style="width:100px;">
+                            <form:option value="" label="市" cityId=""/>
+                        </form:select>
+                        <form:select path="townID" disabled="true" class="input-xlarge" id="town" style="width:100px;">
+                            <form:option value="" label="区"/>
+                        </form:select>
+                            ${newCmClub.address}
+                    </div>--%>
+                </div>
+            </td>
+        </tr>
+        <tr>
+            <td colspan="2">
+                <div class="control-group">
+                    <label class="control-label"><b>营业执照编号:</b></label>
+                    <div class="controls">${newCmClub.socialCreditCode}</div>
+                </div>
+            </td>
+        </tr>
+        <tr>
+            <td>
+                <div class="control-group">
+                    <label class="control-label"><b>营业执照:</b></label>
+                    <img width="100" height="100" src="${newCmClub.businessLicenseImage}">
+                </div>
+            </td>
+            <td>
+                <div class="control-group">
+                    <label class="control-label"><b>门头照:</b></label>
+                    <img width="100" height="100" src="${newCmClub.headpic}">
+                </div>
+            </td>
+        </tr>
+        <tr>
+            <td>
+                <div class="control-group">
+                    <label class="control-label" for=""><b>机构类型:</b></label>
+                    <div class="medical-radio the-oradio">
+                        <input value="${cmClubinfo.firstClubType}" class="hide" type="text" id="firstClubType"/>
+                        <div class="med-beauty">
+                            <c:if test="${cmClubinfo.firstClubType == '1'}">医美</c:if>
+                            <c:if test="${cmClubinfo.firstClubType == '2'}">生美</c:if>
+                            <c:if test="${cmClubinfo.firstClubType == '3'}">项目公司</c:if>
+                            <c:if test="${cmClubinfo.firstClubType == '4'}">个人</c:if>
+                            <c:if test="${cmClubinfo.firstClubType == '5'}">其他</c:if>
+
+                            <c:if test="${cmClubinfo.secondClubType eq '1'}"> - 诊所</c:if>
+                            <c:if test="${cmClubinfo.secondClubType eq '2'}"> - 门诊</c:if>
+                            <c:if test="${cmClubinfo.secondClubType eq '3'}"> - 医院</c:if>
+                            <c:if test="${cmClubinfo.secondClubType eq '4'}"> - 其他</c:if>
+                            <c:if test="${cmClubinfo.secondClubType eq '5'}"> - 美容院</c:if>
+                            <c:if test="${cmClubinfo.secondClubType eq '6'}"> - 养生馆</c:if>
+                            <c:if test="${cmClubinfo.secondClubType eq '7'}"> - 其他</c:if>
+                        </div>
+
+                    </div>
+
+                    <div class="qualification control-group" style="display: none">
+                        <label class="control-label"><b>医疗许可证:</b></label>
+                        <img width="100" height="100" src="${cmClubinfo.medicalPracticeLicenseImg}">
+
+                    </div>
+                </div>
+                <div class="control-group epart" style="display: none">
+                    <label class="control-label"><b>科室:</b></label>
+                    <input class="reg-input" type="text" name="department" id="Department"
+                           placeholder="请填写您的所经营的科室,用逗号隔开。(至少三个)" value="${cmClubinfo.department}"
+                           style="margin-left: 10px;"/>
+                    <span class="err-tip"></span>
+                </div>
+                <div class="control-group" >
+                    <label class="control-label"><b>主营内容:</b></label>
+                    <font size="3">${cmClubinfo.mainpro}</font>
+                </div>
+            </td>
+        </tr>
+        <tr>
+            <td>
+                <div class="control-group">
+                    <label class="control-label"><b>固定电话:</b></label>
+                    <div class="controls">${cmClubinfo.contractPhone}</div>
+                </div>
+            </td>
+            <td>
+                <div class="control-group">
+                    <label class="control-label"><b>传真:</b></label>
+                    <div class="controls">${cmClubinfo.fax}</div>
+                </div>
+            </td>
+        </tr>
+        <tr>
+            <td colspan="2">
+                <div class="control-group">
+                    <label class="control-label"><b>员工人数:</b></label>
+                    <div class="controls">${cmClubinfo.empnum}</div>
+                </div>
+            </td>
+        </tr>
+        <tr>
+            <td colspan="2">
+                <div class="control-group">
+                    <label class="control-label"><b>公司简介:</b></label>
+                    <div class="controls">${cmClubinfo.info}</div>
+                </div>
+            </td>
+        </tr>
+    </table>
+    <div style="visibility: hidden;">
+        <div class="clubInfo">
+            <div class="clubInfoTitle">基本信息</div>
+            <table border="0" cellspacing="0" cellpadding="0" width="100%">
+                <tr height="28">
+                    <th>机构面积:</th>
+                    <td>${cmClubinfo.area}</td>
+                </tr>
+                <tr height="28">
+                    <th>美容床数:</th>
+                    <td>${cmClubinfo.bedNums}</td>
+                </tr>
+                <tr height="28">
+                    <th>美容师数:</th>
+                    <td>${cmClubinfo.beauticians}</td>
+                </tr>
+            </table>
+        </div>
+        <div class="clubInfo">
+            <div class="clubInfoTitle">业绩信息</div>
+            <table border="0" cellspacing="0" cellpadding="0" width="100%">
+                <tr height="28">
+                    <th>月业绩:</th>
+                    <td>${cmClubinfo.monthAchievement}</td>
+                </tr>
+                <tr height="28">
+                    <th>促销业绩:</th>
+                    <td>${cmClubinfo.promotionAchievement}</td>
+                </tr>
+                <tr height="28">
+                    <th>年业绩:</th>
+                    <td>${cmClubinfo.yearAchievement}</td>
+                </tr>
+            </table>
+        </div>
+        <div class="clubInfo">
+            <div class="clubInfoTitle">会员信息及消费情况</div>
+            <table border="0" cellspacing="0" cellpadding="0" width="100%">
+                <tr height="28">
+                    <th>A类会员:</th>
+                    <td colspan="3" style="padding-top: 6px;">${cmClubinfo.cateA}人&nbsp;</td>
+                </tr>
+                <tr height="28">
+                    <th>B类会员:</th>
+                    <td colspan="3" style="padding-top: 6px;">${cmClubinfo.cateB}人&nbsp;</td>
+                </tr>
+                <tr height="28">
+                    <th>C类会员:</th>
+                    <td colspan="3" style="padding-top: 6px;">${cmClubinfo.cateC}人&nbsp;</td>
+                </tr>
+            </table>
+        </div>
+        <div class="clubInfo">
+            <div class="clubInfoTitle">活动业绩</div>
+            <table border="0" cellspacing="0" cellpadding="0" width="100%">
+                <tr height="28">
+                    <th>最高业绩:</th>
+                    <td>${cmClubinfo.highestAchievement}</td>
+                </tr>
+                <tr height="28">
+                    <th>到店人数:</th>
+                    <td>${cmClubinfo.reachPepole}</td>
+                </tr>
+                <tr height="28">
+                    <th>成交人数:</th>
+                    <td>${cmClubinfo.clinchPepole}</td>
+                </tr>
+            </table>
+        </div>
+        <table border="0" cellspacing="0" cellpadding="0" width="100%">
+            <tr height="28">
+                <th>店内所经营品牌及推广优势:</th>
+                <td colspan="10" width="25%">${cmClubinfo.brandSuperiority}</td>
+                <th>临近一次促销的模式及达成业绩:</th>
+                <td colspan="10" width="25%">${cmClubinfo.lastPromotion}</td>
+            </tr>
+        </table>
+    </div>
+    </form:form>
+</body>
+</html>

+ 157 - 0
src/main/webapp/WEB-INF/views/modules/userNew/cmClubPortrait.jsp

@@ -0,0 +1,157 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/WEB-INF/views/include/taglib.jsp"%>
+<html>
+<head>
+    <title>机构画像</title>
+    <meta name="decorator" content="default"/>
+    <link href="${ctxStatic}/datapicker/daterangepicker.css" rel="stylesheet">
+    <link href="${ctxStatic}/modules/cmClubPortrait/cmClubPortrait.css" rel="stylesheet">
+</head>
+<body>
+<ul class="nav nav-tabs">
+    <li><a href="${ctx}/new/user/agency/">机构列表</a></li>
+    <li class="active"><a href="${ctx}/new/user/agency/clubPortrait?clubID=${cmPortrait.clubID}&clubName=${cmPortrait.clubName}&dateType=0&type=4">机构画像</a></li>
+</ul>
+<div class="ul-form">
+    <input type="hidden" id="clubId" value="${cmPortrait.clubID}">
+    <input type="hidden" id="eachtsAjaxUrl" value="${ctx}/new/user/agency/selPortraitData">
+    <ul class="nav nav-tabs">
+        <li class="active"><a href="${ctx}/new/user/agency/clubPortrait?clubID=${cmPortrait.clubID}&clubName=${cmPortrait.clubName}&dateType=0&type=4">仪表盘</a></li>
+        <li><a href="${ctx}/new/user/agency/clubData?clubID=${cmPortrait.clubID}">机构资料</a></li>
+    </ul>
+    <div class="main-content">
+        <div class="flex-content">
+            <div class="flex-box">
+                <div class="box-title">
+                    <span>订单总量:<a class="line" href="${ctx}/order/orderList?buyer=${cmPortrait.clubName}"><c:if test="${!empty portrait.orderTotal}">${portrait.orderTotal}</c:if><c:if test="${empty portrait.orderTotal}">0</c:if> 个</a></span>
+                    <span>购买总额:<a href="javascript: void(0);">¥<c:if test="${!empty portrait.orderTotalAmount}">${portrait.orderTotalAmount}</c:if><c:if test="${empty portrait.orderTotalAmount}">0</c:if></a></span>
+                </div>
+                <div class="box-tabmain">
+                    <div class="box-tabs" id="orderTabs">
+                        <a class="box-tabs-li active" href="javascript: void(0);" data-type="1">日</a>
+                        <a class="box-tabs-li" href="javascript: void(0);" data-type="2">月</a>
+                        <a class="box-tabs-li" href="javascript: void(0);" data-type="3">半年</a>
+                        <a class="box-tabs-li" href="javascript: void(0);" data-type="4">全年</a>
+                    </div>
+                    <div class="box-time" id="orderDate">
+                        <div class="time-input">
+                            <input type="text" placeholder="开始时间" class="input start" id="orderTimeStart">
+                        </div>
+                        <span class="line">至</span>
+                        <div class="time-input">
+                            <input type="text" placeholder="结束时间" class="input end" id="orderTimeEnd">
+                        </div>
+                    </div>
+                </div>
+                <div class="box-eachts">
+                    <div class="eachts-total">订单数:<span id="orderTotalNum"></span></div>
+                    <div class="eachts-data" id="orderEacths" style="">
+                        <!-- orderEacths表 -->
+                    </div>
+                    <div class="eachts-none" id="orderEacthsNone">
+                        <p>暂无数据</p>
+                    </div>
+                </div>
+            </div>
+            <div class="flex-box">
+                <div class="box-title">
+                    <span>搜索关键词总数:<em><c:if test="${!empty portrait.totalkeywords}">${portrait.totalkeywords}</c:if><c:if test="${empty portrait.totalkeywords}">0</c:if> 条</em></span>
+                </div>
+                <div class="box-tabmain">
+                    <div class="box-tabs" id="keyWordTabs">
+                        <a class="box-tabs-li active" href="javascript: void(0);" data-type="1">日</a>
+                        <a class="box-tabs-li" href="javascript: void(0);" data-type="2">月</a>
+                        <a class="box-tabs-li" href="javascript: void(0);" data-type="3">半年</a>
+                        <a class="box-tabs-li" href="javascript: void(0);" data-type="4">全年</a>
+                    </div>
+                    <div class="box-time" id="keyWordsDate">
+                        <div class="time-input">
+                            <input type="text" placeholder="开始时间" class="input start" id="keyWordsTimeStart">
+                        </div>
+                        <span class="line">至</span>
+                        <div class="time-input">
+                            <input type="text" placeholder="结束时间" class="input end" id="keyWordsTimeEnd">
+                        </div>
+                    </div>
+                </div>
+                <div class="box-eachts">
+                    <div class="eachts-data" id="keyWordsEacths" style="">
+                        <!-- keyWordsEacths表 -->
+                    </div>
+                    <div class="eachts-none" id="keyWordsEacthsNone">
+                        <p>暂无数据</p>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="flex-content">
+            <div class="flex-box">
+                <div class="box-title">
+                    <span>咨询记录总数:<a class="line" href="${ctx}/new/user/agency/regist?clubName=${cmPortrait.clubName}"><c:if test="${!empty portrait.remarksTotal}">${portrait.remarksTotal}</c:if><c:if test="${empty portrait.remarksTotal}">0</c:if> 条</a></span>
+                </div>
+                <div class="box-tabmain">
+                    <div class="box-tabs" id="serviceTabs">
+                        <a class="box-tabs-li active" href="javascript: void(0);" data-type="1">日</a>
+                        <a class="box-tabs-li" href="javascript: void(0);" data-type="2">月</a>
+                        <a class="box-tabs-li" href="javascript: void(0);" data-type="3">半年</a>
+                        <a class="box-tabs-li" href="javascript: void(0);" data-type="4">全年</a>
+                    </div>
+                    <div class="box-time" id="serviceDate">
+                        <div class="time-input">
+                            <input type="text" placeholder="开始时间" class="input start" id="serviceTimeStart">
+                        </div>
+                        <span class="line">至</span>
+                        <div class="time-input">
+                            <input type="text" placeholder="结束时间" class="input end" id="serviceTimeEnd">
+                        </div>
+                    </div>
+                </div>
+                <div class="box-eachts">
+                    <div class="eachts-data" id="serviceEacths" style="">
+                        <!-- serviceEacths表 -->
+                    </div>
+                    <div class="eachts-none" id="serviceEacthsNone">
+                        <p>暂无数据</p>
+                    </div>
+                </div>
+            </div>
+            <div class="flex-box">
+                <div class="box-title">
+                    <span>访问记录</span>
+                </div>
+                <div class="box-tabmain">
+                    <div class="box-tabs" id="visitTabs">
+                        <a class="box-tabs-li active" href="javascript: void(0);" data-type="1">日</a>
+                        <a class="box-tabs-li" href="javascript: void(0);" data-type="2">月</a>
+                        <a class="box-tabs-li" href="javascript: void(0);" data-type="3">半年</a>
+                        <a class="box-tabs-li" href="javascript: void(0);" data-type="4">全年</a>
+                    </div>
+                    <div class="box-time" id="visitDate">
+                        <div class="time-input">
+                            <input type="text" placeholder="开始时间" class="input start" id="visitTimeStart">
+                        </div>
+                        <span class="line">至</span>
+                        <div class="time-input">
+                            <input type="text" placeholder="结束时间" class="input end" id="visitTimeEnd">
+                        </div>
+                    </div>
+                </div>
+                <div class="box-eachts">
+                    <div class="eachts-data" id="visitEacths" style="">
+                        <!-- visitEacths表 -->
+                    </div>
+                    <div class="eachts-none" id="visitEacthsNone">
+                        <p>暂无数据</p>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<script type="text/javascript" src="${ctxStatic}/datapicker/moment-2.29.min.js"></script>
+<script type="text/javascript" src="${ctxStatic}/datapicker/jquery.daterangepicker.js"></script>
+<script type="text/javascript" src="${ctxStatic}/echarts/echarts.min.js"></script>
+<script type="text/javascript" src="${ctxStatic}/modules/cmClubPortrait/cmClubEacths.js"></script>
+<script type="text/javascript" src="${ctxStatic}/modules/cmClubPortrait/cmClubPortrait.js"></script>
+</body>
+</html>

+ 90 - 0
src/main/webapp/static/datapicker/daterangepicker.css

@@ -0,0 +1,90 @@
+.date-picker{width:170px;height:25px;padding:0;border:0;line-height:25px;padding-left:10px;font-size:12px;font-family:Arial,sans-serif;font-weight:bold;cursor:pointer;color:#303030;position:relative;z-index:2;}
+.date-picker-wrapper{position:absolute;z-index:1;border:1px solid #bfbfbf;background-color:#efefef;font-size:12px;line-height:20px;color:#aaa;font-family:Arial,sans-serif;-webkit-box-shadow:3px 3px 10px rgba(0,0,0,0.5);box-shadow:3px 3px 10px rgba(0,0,0,0.5);-webkit-box-sizing:initial;box-sizing:initial;}
+.dp-clearfix{clear:both;height:0;font-size:0;}
+.date-picker-wrapper.inline-wrapper{position:relative;-webkit-box-shadow:none;box-shadow:none;display:inline-block;}
+.date-picker-wrapper table tr{background:none;}
+.date-picker-wrapper .drp_top-icon{position:absolute;left:60px;top:-9px;width:20px;height:10px;}
+.date-picker-wrapper .drp_top-icon:before{content:"";width:0;height:0;border-style:solid;border-width:0 10px 10px 10px;border-color:transparent transparent #ccc transparent;position:absolute;left:0;top:-2px;}
+.date-picker-wrapper .drp_top-icon:after{content:"";width:0;height:0;border-style:solid;border-width:0 10px 10px 10px;border-color:transparent transparent #fff transparent;position:absolute;left:0;top:2px;}
+.date-picker-wrapper.single-date{width:auto;}
+.date-picker-wrapper .footer{font-size:11px;padding-top:3px;}
+.date-picker-wrapper b{color:#666;font-weight:700;}
+.date-picker-wrapper a{color:#6bb4d6;text-decoration:underline;}
+.date-picker-wrapper .month-name{text-transform:uppercase;color:#000;cursor:default;font-size:18px;}
+.date-picker-wrapper .select-wrapper{position:relative;overflow:hidden;display:inline-block;vertical-align:middle;}
+.date-picker-wrapper .select-wrapper:hover{text-decoration:underline;}
+.date-picker-wrapper .month-element{display:inline-block;vertical-align:middle;}
+.date-picker-wrapper .select-wrapper select{position:absolute;margin:0;padding:0;left:0;top:-1px;font-size:inherit;font-style:inherit;font-weight:inherit;text-transform:inherit;color:inherit;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:0;outline:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=1)";filter:alpha(opacity=1);opacity:0.01;}
+.date-picker-wrapper .month-wrapper table th{margin:0px;padding:0px;line-height:30px;height:30px;text-align:center;width:38px;}
+.date-picker-wrapper .month-wrapper table td{vertical-align:middle;text-align:center;line-height:14px;margin:0px;padding:0px;}
+.date-picker-wrapper .month-wrapper table .week-name{height:20px;line-height:20px;font-weight:100;text-transform:uppercase;}
+.date-picker-wrapper .month-wrapper table .day{line-height:36px;height:36px;text-align:center;cursor:default;width:36px;float:left;color:#333;background:#ececec;margin:1px;}
+.date-picker-wrapper .month-wrapper table .day.invalid{background:#f7f7f7;cursor:default;color:#DBDBDB;}
+.date-picker-wrapper .month-wrapper table .day.valid:hover{box-shadow:0 0 5px #e15616 inset;}
+.date-picker-wrapper .month-wrapper table div.day.lastMonth,.date-picker-wrapper .month-wrapper table div.day.nextMonth{color:#999;cursor:default;}
+.date-picker-wrapper .month-wrapper table .day.has-tooltip{cursor:help!important;}
+.date-picker-wrapper .month-wrapper table .day.has-tooltip .tooltip{white-space:nowrap;}
+.date-picker-wrapper .time label{white-space:nowrap;}
+.date-picker-wrapper .month-wrapper table .day.toMonth.valid{color:#333;cursor:pointer;}
+.date-picker-wrapper .month-wrapper table .day.toMonth.hovering{background-color:#f5ded4;}
+.date-picker-wrapper .month-wrapper table .day.nextMonth,.date-picker-wrapper .month-wrapper table .day.lastMonth{display:none;}
+.date-picker-wrapper .month-wrapper table .day.real-today{background-color:#f5ded4;}
+.date-picker-wrapper .month-wrapper table .day.real-today.checked,.date-picker-wrapper .month-wrapper table .day.real-today.hovering{background-color:#FFB496;}
+.date-picker-wrapper .month-wrapper table .day.checked{background:#ffe6dc;cursor:pointer;color:#543376;}
+.date-picker-wrapper .month-wrapper table .day.checked.first-date-selected,.date-picker-wrapper .month-wrapper table .day.checked.last-date-selected{background:#e15616;color:#fff;position:relative;}
+.date-picker-wrapper.single-date .month-wrapper table .day.checked.last-date-selected{background:#ffe6dc;color:#fff;position:relative;}
+.date-picker-wrapper .month-wrapper table .day.checked.first-date-selected:after{width:0;height:0;border-style:solid;border-width:18px 0 18px 10px;border-color:#ffe6dc transparent #ffe6dc #e15616;content:"";position:absolute;right:0;top:0;}
+.date-picker-wrapper.single-date .month-wrapper table .day.checked.first-date-selected:after{width:0;height:0;border-style:solid;border-width:0 0 0 0;border-color:#ffe6dc #ffe6dc #ffe6dc #ffe6dc;content:"";position:absolute;right:0;top:0;}
+.date-picker-wrapper .month-wrapper table .day.checked.last-date-selected:before{width:0;height:0;border-style:solid;border-width:18px 10px 18px 0;border-color:#ffe6dc transparent #ffe6dc #e15616;content:"";position:absolute;left:0;top:0;}
+.date-picker-wrapper table .caption{box-sizing:border-box;height:40px;padding:5px 0;}
+.date-picker-wrapper table .caption .next,.date-picker-wrapper table .caption .prev{cursor:pointer;background:#e15616;width:30px;height:28px;line-height:28px;font-size:20px;text-align:center;font-weight:normal;display:inline-block;color:transparent;vertical-align:top;}
+.date-picker-wrapper table .caption .prev:before,.date-picker-wrapper table .caption .next:before{display:inline-block;width:100%;text-align:center;vertical-align:top;color:#FFF;}
+.date-picker-wrapper table .caption .prev:before{content:'\276E';}
+.date-picker-wrapper table .caption .next:before{content:'\276F';}
+.date-picker-wrapper table .caption .next.disabled, .date-picker-wrapper table .caption .prev.disabled {background:#bdbdbd;}
+.date-picker-wrapper .gap{display:none;}
+.date-picker-wrapper .selected-days{display:none;}
+.date-picker-wrapper .drp_top-bar{line-height:1.4;position:relative;padding:10px 40px 10px 0;}
+.date-picker-wrapper .drp_top-bar .error-top,.date-picker-wrapper .drp_top-bar .normal-top{display:none;}
+.date-picker-wrapper .drp_top-bar .default-top{display:none;}
+.date-picker-wrapper .drp_top-bar.error .default-top{display:none;}
+.date-picker-wrapper .drp_top-bar.error .error-top{display:block;color:red;}
+.date-picker-wrapper .drp_top-bar.normal .default-top{display:none;}
+.date-picker-wrapper .drp_top-bar.normal .normal-top{display:block;}
+.date-picker-wrapper .drp_top-bar.normal .normal-top .selection-top{color:#333;}
+/*time styling*/
+.date-picker-wrapper .time{position:relative;}
+.date-picker-wrapper.single-month .time{display:block;}
+.date-picker-wrapper .time input[type=range]{vertical-align:middle;width:129px;padding:0;margin:0;height:20px;}
+.date-picker-wrapper .time1,.date-picker-wrapper .time2{width:180px;padding:0 5px;text-align:center;}
+.date-picker-wrapper .time1{float:left;}
+.date-picker-wrapper .time2{float:right;}
+.date-picker-wrapper .hour,.date-picker-wrapper .minute{text-align:right;}
+.date-picker-wrapper .hide{display:none;}
+.date-picker-wrapper .drp_top-bar .apply-btn{position:absolute;right:0px;top:10px;width:60px;height:30px;line-height:28px;cursor:pointer;background:#e15616;font-size:12px;color:#363636;border:none;outline:none;}
+.date-picker-wrapper .drp_top-bar .apply-btn.disabled{background:#999;}
+.date-picker-wrapper .date-range-length-tip{position:absolute;color:#FFF;margin-top:-4px;margin-left:-8px;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.3);box-shadow:0 0 3px rgba(0,0,0,0.3);display:none;background-color: #e15616;padding:0 6px;border-radius:2px;font-size:12px;line-height:16px;-webkit-filter:drop-shadow(0 0 3px rgba(0,0,0,0.3));-moz-filter:drop-shadow(0 0 3px rgba(0,0,0,0.3));-ms-filter:drop-shadow(0 0 3px rgba(0,0,0,0.3));-o-filter:drop-shadow(0 0 3px rgba(0,0,0,0.3));filter:drop-shadow(0 0 3px rgba(0,0,0,0.3));}
+.date-picker-wrapper .date-range-length-tip:after{content:'';position:absolute;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #e15616;left:50%;margin-left:-4px;bottom:-4px;}
+.date-picker-wrapper.two-months.no-gap .month1 .next,.date-picker-wrapper.two-months.no-gap .month2 .prev{display:none;}
+.date-picker-wrapper .week-number{padding:5px 0;line-height:1;font-size:12px;margin-bottom:1px;color:#999;cursor:pointer;}
+.date-picker-wrapper .week-number.week-number-selected{color:#49e;font-weight:bold;}
+@media screen and (min-width:768px){
+    .date-picker-wrapper{width:600px;}
+    .date-picker-wrapper .month-wrapper{border-radius:3px;background-color:#fff;padding:15px;cursor:default;position:relative;_overflow:hidden;}
+    .date-picker-wrapper .drp_top-bar{display:none;}
+    .date-picker-wrapper .month-wrapper table{width:266px;float:left;}
+    .date-picker-wrapper .month-wrapper table.month2{width:266px;float:right;}
+}
+@media screen and (max-width:768px){
+    .date-picker-wrapper{position:fixed;left:0px!important;top:0px!important;background-color:#fff;overflow:scroll;box-sizing:border-box;width:100%!important;height:100%!important;z-index:99999;box-sizing:border-box;width:354px;padding:15px;}
+    .date-picker-wrapper .mobile-wrapper{box-sizing:border-box;width:354px;padding:15px 15px 150px 15px;margin:0 auto;}
+    .date-picker-wrapper .month-wrapper{padding-right:60px;}
+    .date-picker-wrapper .month-wrapper table{width:266px;margin:0 auto 5px auto;position:relative;}
+    .date-picker-wrapper .month-wrapper tr.caption{position:absolute;right:-50px;top:0;width:40px;}
+    .date-picker-wrapper .drp_top-bar .apply-btn{color:#FFF;}
+    .date-picker-wrapper .month-wrapper tr.caption th{display:block;border:none;}
+    .date-picker-wrapper .month-wrapper tr.caption th.month-name{height:180px;width:18px;line-height:24px;border:none;}
+    .date-picker-wrapper .month-wrapper .week-name th:last-of-type,.date-picker-wrapper .month-wrapper .week-name th:first-of-type{color:#e15616;}
+    .date-picker-wrapper .drp_top-bar{border-top:1px #e15616 dotted;margin:40px auto 0;width:100%;box-sizing:border-box;}
+    .date-picker-wrapper table .caption .next,.date-picker-wrapper table .caption .prev{transform:rotate(90deg);}
+}

+ 2745 - 0
src/main/webapp/static/datapicker/jquery.daterangepicker.js

@@ -0,0 +1,2745 @@
+/**
+ * jquery-date-range-picker
+ * @version v0.18.0
+ * @link https://github.com/longbill/jquery-date-range-picker
+ * @license MIT
+ */
+(function(factory) {
+  if (typeof define === 'function' && define.amd) {
+    // AMD. Register as an anonymous module.
+    define(['jquery', 'moment'], factory);
+  } else if (typeof exports === 'object' && typeof module !== 'undefined') {
+    // CommonJS. Register as a module
+    module.exports = factory(require('jquery'), require('moment'));
+  } else {
+    // Browser globals
+    factory(jQuery, moment);
+  }
+}(function($, moment) {
+  'use strict';
+  $.dateRangePickerLanguages = {
+    "default": //default language: English
+    {
+      "selected": "Selected:",
+      "day": "Day",
+      "days": "Days",
+      "apply": "Close",
+      "week-1": "mo",
+      "week-2": "tu",
+      "week-3": "we",
+      "week-4": "th",
+      "week-5": "fr",
+      "week-6": "sa",
+      "week-7": "su",
+      "week-number": "W",
+      "month-name": ["january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"],
+      "shortcuts": "Shortcuts",
+      "custom-values": "Custom Values",
+      "past": "Past",
+      "following": "Following",
+      "previous": "Previous",
+      "prev-week": "Week",
+      "prev-month": "Month",
+      "prev-year": "Year",
+      "next": "Next",
+      "next-week": "Week",
+      "next-month": "Month",
+      "next-year": "Year",
+      "less-than": "Date range should not be more than %d days",
+      "more-than": "Date range should not be less than %d days",
+      "default-more": "Please select a date range longer than %d days",
+      "default-single": "Please select a date",
+      "default-less": "Please select a date range less than %d days",
+      "default-range": "Please select a date range between %d and %d days",
+      "default-default": "Please select a date range",
+      "time": "Time",
+      "hour": "Hour",
+      "minute": "Minute"
+    },
+    "id": {
+      "selected": "Terpilih:",
+      "day": "Hari",
+      "days": "Hari",
+      "apply": "Tutup",
+      "week-1": "sen",
+      "week-2": "sel",
+      "week-3": "rab",
+      "week-4": "kam",
+      "week-5": "jum",
+      "week-6": "sab",
+      "week-7": "min",
+      "week-number": "W",
+      "month-name": ["januari", "februari", "maret", "april", "mei", "juni", "juli", "agustus", "september", "oktober", "november", "desember"],
+      "shortcuts": "Pintas",
+      "custom-values": "Nilai yang ditentukan",
+      "past": "Yang Lalu",
+      "following": "Mengikuti",
+      "previous": "Sebelumnya",
+      "prev-week": "Minggu",
+      "prev-month": "Bulan",
+      "prev-year": "Tahun",
+      "next": "Selanjutnya",
+      "next-week": "Minggu",
+      "next-month": "Bulan",
+      "next-year": "Tahun",
+      "less-than": "Tanggal harus lebih dari %d hari",
+      "more-than": "Tanggal harus kurang dari %d hari",
+      "default-more": "Jarak tanggal harus lebih lama dari %d hari",
+      "default-single": "Silakan pilih tanggal",
+      "default-less": "Jarak rentang tanggal tidak boleh lebih lama dari %d hari",
+      "default-range": "Rentang tanggal harus antara %d dan %d hari",
+      "default-default": "Silakan pilih rentang tanggal",
+      "time": "Waktu",
+      "hour": "Jam",
+      "minute": "Menit"
+    },
+    "az": {
+      "selected": "Seçildi:",
+      "day": " gün",
+      "days": " gün",
+      "apply": "tətbiq",
+      "week-1": "1",
+      "week-2": "2",
+      "week-3": "3",
+      "week-4": "4",
+      "week-5": "5",
+      "week-6": "6",
+      "week-7": "7",
+      "month-name": ["yanvar", "fevral", "mart", "aprel", "may", "iyun", "iyul", "avqust", "sentyabr", "oktyabr", "noyabr", "dekabr"],
+      "shortcuts": "Qısayollar",
+      "past": "Keçmiş",
+      "following": "Növbəti",
+      "previous": "&nbsp;&nbsp;&nbsp;",
+      "prev-week": "Öncəki həftə",
+      "prev-month": "Öncəki ay",
+      "prev-year": "Öncəki il",
+      "next": "&nbsp;&nbsp;&nbsp;",
+      "next-week": "Növbəti həftə",
+      "next-month": "Növbəti ay",
+      "next-year": "Növbəti il",
+      "less-than": "Tarix aralığı %d gündən çox olmamalıdır",
+      "more-than": "Tarix aralığı %d gündən az olmamalıdır",
+      "default-more": "%d gündən çox bir tarix seçin",
+      "default-single": "Tarix seçin",
+      "default-less": "%d gündən az bir tarix seçin",
+      "default-range": "%d və %d gün aralığında tarixlər seçin",
+      "default-default": "Tarix aralığı seçin"
+    },
+    "bg": {
+      "selected": "Избрано:",
+      "day": "Ден",
+      "days": "Дни",
+      "apply": "Затвори",
+      "week-1": "пн",
+      "week-2": "вт",
+      "week-3": "ср",
+      "week-4": "чт",
+      "week-5": "пт",
+      "week-6": "сб",
+      "week-7": "нд",
+      "week-number": "С",
+      "month-name": ["януари", "февруари", "март", "април", "май", "юни", "юли", "август", "септември", "октомври", "ноември", "декември"],
+      "shortcuts": "Преки пътища",
+      "custom-values": "Персонализирани стойности",
+      "past": "Минал",
+      "following": "Следващ",
+      "previous": "Предишен",
+      "prev-week": "Седмица",
+      "prev-month": "Месец",
+      "prev-year": "Година",
+      "next": "Следващ",
+      "next-week": "Седмица",
+      "next-month": "Месец",
+      "next-year": "Година",
+      "less-than": "Периодът от време не трябва да е повече от %d дни",
+      "more-than": "Периодът от време не трябва да е по-малко от %d дни",
+      "default-more": "Моля изберете период по-дълъг от %d дни",
+      "default-single": "Моля изберете дата",
+      "default-less": "Моля изберете период по-къс от %d дни",
+      "default-range": "Моля изберете период между %d и %d дни",
+      "default-default": "Моля изберете период",
+      "time": "Време",
+      "hour": "Час",
+      "minute": "Минута"
+    },
+    "cn": //simplified chinese
+    {
+      "selected": "已选择:",
+      "day": "天",
+      "days": "天",
+      "apply": "确定",
+      "week-1": "一",
+      "week-2": "二",
+      "week-3": "三",
+      "week-4": "四",
+      "week-5": "五",
+      "week-6": "六",
+      "week-7": "日",
+      "week-number": "周",
+      "month-name": ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
+      "shortcuts": "快捷选择",
+      "past": "过去",
+      "following": "将来",
+      "previous": "&nbsp;&nbsp;&nbsp;",
+      "prev-week": "上周",
+      "prev-month": "上个月",
+      "prev-year": "去年",
+      "next": "&nbsp;&nbsp;&nbsp;",
+      "next-week": "下周",
+      "next-month": "下个月",
+      "next-year": "明年",
+      "less-than": "所选日期范围不能大于%d天",
+      "more-than": "所选日期范围不能小于%d天",
+      "default-more": "请选择大于%d天的日期范围",
+      "default-less": "请选择小于%d天的日期范围",
+      "default-range": "请选择%d天到%d天的日期范围",
+      "default-single": "请选择一个日期",
+      "default-default": "请选择一个日期范围",
+      "time": "时间",
+      "hour": "小时",
+      "minute": "分钟"
+    },
+    "cz": {
+      "selected": "Vybráno:",
+      "day": "Den",
+      "days": "Dny",
+      "apply": "Zavřít",
+      "week-1": "po",
+      "week-2": "út",
+      "week-3": "st",
+      "week-4": "čt",
+      "week-5": "pá",
+      "week-6": "so",
+      "week-7": "ne",
+      "month-name": ["leden", "únor", "březen", "duben", "květen", "červen", "červenec", "srpen", "září", "říjen", "listopad", "prosinec"],
+      "shortcuts": "Zkratky",
+      "past": "po",
+      "following": "následující",
+      "previous": "předchozí",
+      "prev-week": "týden",
+      "prev-month": "měsíc",
+      "prev-year": "rok",
+      "next": "další",
+      "next-week": "týden",
+      "next-month": "měsíc",
+      "next-year": "rok",
+      "less-than": "Rozsah data by neměl být větší než %d dnů",
+      "more-than": "Rozsah data by neměl být menší než %d dnů",
+      "default-more": "Prosím zvolte rozsah data větší než %d dnů",
+      "default-single": "Prosím zvolte datum",
+      "default-less": "Prosím zvolte rozsah data menší než %d dnů",
+      "default-range": "Prosím zvolte rozsah data mezi %d a %d dny",
+      "default-default": "Prosím zvolte rozsah data"
+    },
+    "de": {
+      "selected": "Auswahl:",
+      "day": "Tag",
+      "days": "Tage",
+      "apply": "Schließen",
+      "week-1": "mo",
+      "week-2": "di",
+      "week-3": "mi",
+      "week-4": "do",
+      "week-5": "fr",
+      "week-6": "sa",
+      "week-7": "so",
+      "month-name": ["januar", "februar", "märz", "april", "mai", "juni", "juli", "august", "september", "oktober", "november", "dezember"],
+      "shortcuts": "Schnellwahl",
+      "past": "Vorherige",
+      "following": "Folgende",
+      "previous": "Vorherige",
+      "prev-week": "Woche",
+      "prev-month": "Monat",
+      "prev-year": "Jahr",
+      "next": "Nächste",
+      "next-week": "Woche",
+      "next-month": "Monat",
+      "next-year": "Jahr",
+      "less-than": "Datumsbereich darf nicht größer sein als %d Tage",
+      "more-than": "Datumsbereich darf nicht kleiner sein als %d Tage",
+      "default-more": "Bitte mindestens %d Tage auswählen",
+      "default-single": "Bitte ein Datum auswählen",
+      "default-less": "Bitte weniger als %d Tage auswählen",
+      "default-range": "Bitte einen Datumsbereich zwischen %d und %d Tagen auswählen",
+      "default-default": "Bitte ein Start- und Enddatum auswählen",
+      "Time": "Zeit",
+      "hour": "Stunde",
+      "minute": "Minute"
+    },
+    "es": {
+      "selected": "Seleccionado:",
+      "day": "Día",
+      "days": "Días",
+      "apply": "Cerrar",
+      "week-1": "lu",
+      "week-2": "ma",
+      "week-3": "mi",
+      "week-4": "ju",
+      "week-5": "vi",
+      "week-6": "sa",
+      "week-7": "do",
+      "month-name": ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"],
+      "shortcuts": "Accesos directos",
+      "past": "Pasado",
+      "following": "Siguiente",
+      "previous": "Anterior",
+      "prev-week": "Semana",
+      "prev-month": "Mes",
+      "prev-year": "Año",
+      "next": "Siguiente",
+      "next-week": "Semana",
+      "next-month": "Mes",
+      "next-year": "Año",
+      "less-than": "El rango no debería ser mayor de %d días",
+      "more-than": "El rango no debería ser menor de %d días",
+      "default-more": "Por favor selecciona un rango mayor a %d días",
+      "default-single": "Por favor selecciona un día",
+      "default-less": "Por favor selecciona un rango menor a %d días",
+      "default-range": "Por favor selecciona un rango entre %d y %d días",
+      "default-default": "Por favor selecciona un rango de fechas."
+    },
+    "fr": {
+      "selected": "Sélection:",
+      "day": "Jour",
+      "days": "Jours",
+      "apply": "Fermer",
+      "week-1": "lu",
+      "week-2": "ma",
+      "week-3": "me",
+      "week-4": "je",
+      "week-5": "ve",
+      "week-6": "sa",
+      "week-7": "di",
+      "month-name": ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"],
+      "shortcuts": "Raccourcis",
+      "past": "Passé",
+      "following": "Suivant",
+      "previous": "Précédent",
+      "prev-week": "Semaine",
+      "prev-month": "Mois",
+      "prev-year": "Année",
+      "next": "Suivant",
+      "next-week": "Semaine",
+      "next-month": "Mois",
+      "next-year": "Année",
+      "less-than": "L'intervalle ne doit pas être supérieure à %d jours",
+      "more-than": "L'intervalle ne doit pas être inférieure à %d jours",
+      "default-more": "Merci de choisir une intervalle supérieure à %d jours",
+      "default-single": "Merci de choisir une date",
+      "default-less": "Merci de choisir une intervalle inférieure %d jours",
+      "default-range": "Merci de choisir une intervalle comprise entre %d et %d jours",
+      "default-default": "Merci de choisir une date"
+    },
+    "hu": {
+      "selected": "Kiválasztva:",
+      "day": "Nap",
+      "days": "Nap",
+      "apply": "Ok",
+      "week-1": "h",
+      "week-2": "k",
+      "week-3": "sz",
+      "week-4": "cs",
+      "week-5": "p",
+      "week-6": "sz",
+      "week-7": "v",
+      "month-name": ["január", "február", "március", "április", "május", "június", "július", "augusztus", "szeptember", "október", "november", "december"],
+      "shortcuts": "Gyorsválasztó",
+      "past": "Múlt",
+      "following": "Következő",
+      "previous": "Előző",
+      "prev-week": "Hét",
+      "prev-month": "Hónap",
+      "prev-year": "Év",
+      "next": "Következő",
+      "next-week": "Hét",
+      "next-month": "Hónap",
+      "next-year": "Év",
+      "less-than": "A kiválasztás nem lehet több %d napnál",
+      "more-than": "A kiválasztás nem lehet több %d napnál",
+      "default-more": "Válassz ki egy időszakot ami hosszabb mint %d nap",
+      "default-single": "Válassz egy napot",
+      "default-less": "Válassz ki egy időszakot ami rövidebb mint %d nap",
+      "default-range": "Válassz ki egy %d - %d nap hosszú időszakot",
+      "default-default": "Válassz ki egy időszakot"
+    },
+    "it": {
+      "selected": "Selezionati:",
+      "day": "Giorno",
+      "days": "Giorni",
+      "apply": "Chiudi",
+      "week-1": "lu",
+      "week-2": "ma",
+      "week-3": "me",
+      "week-4": "gi",
+      "week-5": "ve",
+      "week-6": "sa",
+      "week-7": "do",
+      "month-name": ["gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno", "luglio", "agosto", "settembre", "ottobre", "novembre", "dicembre"],
+      "shortcuts": "Scorciatoie",
+      "past": "Scorso",
+      "following": "Successivo",
+      "previous": "Precedente",
+      "prev-week": "Settimana",
+      "prev-month": "Mese",
+      "prev-year": "Anno",
+      "next": "Prossimo",
+      "next-week": "Settimana",
+      "next-month": "Mese",
+      "next-year": "Anno",
+      "less-than": "L'intervallo non dev'essere maggiore di %d giorni",
+      "more-than": "L'intervallo non dev'essere minore di %d giorni",
+      "default-more": "Seleziona un intervallo maggiore di %d giorni",
+      "default-single": "Seleziona una data",
+      "default-less": "Seleziona un intervallo minore di %d giorni",
+      "default-range": "Seleziona un intervallo compreso tra i %d e i %d giorni",
+      "default-default": "Seleziona un intervallo di date"
+    },
+    "ko": {
+      "selected": "기간:",
+      "day": "일",
+      "days": "일간",
+      "apply": "닫기",
+      "week-1": "월",
+      "week-2": "화",
+      "week-3": "수",
+      "week-4": "목",
+      "week-5": "금",
+      "week-6": "토",
+      "week-7": "일",
+      "week-number": "주",
+      "month-name": ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"],
+      "shortcuts": "단축키들",
+      "past": "지난(오늘기준)",
+      "following": "이후(오늘기준)",
+      "previous": "이전",
+      "prev-week": "1주",
+      "prev-month": "1달",
+      "prev-year": "1년",
+      "next": "다음",
+      "next-week": "1주",
+      "next-month": "1달",
+      "next-year": "1년",
+      "less-than": "날짜 범위는 %d 일보다 많을 수 없습니다",
+      "more-than": "날짜 범위는 %d 일보다 작을 수 없습니다",
+      "default-more": "날짜 범위를 %d 일보다 길게 선택해 주세요",
+      "default-single": "날짜를 선택해 주세요",
+      "default-less": "%d 일보다 작은 날짜를 선택해 주세요",
+      "default-range": "%d와 %d 일 사이의 날짜 범위를 선택해 주세요",
+      "default-default": "날짜 범위를 선택해 주세요",
+      "time": "시각",
+      "hour": "시",
+      "minute": "분"
+    },
+    "no": {
+      "selected": "Valgt:",
+      "day": "Dag",
+      "days": "Dager",
+      "apply": "Lukk",
+      "week-1": "ma",
+      "week-2": "ti",
+      "week-3": "on",
+      "week-4": "to",
+      "week-5": "fr",
+      "week-6": "lø",
+      "week-7": "sø",
+      "month-name": ["januar", "februar", "mars", "april", "mai", "juni", "juli", "august", "september", "oktober", "november", "desember"],
+      "shortcuts": "Snarveier",
+      "custom-values": "Egendefinerte Verdier",
+      "past": "Over", // Not quite sure about the context of this one
+      "following": "Følger",
+      "previous": "Forrige",
+      "prev-week": "Uke",
+      "prev-month": "Måned",
+      "prev-year": "År",
+      "next": "Neste",
+      "next-week": "Uke",
+      "next-month": "Måned",
+      "next-year": "År",
+      "less-than": "Datoperioden skal ikkje være lengre enn %d dager",
+      "more-than": "Datoperioden skal ikkje være kortere enn %d dager",
+      "default-more": "Vennligst velg ein datoperiode lengre enn %d dager",
+      "default-single": "Vennligst velg ein dato",
+      "default-less": "Vennligst velg ein datoperiode mindre enn %d dager",
+      "default-range": "Vennligst velg ein datoperiode mellom %d og %d dager",
+      "default-default": "Vennligst velg ein datoperiode",
+      "time": "Tid",
+      "hour": "Time",
+      "minute": "Minutter"
+    },
+    "nl": {
+      "selected": "Geselecteerd:",
+      "day": "Dag",
+      "days": "Dagen",
+      "apply": "Ok",
+      "week-1": "ma",
+      "week-2": "di",
+      "week-3": "wo",
+      "week-4": "do",
+      "week-5": "vr",
+      "week-6": "za",
+      "week-7": "zo",
+      "month-name": ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"],
+      "shortcuts": "Snelkoppelingen",
+      "custom-values": "Aangepaste waarden",
+      "past": "Verleden",
+      "following": "Komend",
+      "previous": "Vorige",
+      "prev-week": "Week",
+      "prev-month": "Maand",
+      "prev-year": "Jaar",
+      "next": "Volgende",
+      "next-week": "Week",
+      "next-month": "Maand",
+      "next-year": "Jaar",
+      "less-than": "Interval moet langer dan %d dagen zijn",
+      "more-than": "Interval mag niet minder dan %d dagen zijn",
+      "default-more": "Selecteer een interval langer dan %dagen",
+      "default-single": "Selecteer een datum",
+      "default-less": "Selecteer een interval minder dan %d dagen",
+      "default-range": "Selecteer een interval tussen %d en %d dagen",
+      "default-default": "Selecteer een interval",
+      "time": "Tijd",
+      "hour": "Uur",
+      "minute": "Minuut"
+    },
+    "ru": {
+      "selected": "Выбрано:",
+      "day": "День",
+      "days": "Дней",
+      "apply": "Применить",
+      "week-1": "пн",
+      "week-2": "вт",
+      "week-3": "ср",
+      "week-4": "чт",
+      "week-5": "пт",
+      "week-6": "сб",
+      "week-7": "вс",
+      "month-name": ["январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"],
+      "shortcuts": "Быстрый выбор",
+      "custom-values": "Пользовательские значения",
+      "past": "Прошедшие",
+      "following": "Следующие",
+      "previous": "&nbsp;&nbsp;&nbsp;",
+      "prev-week": "Неделя",
+      "prev-month": "Месяц",
+      "prev-year": "Год",
+      "next": "&nbsp;&nbsp;&nbsp;",
+      "next-week": "Неделя",
+      "next-month": "Месяц",
+      "next-year": "Год",
+      "less-than": "Диапазон не может быть больше %d дней",
+      "more-than": "Диапазон не может быть меньше %d дней",
+      "default-more": "Пожалуйста выберите диапазон больше %d дней",
+      "default-single": "Пожалуйста выберите дату",
+      "default-less": "Пожалуйста выберите диапазон меньше %d дней",
+      "default-range": "Пожалуйста выберите диапазон между %d и %d днями",
+      "default-default": "Пожалуйста выберите диапазон",
+      "time": "Время",
+      "hour": "Часы",
+      "minute": "Минуты"
+    },
+    "uk": {
+      "selected": "Вибрано:",
+      "day": "День",
+      "days": "Днів",
+      "apply": "Застосувати",
+      "week-1": "пн",
+      "week-2": "вт",
+      "week-3": "ср",
+      "week-4": "чт",
+      "week-5": "пт",
+      "week-6": "сб",
+      "week-7": "нд",
+      "month-name": ["січень", "лютий", "березень", "квітень", "травень", "червень", "липень", "серпень", "вересень", "жовтень", "листопад", "грудень"],
+      "shortcuts": "Швидкий вибір",
+      "custom-values": "Значення користувача",
+      "past": "Минулі",
+      "following": "Наступні",
+      "previous": "&nbsp;&nbsp;&nbsp;",
+      "prev-week": "Тиждень",
+      "prev-month": "Місяць",
+      "prev-year": "Рік",
+      "next": "&nbsp;&nbsp;&nbsp;",
+      "next-week": "Тиждень",
+      "next-month": "Місяць",
+      "next-year": "Рік",
+      "less-than": "Діапазон не може бути більш ніж %d днів",
+      "more-than": "Діапазон не може бути меньш ніж %d днів",
+      "default-more": "Будь ласка виберіть діапазон більше %d днів",
+      "default-single": "Будь ласка виберіть дату",
+      "default-less": "Будь ласка виберіть діапазон менше %d днів",
+      "default-range": "Будь ласка виберіть діапазон між %d та %d днями",
+      "default-default": "Будь ласка виберіть діапазон",
+      "time": "Час",
+      "hour": "Години",
+      "minute": "Хвилини"
+    },
+    "pl": {
+      "selected": "Wybrany:",
+      "day": "Dzień",
+      "days": "Dni",
+      "apply": "Zamknij",
+      "week-1": "pon",
+      "week-2": "wt",
+      "week-3": "śr",
+      "week-4": "czw",
+      "week-5": "pt",
+      "week-6": "so",
+      "week-7": "nd",
+      "month-name": ["styczeń", "luty", "marzec", "kwiecień", "maj", "czerwiec", "lipiec", "sierpień", "wrzesień", "październik", "listopad", "grudzień"],
+      "shortcuts": "Skróty",
+      "custom-values": "Niestandardowe wartości",
+      "past": "Przeszłe",
+      "following": "Następne",
+      "previous": "Poprzednie",
+      "prev-week": "tydzień",
+      "prev-month": "miesiąc",
+      "prev-year": "rok",
+      "next": "Następny",
+      "next-week": "tydzień",
+      "next-month": "miesiąc",
+      "next-year": "rok",
+      "less-than": "Okres nie powinien być dłuższy niż %d dni",
+      "more-than": "Okres nie powinien być krótszy niż  %d ni",
+      "default-more": "Wybierz okres dłuższy niż %d dni",
+      "default-single": "Wybierz datę",
+      "default-less": "Wybierz okres krótszy niż %d dni",
+      "default-range": "Wybierz okres trwający od %d do %d dni",
+      "default-default": "Wybierz okres",
+      "time": "Czas",
+      "hour": "Godzina",
+      "minute": "Minuta"
+    },
+    "se": {
+      "selected": "Vald:",
+      "day": "dag",
+      "days": "dagar",
+      "apply": "godkänn",
+      "week-1": "ma",
+      "week-2": "ti",
+      "week-3": "on",
+      "week-4": "to",
+      "week-5": "fr",
+      "week-6": "lö",
+      "week-7": "sö",
+      "month-name": ["januari", "februari", "mars", "april", "maj", "juni", "juli", "augusti", "september", "oktober", "november", "december"],
+      "shortcuts": "genvägar",
+      "custom-values": "Anpassade värden",
+      "past": "över",
+      "following": "följande",
+      "previous": "förra",
+      "prev-week": "vecka",
+      "prev-month": "månad",
+      "prev-year": "år",
+      "next": "nästa",
+      "next-week": "vecka",
+      "next-month": "måned",
+      "next-year": "år",
+      "less-than": "Datumintervall bör inte vara mindre än %d dagar",
+      "more-than": "Datumintervall bör inte vara mer än %d dagar",
+      "default-more": "Välj ett datumintervall längre än %d dagar",
+      "default-single": "Välj ett datum",
+      "default-less": "Välj ett datumintervall mindre än %d dagar",
+      "default-range": "Välj ett datumintervall mellan %d och %d dagar",
+      "default-default": "Välj ett datumintervall",
+      "time": "tid",
+      "hour": "timme",
+      "minute": "minut"
+    },
+    "pt": //Portuguese (European)
+    {
+      "selected": "Selecionado:",
+      "day": "Dia",
+      "days": "Dias",
+      "apply": "Fechar",
+      "week-1": "seg",
+      "week-2": "ter",
+      "week-3": "qua",
+      "week-4": "qui",
+      "week-5": "sex",
+      "week-6": "sab",
+      "week-7": "dom",
+      "week-number": "N",
+      "month-name": ["janeiro", "fevereiro", "março", "abril", "maio", "junho", "julho", "agosto", "setembro", "outubro", "novembro", "dezembro"],
+      "shortcuts": "Atalhos",
+      "custom-values": "Valores Personalizados",
+      "past": "Passado",
+      "following": "Seguinte",
+      "previous": "Anterior",
+      "prev-week": "Semana",
+      "prev-month": "Mês",
+      "prev-year": "Ano",
+      "next": "Próximo",
+      "next-week": "Próxima Semana",
+      "next-month": "Próximo Mês",
+      "next-year": "Próximo Ano",
+      "less-than": "O período selecionado não deve ser maior que %d dias",
+      "more-than": "O período selecionado não deve ser menor que %d dias",
+      "default-more": "Selecione um período superior a %d dias",
+      "default-single": "Selecione uma data",
+      "default-less": "Selecione um período inferior a %d dias",
+      "default-range": "Selecione um período de %d a %d dias",
+      "default-default": "Selecione um período",
+      "time": "Tempo",
+      "hour": "Hora",
+      "minute": "Minuto"
+    },
+    "tw": // traditional chinese
+    {
+      "selected": "已選擇:",
+      "day": "天",
+      "days": "天",
+      "apply": "確定",
+      "week-1": "一",
+      "week-2": "二",
+      "week-3": "三",
+      "week-4": "四",
+      "week-5": "五",
+      "week-6": "六",
+      "week-7": "日",
+      "week-number": "周",
+      "month-name": ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
+      "shortcuts": "快速選擇",
+      "past": "過去",
+      "following": "將來",
+      "previous": "&nbsp;&nbsp;&nbsp;",
+      "prev-week": "上週",
+      "prev-month": "上個月",
+      "prev-year": "去年",
+      "next": "&nbsp;&nbsp;&nbsp;",
+      "next-week": "下周",
+      "next-month": "下個月",
+      "next-year": "明年",
+      "less-than": "所選日期範圍不能大於%d天",
+      "more-than": "所選日期範圍不能小於%d天",
+      "default-more": "請選擇大於%d天的日期範圍",
+      "default-less": "請選擇小於%d天的日期範圍",
+      "default-range": "請選擇%d天到%d天的日期範圍",
+      "default-single": "請選擇一個日期",
+      "default-default": "請選擇一個日期範圍",
+      "time": "日期",
+      "hour": "小時",
+      "minute": "分鐘"
+    },
+    "ja": {
+      "selected": "選択しました:",
+      "day": "日",
+      "days": "日々",
+      "apply": "閉じる",
+      "week-1": "月",
+      "week-2": "火",
+      "week-3": "水",
+      "week-4": "木",
+      "week-5": "金",
+      "week-6": "土",
+      "week-7": "日",
+      "month-name": ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
+      "shortcuts": "クイック選択",
+      "past": "過去",
+      "following": "将来",
+      "previous": "&nbsp;&nbsp;&nbsp;",
+      "prev-week": "先週、",
+      "prev-month": "先月",
+      "prev-year": "昨年",
+      "next": "&nbsp;&nbsp;&nbsp;",
+      "next-week": "来週",
+      "next-month": "来月",
+      "next-year": "来年",
+      "less-than": "日付の範囲は %d 日以上にすべきではありません",
+      "more-than": "日付の範囲は %d 日を下回ってはいけません",
+      "default-more": "%d 日よりも長い期間を選択してください",
+      "default-less": "%d 日未満の期間を選択してください",
+      "default-range": "%d と% d日の間の日付範囲を選択してください",
+      "default-single": "日付を選択してください",
+      "default-default": "日付範囲を選択してください",
+      "time": "時間",
+      "hour": "時間",
+      "minute": "分"
+    },
+    "da": {
+      "selected": "Valgt:",
+      "day": "Dag",
+      "days": "Dage",
+      "apply": "Luk",
+      "week-1": "ma",
+      "week-2": "ti",
+      "week-3": "on",
+      "week-4": "to",
+      "week-5": "fr",
+      "week-6": "lö",
+      "week-7": "sö",
+      "month-name": ["januar", "februar", "marts", "april", "maj", "juni", "juli", "august", "september", "oktober", "november", "december"],
+      "shortcuts": "genveje",
+      "custom-values": "Brugerdefinerede værdier",
+      "past": "Forbi",
+      "following": "Følgende",
+      "previous": "Forrige",
+      "prev-week": "uge",
+      "prev-month": "månad",
+      "prev-year": "år",
+      "next": "Næste",
+      "next-week": "Næste uge",
+      "next-month": "Næste måned",
+      "next-year": "Næste år",
+      "less-than": "Dato interval bør ikke være med end %d dage",
+      "more-than": "Dato interval bør ikke være mindre end %d dage",
+      "default-more": "Vælg datointerval længere end %d dage",
+      "default-single": "Vælg dato",
+      "default-less": "Vælg datointerval mindre end %d dage",
+      "default-range": "Vælg datointerval mellem %d og %d dage",
+      "default-default": "Vælg datointerval",
+      "time": "tid",
+      "hour": "time",
+      "minute": "minut"
+    },
+    "fi": // Finnish
+    {
+      "selected": "Valittu:",
+      "day": "Päivä",
+      "days": "Päivää",
+      "apply": "Sulje",
+      "week-1": "ma",
+      "week-2": "ti",
+      "week-3": "ke",
+      "week-4": "to",
+      "week-5": "pe",
+      "week-6": "la",
+      "week-7": "su",
+      "week-number": "V",
+      "month-name": ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"],
+      "shortcuts": "Pikavalinnat",
+      "custom-values": "Mukautetut Arvot",
+      "past": "Menneet",
+      "following": "Tulevat",
+      "previous": "Edellinen",
+      "prev-week": "Viikko",
+      "prev-month": "Kuukausi",
+      "prev-year": "Vuosi",
+      "next": "Seuraava",
+      "next-week": "Viikko",
+      "next-month": "Kuukausi",
+      "next-year": "Vuosi",
+      "less-than": "Aikajakson tulisi olla vähemmän kuin %d päivää",
+      "more-than": "Aikajakson ei tulisi olla vähempää kuin %d päivää",
+      "default-more": "Valitse pidempi aikajakso kuin %d päivää",
+      "default-single": "Valitse päivä",
+      "default-less": "Valitse lyhyempi aikajakso kuin %d päivää",
+      "default-range": "Valitse aikajakso %d ja %d päivän väliltä",
+      "default-default": "Valitse aikajakso",
+      "time": "Aika",
+      "hour": "Tunti",
+      "minute": "Minuutti"
+    },
+    "cat": // Catala
+    {
+      "selected": "Seleccionats:",
+      "day": "Dia",
+      "days": "Dies",
+      "apply": "Tanca",
+      "week-1": "Dl",
+      "week-2": "Dm",
+      "week-3": "Dc",
+      "week-4": "Dj",
+      "week-5": "Dv",
+      "week-6": "Ds",
+      "week-7": "Dg",
+      "week-number": "S",
+      "month-name": ["gener", "febrer", "març", "abril", "maig", "juny", "juliol", "agost", "setembre", "octubre", "novembre", "desembre"],
+      "shortcuts": "Dreçeres",
+      "custom-values": "Valors personalitzats",
+      "past": "Passat",
+      "following": "Futur",
+      "previous": "Anterior",
+      "prev-week": "Setmana",
+      "prev-month": "Mes",
+      "prev-year": "Any",
+      "next": "Següent",
+      "next-week": "Setmana",
+      "next-month": "Mes",
+      "next-year": "Any",
+      "less-than": "El període no hauria de ser de més de %d dies",
+      "more-than": "El període no hauria de ser de menys de %d dies",
+      "default-more": "Perfavor selecciona un període més gran de %d dies",
+      "default-single": "Perfavor selecciona una data",
+      "default-less": "Perfavor selecciona un període de menys de %d dies",
+      "default-range": "Perfavor selecciona un període d'entre %d i %d dies",
+      "default-default": "Perfavor selecciona un període",
+      "time": "Temps",
+      "hour": "Hora",
+      "minute": "Minut"
+    }
+  };
+
+  $.fn.dateRangePicker = function(opt) {
+    if (!opt) opt = {};
+    opt = $.extend(true, {
+      autoClose: false,
+      format: 'YYYY-MM-DD',
+      separator: ' to ',
+      language: 'auto',
+      startOfWeek: 'sunday', // or monday
+      getValue: function() {
+        return $(this).val();
+      },
+      setValue: function(s) {
+        if (!$(this).attr('readonly') && !$(this).is(':disabled') && s != $(this).val()) {
+          $(this).val(s);
+        }
+      },
+      startDate: false,
+      endDate: false,
+      disableDates: [],
+      givenDates: [],
+      time: {
+        enabled: false
+      },
+      minDays: 0,
+      maxDays: 0,
+      showShortcuts: true,
+      shortcuts: {
+        //'prev-days': [1,3,5,7],
+        // 'next-days': [3,5,7],
+        //'prev' : ['week','month','year'],
+        // 'next' : ['week','month','year']
+      },
+      customShortcuts: [],
+      inline: false,
+      container: 'body',
+      alwaysOpen: false,
+      singleDate: false,
+      lookBehind: false,
+      batchMode: false,
+      duration: 200,
+      stickyMonths: true,
+      dayDivAttrs: [],
+      dayTdAttrs: [],
+      selectForward: false,
+      selectBackward: false,
+      applyBtnClass: '',
+      singleMonth: false,
+      monthChange: false,
+      hoveringTooltip: function(days, startTime, hoveringTime) {
+        return days > 1 ? days + ' ' + translate('days') : '';
+      },
+      showTopbar: true,
+      swapTime: false,
+      showWeekNumbers: false,
+      getWeekNumber: function(date) //date will be the first day of a week
+      {
+        return moment(date).format('w');
+      },
+      customOpenAnimation: null,
+      customCloseAnimation: null,
+      customArrowPrevSymbol: null,
+      customArrowNextSymbol: null,
+      monthSelect: false,
+      yearSelect: false
+    }, opt);
+
+    opt.start = false;
+    opt.end = false;
+
+    opt.startWeek = false;
+
+    //detect a touch device
+    opt.isTouchDevice = 'ontouchstart' in window || navigator.msMaxTouchPoints;
+
+    //if it is a touch device, hide hovering tooltip
+    if (opt.isTouchDevice) opt.hoveringTooltip = false;
+
+    //show one month on mobile devices
+    if (opt.singleDate) opt.singleMonth = true;
+
+    if (opt.singleMonth == 'auto') opt.singleMonth = $(window).width() < 480;
+    if (opt.singleMonth) opt.stickyMonths = false;
+
+    if (!opt.showTopbar) opt.autoClose = true;
+
+    if (opt.startDate && typeof opt.startDate == 'string') opt.startDate = moment(opt.startDate, opt.format).toDate();
+    if (opt.endDate && typeof opt.endDate == 'string') opt.endDate = moment(opt.endDate, opt.format).toDate();
+
+    if (opt.yearSelect && typeof opt.yearSelect === 'boolean') {
+      opt.yearSelect = function(current) { return [current - 5, current + 5]; }
+    }
+
+    //如果有禁用日期或仅给定可选日期
+    if ((Array.isArray(opt.disableDates) && opt.disableDates.length > 0) || (Array.isArray(opt.givenDates) && opt.givenDates.length > 0) || (Array.isArray(opt.disabledDays) && opt.disabledDays.length > 0)) {
+      var GetDateStr = function(d_) {
+        return moment(d_).format(opt.format);
+      }
+      if (Array.isArray(opt.givenDates) && opt.givenDates.length > 0) {
+        opt.givenDates = opt.givenDates.map(function(date) {
+          return GetDateStr(date);
+        });
+        if (Array.isArray(opt.disableDates) && opt.disableDates.length > 0) {
+          opt.disableDates = opt.disableDates.map(function(date) {
+            return GetDateStr(date);
+          });
+          opt.givenDates = opt.givenDates.filter(function(v) { return opt.disableDates.indexOf(v) == -1 });
+        }
+        if (Array.isArray(opt.disabledDays) && opt.disabledDays.length > 0) {
+          opt.givenDates = opt.givenDates.filter(function(v) { return opt.disabledDays.indexOf(new Date(GetDateStr(v)).getDay()) == -1 });
+        }
+        var givenDates = opt.givenDates.map(function(date) {
+          return moment(date, opt.format).toDate();
+        });
+        if (givenDates.length > 0) {
+          var minDate = Math.min.apply(null, givenDates);
+          var maxDate = Math.max.apply(null, givenDates);
+          if (!opt.startDate || new Date(opt.startDate).getTime() < minDate) {
+            opt.startDate = new Date(minDate);
+          }
+          if (!opt.endDate || new Date(opt.endDate).getTime() > maxDate) {
+            opt.endDate = new Date(maxDate);
+          }
+          opt.beforeShowDay = function(t) {
+            var time = new Date(GetDateStr(t)).getTime();
+            var valid = false;
+            for (var i = 0; i < opt.givenDates.length; i++) {
+              if (time == new Date(GetDateStr(opt.givenDates[i])).getTime()) {
+                valid = true;
+                break;
+              }
+            }
+            return [valid, '', ''];
+          }
+        } else {
+          opt.beforeShowDay = function(t) {
+            return [false, '', ''];
+          }
+        }
+      } else if ((Array.isArray(opt.disableDates) && opt.disableDates.length > 0) || (Array.isArray(opt.disabledDays) && opt.disabledDays.length > 0)) {
+        opt.beforeShowDay = function(t) {
+          var time = new Date(GetDateStr(t)).getTime();
+          var week = new Date(GetDateStr(t)).getDay();
+          var valid = true
+          if (Array.isArray(opt.disableDates) && opt.disableDates.length > 0) {
+            for (var i = 0; i < opt.disableDates.length; i++) {
+              if (time == new Date(GetDateStr(opt.disableDates[i])).getTime()) {
+                valid = false;
+                break;
+              }
+            }
+          }
+          if (Array.isArray(opt.disabledDays) && opt.disabledDays.length > 0) {
+            for (var i = 0; i < opt.disabledDays.length; i++) {
+              if (week == opt.disabledDays[i]) {
+                valid = false;
+                break;
+              }
+            }
+          }
+          return [valid, '', ''];
+        }
+      }
+    }
+
+    var languages = getLanguages();
+    var box;
+    var initiated = false;
+    var self = this;
+    var selfDom = $(self).get(0);
+    var domChangeTimer;
+    var inputTarget;
+
+    $(this).off('.datepicker').on('click.datepicker', function(evt) {
+      var event = evt || window.event;
+      inputTarget = event.target;
+      var isOpen = box.is(':visible');
+      if (!isOpen) open(opt.duration);
+    }).on('change.datepicker', function(evt) {
+      checkAndSetDefaultValue();
+    }).on('keyup.datepicker', function() {
+      try {
+        clearTimeout(domChangeTimer);
+      } catch (e) {}
+      domChangeTimer = setTimeout(function() {
+        checkAndSetDefaultValue();
+      }, 2000);
+    });
+
+    init_datepicker.call(this);
+
+    if (opt.alwaysOpen) {
+      open(0);
+    }
+
+    // expose some api
+    $(this).data('dateRangePicker', {
+      setStart: function(d1) {
+        if (typeof d1 == 'string') {
+          d1 = moment(d1, opt.format).toDate();
+        }
+
+        opt.end = false;
+        setSingleDate(d1);
+
+        return this;
+      },
+      setEnd: function(d2, silent) {
+        var start = new Date();
+        start.setTime(opt.start);
+        if (typeof d2 == 'string') {
+          d2 = moment(d2, opt.format).toDate();
+        }
+        setDateRange(start, d2, silent);
+        return this;
+      },
+      setDateRange: function(d1, d2, silent) {
+        if (typeof d1 == 'string' && typeof d2 == 'string') {
+          d1 = moment(d1, opt.format).toDate();
+          d2 = moment(d2, opt.format).toDate();
+        }
+        setDateRange(d1, d2, silent);
+      },
+      clear: clearSelection,
+      close: closeDatePicker,
+      open: open,
+      redraw: redrawDatePicker,
+      getDatePicker: getDatePicker,
+      resetMonthsView: resetMonthsView,
+      destroy: function() {
+        $(self).off('.datepicker');
+        $(self).data('dateRangePicker', '');
+        $(self).data('date-picker-opened', null);
+        box.remove();
+        $(window).off('resize.datepicker', calcPosition);
+        $(document).off('click.datepicker', outsideClickClose);
+      }
+    });
+
+    $(window).on('resize.datepicker', calcPosition);
+
+    return this;
+
+    function IsOwnDatePickerClicked(evt, selfObj) {
+      return (selfObj.contains(evt.target) || evt.target == selfObj || (selfObj.childNodes != undefined && $.inArray(evt.target, selfObj.childNodes) >= 0));
+    }
+
+    function init_datepicker() {
+      var self = this;
+
+      if ($(this).data('date-picker-opened')) {
+        closeDatePicker();
+        return;
+      }
+      $(this).data('date-picker-opened', true);
+
+
+      box = createDom().hide();
+      box.append('<div class="date-range-length-tip"></div>');
+
+      $(opt.container).append(box);
+
+      if (!opt.inline) {
+        calcPosition();
+      } else {
+        box.addClass('inline-wrapper');
+      }
+
+      if (opt.alwaysOpen) {
+        box.find('.apply-btn').hide();
+      }
+
+      var defaultTime = getDefaultTime();
+      resetMonthsView(defaultTime);
+
+      if (opt.time.enabled) {
+        if ((opt.startDate && opt.endDate) || (opt.start && opt.end)) {
+          showTime(moment(opt.start || opt.startDate).toDate(), 'time1');
+          showTime(moment(opt.end || opt.endDate).toDate(), 'time2');
+        } else {
+          var defaultEndTime = opt.defaultEndTime ? opt.defaultEndTime : defaultTime;
+          showTime(defaultTime, 'time1');
+          showTime(defaultEndTime, 'time2');
+        }
+      }
+
+      //showSelectedInfo();
+
+
+      var defaultTopText = '';
+      if (opt.singleDate)
+        defaultTopText = translate('default-single');
+      else if (opt.minDays && opt.maxDays)
+        defaultTopText = translate('default-range');
+      else if (opt.minDays)
+        defaultTopText = translate('default-more');
+      else if (opt.maxDays)
+        defaultTopText = translate('default-less');
+      else
+        defaultTopText = translate('default-default');
+
+      box.find('.default-top').html(defaultTopText.replace(/\%d/, opt.minDays).replace(/\%d/, opt.maxDays));
+      if (opt.singleMonth) {
+        box.addClass('single-month');
+      } else {
+        box.addClass('two-months');
+      }
+
+
+      setTimeout(function() {
+        //updateCalendarWidth();
+        initiated = true;
+      }, 0);
+
+      box.click(function(evt) {
+        evt.stopPropagation();
+      });
+
+      //if user click other place of the webpage, close date range picker window
+      $(document).on('click.datepicker', outsideClickClose);
+
+      box.find('.next').click(function() {
+        if (opt.monthChange && typeof opt.monthChange == 'function') { opt.monthChange('next'); };
+        if (!opt.stickyMonths)
+          gotoNextMonth(this);
+        else
+          gotoNextMonth_stickily(this);
+      });
+
+      function gotoNextMonth(self) {
+        var isMonth2 = $(self).parents('table').hasClass('month2');
+        var month = isMonth2 ? opt.month2 : opt.month1;
+        month = nextMonth(month);
+        if (!opt.singleMonth && !opt.singleDate && !isMonth2 && compare_month(month, opt.month2) >= 0 || isMonthOutOfBounds(month)) return;
+        showMonth(month, isMonth2 ? 'month2' : 'month1');
+        showGap();
+      }
+
+      function gotoNextMonth_stickily(self) {
+        var nextMonth1 = nextMonth(opt.month1);
+        var nextMonth2 = nextMonth(opt.month2);
+        if (isMonthOutOfBounds(nextMonth2)) return;
+        if (!opt.singleDate && compare_month(nextMonth1, nextMonth2) >= 0) return;
+        showMonth(nextMonth1, 'month1');
+        showMonth(nextMonth2, 'month2');
+        showSelectedDays();
+      }
+
+
+      box.find('.prev').click(function() {
+        if (opt.monthChange && typeof opt.monthChange == 'function') { opt.monthChange('prev'); };
+        if (!opt.stickyMonths)
+          gotoPrevMonth(this);
+        else
+          gotoPrevMonth_stickily(this);
+      });
+
+      function gotoPrevMonth(self) {
+        var isMonth2 = $(self).parents('table').hasClass('month2');
+        var month = isMonth2 ? opt.month2 : opt.month1;
+        month = prevMonth(month);
+        if (isMonth2 && compare_month(month, opt.month1) <= 0 || isMonthOutOfBounds(month)) return;
+        showMonth(month, isMonth2 ? 'month2' : 'month1');
+        showGap();
+      }
+
+      function gotoPrevMonth_stickily(self) {
+        var prevMonth1 = prevMonth(opt.month1);
+        var prevMonth2 = prevMonth(opt.month2);
+        if (isMonthOutOfBounds(prevMonth1)) return;
+        if (!opt.singleDate && compare_month(prevMonth2, prevMonth1) <= 0) return;
+        showMonth(prevMonth2, 'month2');
+        showMonth(prevMonth1, 'month1');
+        showSelectedDays();
+      }
+
+      box.attr('unselectable', 'on')
+        .css('user-select', 'none')
+        .on('selectstart', function(e) {
+          e.preventDefault();
+          return false;
+        });
+
+      box.find('.apply-btn').click(function() {
+        closeDatePicker();
+        var dateRange = getDateString(new Date(opt.start)) + opt.separator + getDateString(new Date(opt.end));
+        $(self).trigger('datepicker-apply', {
+          'value': dateRange,
+          'date1': new Date(opt.start),
+          'date2': new Date(opt.end)
+        });
+      });
+
+      box.find('[custom]').click(function() {
+        var valueName = $(this).attr('custom');
+        opt.start = false;
+        opt.end = false;
+        box.find('.day.checked').removeClass('checked');
+        opt.setValue.call(selfDom, valueName);
+        checkSelectionValid();
+        showSelectedInfo(true);
+        showSelectedDays();
+        if (opt.autoClose) closeDatePicker();
+      });
+
+      box.find('[shortcut]').click(function() {
+        var shortcut = $(this).attr('shortcut');
+        var end = new Date(),
+          start = false;
+        var dir;
+        if (shortcut.indexOf('day') != -1) {
+          var day = parseInt(shortcut.split(',', 2)[1], 10);
+          start = new Date(new Date().getTime() + 86400000 * day);
+          end = new Date(end.getTime() + 86400000 * (day > 0 ? 1 : -1));
+        } else if (shortcut.indexOf('week') != -1) {
+          dir = shortcut.indexOf('prev,') != -1 ? -1 : 1;
+          var stopDay;
+          if (dir == 1)
+            stopDay = opt.startOfWeek == 'monday' ? 1 : 0;
+          else
+            stopDay = opt.startOfWeek == 'monday' ? 0 : 6;
+
+          end = new Date(end.getTime() - 86400000);
+          while (end.getDay() != stopDay) end = new Date(end.getTime() + dir * 86400000);
+          start = new Date(end.getTime() + dir * 86400000 * 6);
+        } else if (shortcut.indexOf('month') != -1) {
+          dir = shortcut.indexOf('prev,') != -1 ? -1 : 1;
+          if (dir == 1)
+            start = nextMonth(end);
+          else
+            start = prevMonth(end);
+          start.setDate(1);
+          end = nextMonth(start);
+          end.setDate(1);
+          end = new Date(end.getTime() - 86400000);
+        } else if (shortcut.indexOf('year') != -1) {
+          dir = shortcut.indexOf('prev,') != -1 ? -1 : 1;
+          start = new Date();
+          start.setFullYear(end.getFullYear() + dir);
+          start.setMonth(0);
+          start.setDate(1);
+          end.setFullYear(end.getFullYear() + dir);
+          end.setMonth(11);
+          end.setDate(31);
+        } else if (shortcut == 'custom') {
+          var name = $(this).html();
+          if (opt.customShortcuts && opt.customShortcuts.length > 0) {
+            for (var i = 0; i < opt.customShortcuts.length; i++) {
+              var sh = opt.customShortcuts[i];
+              if (sh.name == name) {
+                var data = [];
+                // try
+                // {
+                data = sh['dates'].call();
+                //}catch(e){}
+                if (data && data.length == 2) {
+                  start = data[0];
+                  end = data[1];
+                }
+
+                // if only one date is specified then just move calendars there
+                // move calendars to show this date's month and next months
+                if (data && data.length == 1) {
+                  var movetodate = data[0];
+                  showMonth(movetodate, 'month1');
+                  showMonth(nextMonth(movetodate), 'month2');
+                  showGap();
+                }
+
+                break;
+              }
+            }
+          }
+        }
+        if (start && end) {
+          setDateRange(start, end);
+          checkSelectionValid();
+        }
+      });
+
+      box.find('.time1 input[type=range]').on('change touchmove', function(e) {
+        var target = e.target,
+          hour = target.name == 'hour' ? $(target).val().replace(/^(\d{1})$/, '0$1') : undefined,
+          min = target.name == 'minute' ? $(target).val().replace(/^(\d{1})$/, '0$1') : undefined;
+        setTime('time1', hour, min);
+      });
+
+      box.find('.time2 input[type=range]').on('change touchmove', function(e) {
+        var target = e.target,
+          hour = target.name == 'hour' ? $(target).val().replace(/^(\d{1})$/, '0$1') : undefined,
+          min = target.name == 'minute' ? $(target).val().replace(/^(\d{1})$/, '0$1') : undefined;
+        setTime('time2', hour, min);
+      });
+
+      // 添加日期选择器和输入框的关联
+      $(box).attr("selector", $(self).attr("id"));
+    }
+
+
+    function calcPosition() {
+      if (!opt.inline) {
+        if ($(window).width() > 760) {
+          var offset = $(self).offset();
+          if ($(opt.container).css('position') == 'relative') {
+            var containerOffset = $(opt.container).offset();
+            var leftIndent = Math.max(0, offset.left + box.outerWidth() - $('body').width() + 16);
+            box.css({
+              top: offset.top - containerOffset.top + $(self).outerHeight() + 4,
+              left: offset.left - containerOffset.left - leftIndent
+            });
+          } else {
+            box.css({
+              top: offset.top + $(self).outerHeight() + parseInt($('body').css('border-top') || 0, 10) + 10,
+              left: offset.left
+            });
+            /*if (offset.left < 460) //left to right
+            {
+            box.css({
+              top: offset.top + $(self).outerHeight() + parseInt($('body').css('border-top') || 0, 10),
+              left: offset.left
+            });
+            } else {
+            box.css({
+              top: offset.top + $(self).outerHeight() + parseInt($('body').css('border-top') || 0, 10),
+              left: offset.left + $(self).width() - box.width() - 16
+            });
+            }*/
+          }
+        } else {
+          box.css({
+            top: 0,
+            left: 0
+          });
+        }
+      }
+    }
+
+    // Return the date picker wrapper element
+    function getDatePicker() {
+      return box;
+    }
+
+    function open(animationTime) {
+      redrawDatePicker();
+      checkAndSetDefaultValue();
+      if (opt.customOpenAnimation) {
+        opt.customOpenAnimation.call(box.get(0), function() {
+          $(self).trigger('datepicker-opened', {
+            relatedTarget: box
+          });
+        });
+      } else {
+        box.slideDown(animationTime, function() {
+          $(self).trigger('datepicker-opened', {
+            relatedTarget: box
+          });
+          //移动端消除滚动穿透
+          if (!opt.inline && $(window).width() < 760) {
+            $('body').attr('fixed-top', $(window).scrollTop()).css('position', 'fixed');
+          }
+        });
+      }
+      $(self).trigger('datepicker-open', {
+        relatedTarget: box
+      });
+      showGap();
+      //updateCalendarWidth();
+      calcPosition();
+    }
+
+    function checkAndSetDefaultValue() {
+      var __default_string = opt.getValue.call(selfDom);
+      var defaults = __default_string ? __default_string.split(opt.separator) : '';
+
+      if (defaults && ((defaults.length == 1 && opt.singleDate) || defaults.length >= 2)) {
+        var ___format = opt.format;
+        if (___format.match(/Do/)) {
+
+          ___format = ___format.replace(/Do/, 'D');
+          defaults[0] = defaults[0].replace(/(\d+)(th|nd|st)/, '$1');
+          if (defaults.length >= 2) {
+            defaults[1] = defaults[1].replace(/(\d+)(th|nd|st)/, '$1');
+          }
+        }
+        // set initiated  to avoid triggerring datepicker-change event
+        initiated = false;
+        if (defaults.length >= 2) {
+          setDateRange(getValidValue(defaults[0], ___format, moment.locale(opt.language)), getValidValue(defaults[1], ___format, moment.locale(opt.language)));
+        } else if (defaults.length == 1 && opt.singleDate) {
+          setSingleDate(getValidValue(defaults[0], ___format, moment.locale(opt.language)));
+        }
+
+        initiated = true;
+      }
+    }
+
+    function getValidValue(date, format, locale) {
+      if (moment(date, format, locale).isValid()) {
+        return moment(date, format, locale).toDate();
+      } else {
+        return moment().toDate();
+      }
+    }
+
+    function updateCalendarWidth() {
+      var gapMargin = box.find('.gap').css('margin-left');
+      if (gapMargin) gapMargin = parseInt(gapMargin);
+      var w1 = box.find('.month1').width();
+      var w2 = box.find('.gap').width() + (gapMargin ? gapMargin * 2 : 0);
+      var w3 = box.find('.month2').width();
+      box.find('.month-wrapper').width(w1 + w2 + w3);
+    }
+
+    function renderTime(name, date) {
+      box.find('.' + name + ' input[type=range].hour-range').val(moment(date).hours());
+      box.find('.' + name + ' input[type=range].minute-range').val(moment(date).minutes());
+      setTime(name, moment(date).format('HH'), moment(date).format('mm'));
+    }
+
+    function changeTime(name, date) {
+      opt[name] = parseInt(
+        moment(parseInt(date))
+        .startOf('day')
+        .add(moment(opt[name + 'Time']).format('HH'), 'h')
+        .add(moment(opt[name + 'Time']).format('mm'), 'm').valueOf()
+      );
+    }
+
+    function swapTime() {
+      renderTime('time1', opt.start);
+      renderTime('time2', opt.end);
+    }
+
+    function setTime(name, hour, minute) {
+      hour && (box.find('.' + name + ' .hour-val').text(hour));
+      minute && (box.find('.' + name + ' .minute-val').text(minute));
+      switch (name) {
+        case 'time1':
+          if (opt.start) {
+            setRange('start', moment(opt.start));
+          }
+          setRange('startTime', moment(opt.startTime || moment().valueOf()));
+          break;
+        case 'time2':
+          if (opt.end) {
+            setRange('end', moment(opt.end));
+          }
+          setRange('endTime', moment(opt.endTime || moment().valueOf()));
+          break;
+      }
+
+      function setRange(name, timePoint) {
+        var h = timePoint.format('HH'),
+          m = timePoint.format('mm');
+        opt[name] = timePoint
+          .startOf('day')
+          .add(hour || h, 'h')
+          .add(minute || m, 'm')
+          .valueOf();
+      }
+      checkSelectionValid();
+      showSelectedInfo();
+      showSelectedDays();
+    }
+
+    function clearSelection() {
+      opt.start = false;
+      opt.end = false;
+      box.find('.day.checked').removeClass('checked');
+      box.find('.day.last-date-selected').removeClass('last-date-selected');
+      box.find('.day.first-date-selected').removeClass('first-date-selected');
+      opt.setValue.call(selfDom, '');
+      checkSelectionValid();
+      showSelectedInfo();
+      showSelectedDays();
+    }
+
+    function handleStart(time) {
+      var r = time;
+      if (opt.batchMode === 'week-range') {
+        if (opt.startOfWeek === 'monday') {
+          r = moment(parseInt(time)).startOf('isoweek').valueOf();
+        } else {
+          r = moment(parseInt(time)).startOf('week').valueOf();
+        }
+      } else if (opt.batchMode === 'month-range') {
+        r = moment(parseInt(time)).startOf('month').valueOf();
+      }
+      return r;
+    }
+
+    function handleEnd(time) {
+      var r = time;
+      if (opt.batchMode === 'week-range') {
+        if (opt.startOfWeek === 'monday') {
+          r = moment(parseInt(time)).endOf('isoweek').valueOf();
+        } else {
+          r = moment(parseInt(time)).endOf('week').valueOf();
+        }
+      } else if (opt.batchMode === 'month-range') {
+        r = moment(parseInt(time)).endOf('month').valueOf();
+      }
+      return r;
+    }
+
+
+    function dayClicked(day) {
+      if (day.hasClass('invalid')) return;
+      var time = day.attr('time');
+      day.addClass('checked');
+      if (opt.singleDate) {
+        opt.start = time;
+        opt.end = false;
+      } else if (opt.batchMode === 'week') {
+        if (opt.startOfWeek === 'monday') {
+          opt.start = moment(parseInt(time)).startOf('isoweek').valueOf();
+          opt.end = moment(parseInt(time)).endOf('isoweek').valueOf();
+        } else {
+          opt.end = moment(parseInt(time)).endOf('week').valueOf();
+          opt.start = moment(parseInt(time)).startOf('week').valueOf();
+        }
+      } else if (opt.batchMode === 'workweek') {
+        opt.start = moment(parseInt(time)).day(1).valueOf();
+        opt.end = moment(parseInt(time)).day(5).valueOf();
+      } else if (opt.batchMode === 'weekend') {
+        opt.start = moment(parseInt(time)).day(6).valueOf();
+        opt.end = moment(parseInt(time)).day(7).valueOf();
+      } else if (opt.batchMode === 'month') {
+        opt.start = moment(parseInt(time)).startOf('month').valueOf();
+        opt.end = moment(parseInt(time)).endOf('month').valueOf();
+      } else if (!opt.start && !opt.end) {
+        opt.start = handleStart(time);
+        opt.end = false;
+      } else if (opt.start && opt.end) {
+        opt.start = handleStart(time);
+        opt.end = false;
+        /*if ($(inputTarget).attr("doubleDate") === 'first') {
+          opt.start = handleStart(time);
+          if (opt.start > opt.end) {
+            opt.end = handleEnd(time * 1 + 86400000 * 2);
+          }
+        } else {
+          opt.start = handleStart(time);
+          opt.end = handleEnd(time);
+          if (opt.start > opt.end && (opt.end * 1 - 86400000 * 2 >= opt.startDate.getTime())) {
+            opt.start = handleStart(opt.end * 1 - 86400000 * 2);
+          }
+        }*/
+      } else if (opt.start) {
+        opt.end = handleEnd(time);
+        if (opt.time.enabled) {
+          changeTime('end', opt.end);
+        }
+      }
+
+      //Update time in case it is enabled and timestamps are available
+      if (opt.time.enabled) {
+        if (opt.start) {
+          changeTime('start', opt.start);
+        }
+        if (opt.end) {
+          changeTime('end', opt.end);
+        }
+      }
+
+      //In case the start is after the end, swap the timestamps
+      if (!opt.singleDate && opt.start && opt.end && opt.start > opt.end) {
+        var tmp = opt.end;
+        opt.end = handleEnd(opt.start);
+        opt.start = handleStart(tmp);
+        if (opt.time.enabled && opt.swapTime) {
+          swapTime();
+        }
+      }
+
+      opt.start = parseInt(opt.start);
+      opt.end = parseInt(opt.end);
+
+      clearHovering();
+      if (opt.start && !opt.end) {
+        $(self).trigger('datepicker-first-date-selected', {
+          'date1': new Date(opt.start)
+        });
+        dayHovering(day);
+      }
+      updateSelectableRange(time);
+
+      checkSelectionValid();
+      showSelectedInfo();
+      showSelectedDays();
+
+      if (!opt.singleDate && $(inputTarget).attr("doubleDate") === 'first') {
+        $(selfDom).find("input[doubleDate=last]").trigger("click").trigger("focus");
+      }else{
+        autoclose();
+      }
+    }
+
+
+    function weekNumberClicked(weekNumberDom) {
+      var thisTime = parseInt(weekNumberDom.attr('data-start-time'), 10);
+      var date1, date2;
+      if (!opt.startWeek) {
+        opt.startWeek = thisTime;
+        weekNumberDom.addClass('week-number-selected');
+        date1 = new Date(thisTime);
+        opt.start = moment(date1).day(opt.startOfWeek == 'monday' ? 1 : 0).valueOf();
+        opt.end = moment(date1).day(opt.startOfWeek == 'monday' ? 7 : 6).valueOf();
+      } else {
+        box.find('.week-number-selected').removeClass('week-number-selected');
+        date1 = new Date(thisTime < opt.startWeek ? thisTime : opt.startWeek);
+        date2 = new Date(thisTime < opt.startWeek ? opt.startWeek : thisTime);
+        opt.startWeek = false;
+        opt.start = moment(date1).day(opt.startOfWeek == 'monday' ? 1 : 0).valueOf();
+        opt.end = moment(date2).day(opt.startOfWeek == 'monday' ? 7 : 6).valueOf();
+      }
+      updateSelectableRange();
+      checkSelectionValid();
+      showSelectedInfo();
+      showSelectedDays();
+      autoclose();
+    }
+
+    function isValidTime(time) {
+      time = parseInt(time, 10);
+      if (opt.startDate && compare_day(time, opt.startDate) < 0) return false;
+      if (opt.endDate && compare_day(time, opt.endDate) > 0) return false;
+
+      if (opt.start && !opt.end && !opt.singleDate) {
+        //check maxDays and minDays setting
+        if (opt.maxDays > 0 && countDays(time, opt.start) > opt.maxDays) return false;
+        if (opt.minDays > 0 && countDays(time, opt.start) < opt.minDays) return false;
+
+        //check selectForward and selectBackward
+        if (opt.selectForward && time < opt.start) return false;
+        if (opt.selectBackward && time > opt.start) return false;
+
+        //check disabled days
+        if (opt.beforeShowDay && typeof opt.beforeShowDay == 'function') {
+          var valid = true;
+          var timeTmp = time;
+          while (countDays(timeTmp, opt.start) > 1) {
+            var arr = opt.beforeShowDay(new Date(timeTmp));
+            if (!arr[0]) {
+              valid = false;
+              break;
+            }
+            if (Math.abs(timeTmp - opt.start) < 86400000) break;
+            if (timeTmp > opt.start) timeTmp -= 86400000;
+            if (timeTmp < opt.start) timeTmp += 86400000;
+          }
+          if (!valid) return false;
+        }
+      }
+      return true;
+    }
+
+
+    function updateSelectableRange() {
+      box.find('.day.invalid.tmp').removeClass('tmp invalid').addClass('valid');
+      if (opt.start && !opt.end) {
+        box.find('.day.toMonth.valid').each(function() {
+          var time = parseInt($(this).attr('time'), 10);
+          if (!isValidTime(time))
+            $(this).addClass('invalid tmp').removeClass('valid');
+          else
+            $(this).addClass('valid tmp').removeClass('invalid');
+        });
+      }
+
+      return true;
+    }
+
+
+    function dayHovering(day) {
+      var hoverTime = parseInt(day.attr('time'));
+      var tooltip = '';
+
+      if (day.hasClass('has-tooltip') && day.attr('data-tooltip')) {
+        tooltip = '<span class="tooltip-content">' + day.attr('data-tooltip') + '</span>';
+      } else if (!day.hasClass('invalid')) {
+        if (opt.singleDate) {
+          box.find('.day.hovering').removeClass('hovering');
+          day.addClass('hovering');
+        } else {
+          box.find('.day').each(function() {
+            var time = parseInt($(this).attr('time')),
+              start = opt.start,
+              end = opt.end;
+
+            if (time == hoverTime) {
+              $(this).addClass('hovering');
+            } else {
+              $(this).removeClass('hovering');
+            }
+
+            if (
+              (opt.start && !opt.end) &&
+              (
+                (opt.start < time && hoverTime >= time) ||
+                (opt.start > time && hoverTime <= time)
+              )
+            ) {
+              $(this).addClass('hovering');
+            } else {
+              $(this).removeClass('hovering');
+            }
+          });
+
+          if (opt.start && !opt.end) {
+            var days = countDays(hoverTime, opt.start);
+            if (opt.hoveringTooltip) {
+              if (typeof opt.hoveringTooltip == 'function') {
+                tooltip = opt.hoveringTooltip(days, opt.start, hoverTime);
+              } else if (opt.hoveringTooltip === true && days > 1) {
+                tooltip = days + ' ' + translate('days');
+              }
+            }
+          }
+        }
+      }
+
+      if (tooltip) {
+        var posDay = day.offset();
+        var posBox = box.offset();
+
+        var _left = posDay.left - posBox.left;
+        var _top = posDay.top - posBox.top;
+        _left += day.width() / 2;
+
+
+        var $tip = box.find('.date-range-length-tip');
+        var w = $tip.css({
+          'visibility': 'hidden',
+          'display': 'none'
+        }).html(tooltip).width();
+        var h = $tip.height();
+        _left -= w / 2;
+        _top -= h;
+        setTimeout(function() {
+          $tip.css({
+            left: _left,
+            top: _top,
+            display: 'block',
+            'visibility': 'visible'
+          });
+        }, 10);
+      } else {
+        box.find('.date-range-length-tip').hide();
+      }
+    }
+
+    function clearHovering() {
+      box.find('.day.hovering').removeClass('hovering');
+      box.find('.date-range-length-tip').hide();
+    }
+
+    function dateChanged(date) {
+      var value = date.val();
+      var name = date.attr('name');
+      var type = date.parents('table').hasClass('month1') ? 'month1' : 'month2';
+      var oppositeType = type === 'month1' ? 'month2' : 'month1';
+      var startDate = opt.startDate ? moment(opt.startDate) : false;
+      var endDate = opt.endDate ? moment(opt.endDate) : false;
+      var newDate = moment(opt[type])[name](value);
+
+
+      if (startDate && newDate.isSameOrBefore(startDate)) {
+        newDate = startDate.add(type === 'month2' ? 1 : 0, 'month');
+      }
+
+      if (endDate && newDate.isSameOrAfter(endDate)) {
+        newDate = endDate.add(!opt.singleMonth && type === 'month1' ? -1 : 0, 'month');
+      }
+
+      showMonth(newDate, type);
+
+      if (type === 'month1') {
+        if (opt.stickyMonths || moment(newDate).isSameOrAfter(opt[oppositeType], 'month')) {
+          showMonth(moment(newDate).add(1, 'month'), oppositeType);
+        }
+      } else {
+        if (opt.stickyMonths || moment(newDate).isSameOrBefore(opt[oppositeType], 'month')) {
+          showMonth(moment(newDate).add(-1, 'month'), oppositeType);
+        }
+      }
+
+      showGap();
+    }
+
+    function autoclose() {
+      if (opt.singleDate === true) {
+        if (initiated && opt.start) {
+          if (opt.autoClose) closeDatePicker();
+        }
+      } else {
+        if (initiated && opt.start && opt.end) {
+          if (opt.autoClose) closeDatePicker();
+        }
+      }
+    }
+
+    function checkSelectionValid() {
+      var days = Math.ceil((opt.end - opt.start) / 86400000) + 1;
+      if (opt.singleDate) { // Validate if only start is there
+        if (opt.start && !opt.end)
+          box.find('.drp_top-bar').removeClass('error').addClass('normal');
+        else
+          box.find('.drp_top-bar').removeClass('error').removeClass('normal');
+      } else if (opt.maxDays && days > opt.maxDays) {
+        opt.start = false;
+        opt.end = false;
+        box.find('.day').removeClass('checked');
+        box.find('.drp_top-bar').removeClass('normal').addClass('error').find('.error-top').html(translate('less-than').replace('%d', opt.maxDays));
+      } else if (opt.minDays && days < opt.minDays) {
+        opt.start = false;
+        opt.end = false;
+        box.find('.day').removeClass('checked');
+        box.find('.drp_top-bar').removeClass('normal').addClass('error').find('.error-top').html(translate('more-than').replace('%d', opt.minDays));
+      } else {
+        if (opt.start || opt.end)
+          box.find('.drp_top-bar').removeClass('error').addClass('normal');
+        else
+          box.find('.drp_top-bar').removeClass('error').removeClass('normal');
+      }
+
+      if ((opt.singleDate && opt.start && !opt.end) || (!opt.singleDate && opt.start && opt.end)) {
+        box.find('.apply-btn').removeClass('disabled');
+      } else {
+        box.find('.apply-btn').addClass('disabled');
+      }
+
+      if (opt.batchMode) {
+        if (
+          (opt.start && opt.startDate && compare_day(opt.start, opt.startDate) < 0) ||
+          (opt.end && opt.endDate && compare_day(opt.end, opt.endDate) > 0)
+        ) {
+          opt.start = false;
+          opt.end = false;
+          box.find('.day').removeClass('checked');
+        }
+      }
+    }
+
+    function showSelectedInfo(forceValid, silent) {
+      setTimeout(function() { //ios去除光标
+        if (!isPC) $("input").blur();
+        if (selfDom.firstChild) {
+          selfDom.firstChild.blur();
+        } else {
+          selfDom.blur();
+        }
+      }, 0)
+      box.find('.start-day').html('...');
+      box.find('.end-day').html('...');
+      box.find('.selected-days').hide();
+      if (opt.start) {
+        box.find('.start-day').html(getDateString(new Date(parseInt(opt.start))));
+      }
+      if (opt.end) {
+        box.find('.end-day').html(getDateString(new Date(parseInt(opt.end))));
+      }
+      var dateRange;
+      if (opt.start && opt.singleDate) {
+        box.find('.apply-btn').removeClass('disabled');
+        dateRange = getDateString(new Date(opt.start));
+        opt.setValue.call(selfDom, dateRange, getDateString(new Date(opt.start)), getDateString(new Date(opt.end)));
+
+        if (initiated && !silent) {
+          $(self).trigger('datepicker-change', {
+            'value': dateRange,
+            'date1': new Date(opt.start)
+          });
+        }
+      } else if (opt.start && opt.end) {
+        box.find('.selected-days').show().find('.selected-days-num').html(countDays(opt.end, opt.start));
+        box.find('.apply-btn').removeClass('disabled');
+        dateRange = getDateString(new Date(opt.start)) + opt.separator + getDateString(new Date(opt.end));
+        opt.setValue.call(selfDom, dateRange, getDateString(new Date(opt.start)), getDateString(new Date(opt.end)));
+        if (initiated && !silent) {
+          $(self).trigger('datepicker-change', {
+            'value': dateRange,
+            'date1': new Date(opt.start),
+            'date2': new Date(opt.end)
+          });
+        }
+      } else if (opt.start && !opt.end) {
+        dateRange = getDateString(new Date(opt.start));
+        opt.setValue.call(selfDom, dateRange, getDateString(new Date(opt.start)), '');
+        if (initiated && !silent) {
+          $(self).trigger('datepicker-change', {
+            'value': dateRange,
+            'date1': new Date(opt.start),
+            'date2': ''
+          });
+        }
+      } else if (forceValid) {
+        box.find('.apply-btn').removeClass('disabled');
+      } else {
+        box.find('.apply-btn').addClass('disabled');
+      }
+    }
+
+    function countDays(start, end) {
+      return Math.abs(moment(start).diff(moment(end), 'd')) + 1;
+    }
+
+    function setDateRange(date1, date2, silent) {
+      if (date1.getTime() > date2.getTime()) {
+        var tmp = date2;
+        date2 = date1;
+        date1 = tmp;
+        tmp = null;
+      }
+      var valid = true;
+      if (opt.startDate && compare_day(date1, opt.startDate) < 0) valid = false;
+      if (opt.endDate && compare_day(date2, opt.endDate) > 0) valid = false;
+      if (!valid) {
+        showMonth(opt.startDate, 'month1');
+        showMonth(nextMonth(opt.startDate), 'month2');
+        showGap();
+        return;
+      }
+
+      opt.start = date1.getTime();
+      opt.end = date2.getTime();
+
+      if (opt.time.enabled) {
+        renderTime('time1', date1);
+        renderTime('time2', date2);
+      }
+
+      if (opt.stickyMonths || (compare_day(date1, date2) > 0 && compare_month(date1, date2) === 0)) {
+        if (opt.lookBehind) {
+          date1 = prevMonth(date2);
+        } else {
+          date2 = nextMonth(date1);
+        }
+      }
+
+      if (opt.stickyMonths && opt.endDate !== false && compare_month(date2, opt.endDate) > 0) {
+        date1 = prevMonth(date1);
+        date2 = prevMonth(date2);
+      }
+
+      if (!opt.stickyMonths) {
+        if (compare_month(date1, date2) === 0) {
+          if (opt.lookBehind) {
+            date1 = prevMonth(date2);
+          } else {
+            date2 = nextMonth(date1);
+          }
+        }
+      }
+
+      showMonth(date1, 'month1');
+      showMonth(date2, 'month2');
+      showGap();
+      checkSelectionValid();
+      showSelectedInfo(false, silent);
+      autoclose();
+    }
+
+    function setSingleDate(date1) {
+
+      var valid = true;
+      if (opt.startDate && compare_day(date1, opt.startDate) < 0) valid = false;
+      if (opt.endDate && compare_day(date1, opt.endDate) > 0) valid = false;
+      if (!valid) {
+        showMonth(opt.startDate, 'month1');
+        return;
+      }
+
+      opt.start = date1.getTime();
+
+
+      if (opt.time.enabled) {
+        renderTime('time1', date1);
+
+      }
+      showMonth(date1, 'month1');
+      if (opt.singleMonth !== true) {
+        var date2 = nextMonth(date1);
+        showMonth(date2, 'month2');
+      }
+      showGap();
+      showSelectedInfo();
+      autoclose();
+    }
+
+    function showSelectedDays() {
+      if (!opt.start && !opt.end) return;
+      box.find('.day').each(function() {
+        var time = parseInt($(this).attr('time')),
+          start = opt.start,
+          end = opt.end;
+        if (opt.time.enabled) {
+          time = moment(time).startOf('day').valueOf();
+          start = moment(start || moment().valueOf()).startOf('day').valueOf();
+          end = moment(end || moment().valueOf()).startOf('day').valueOf();
+        }
+        if (
+          (opt.start && opt.end && end >= time && start <= time) ||
+          (opt.start && !opt.end && moment(start).format('YYYY-MM-DD') == moment(time).format('YYYY-MM-DD'))
+        ) {
+          $(this).addClass('checked');
+        } else {
+          $(this).removeClass('checked');
+        }
+
+        //add first-date-selected class name to the first date selected
+        if (opt.start && moment(start).format('YYYY-MM-DD') == moment(time).format('YYYY-MM-DD')) {
+          $(this).addClass('first-date-selected');
+        } else {
+          $(this).removeClass('first-date-selected');
+        }
+        //add last-date-selected
+        if (opt.end && moment(end).format('YYYY-MM-DD') == moment(time).format('YYYY-MM-DD')) {
+          $(this).addClass('last-date-selected');
+        } else {
+          $(this).removeClass('last-date-selected');
+        }
+      });
+      box.find('.week-number').each(function() {
+        if ($(this).attr('data-start-time') == opt.startWeek) {
+          $(this).addClass('week-number-selected');
+        }
+      });
+      if (opt.monthChange == false) {
+        box.find('.prev').removeClass("disabled");
+        box.find('.next').removeClass("disabled");
+        var timeStr = parseInt(box.find('.day').eq(20).attr('time'))
+        if (opt.startDate && moment(opt.startDate).format('YYYY-MM-DD').slice(0, 7) == moment(timeStr).format('YYYY-MM-DD').slice(0, 7)) {
+          box.find('.prev').addClass("disabled");
+        }
+        if (opt.endDate && moment(opt.endDate).format('YYYY-MM-DD').slice(0, 7) == moment(timeStr).format('YYYY-MM-DD').slice(0, 7)) {
+          box.find('.next').addClass("disabled");
+        }
+      }
+    }
+
+    function showMonth(date, month) {
+      date = moment(date).toDate();
+      var monthElement = generateMonthElement(date, month);
+      var yearElement = generateYearElement(date, month);
+      if (opt.language == 'tw' || opt.language == 'cn') {
+        box.find('.' + month + ' .month-name').html(yearElement + '年' + monthElement);
+      } else {
+        box.find('.' + month + ' .month-name').html(monthElement + ' ' + yearElement);
+      }
+      box.find('.' + month + ' tbody').html(createMonthHTML(date));
+      opt[month] = date;
+      updateSelectableRange();
+      bindEvents();
+    }
+
+    function generateMonthElement(date, month) {
+      var range;
+      var startDate = opt.startDate ? moment(opt.startDate).add(!opt.singleMonth && month === 'month2' ? 1 : 0, 'month') : false;
+      var endDate = opt.endDate ? moment(opt.endDate).add(!opt.singleMonth && month === 'month1' ? -1 : 0, 'month') : false;
+      date = moment(date);
+
+      if (!opt.monthSelect ||
+        startDate && endDate && startDate.isSame(endDate, 'month')) {
+        return '<div class="month-element">' + nameMonth(date.get('month')) + '</div>';
+      }
+
+      range = [
+        startDate && date.isSame(startDate, 'year') ? startDate.get('month') : 0,
+        date ? date.get('month') : 11
+      ];
+
+      if (range[0] === range[1]) {
+        return '<div class="month-element">' + nameMonth(date.get('month')) + '</div>';
+      }
+
+      return generateSelect(
+        'month',
+        generateSelectData(
+          range,
+          date.get('month'),
+          function(value) { return nameMonth(value); }
+        )
+      );
+    }
+
+    function generateYearElement(date, month) {
+      date = moment(date);
+      var startDate = opt.startDate ? moment(opt.startDate).add(!opt.singleMonth && month === 'month2' ? 1 : 0, 'month') : false;
+      var endDate = opt.endDate ? moment(opt.endDate).add(!opt.singleMonth && month === 'month1' ? -1 : 0, 'month') : false;
+      var fullYear = date.get('year');
+      var isYearFunction = opt.yearSelect && typeof opt.yearSelect === 'function';
+      var range;
+
+      if (!opt.yearSelect ||
+        startDate && endDate && startDate.isSame(moment(endDate), 'year')) {
+        return '<div class="month-element">' + fullYear + '</div>';
+      }
+
+      range = isYearFunction ? opt.yearSelect(fullYear) : opt.yearSelect.slice();
+
+      range = [
+        startDate ? Math.max(range[0], startDate.get('year')) : Math.min(range[0], fullYear),
+        endDate ? Math.min(range[1], endDate.get('year')) : Math.max(range[1], fullYear)
+      ];
+
+      return generateSelect('year', generateSelectData(range, fullYear));
+    }
+
+
+    function generateSelectData(range, current, valueBeautifier) {
+      var data = [];
+      valueBeautifier = valueBeautifier || function(value) { return value; };
+
+      for (var i = range[0]; i <= range[1]; i++) {
+        data.push({
+          value: i,
+          text: valueBeautifier(i),
+          isCurrent: i === current
+        });
+      }
+
+      return data;
+    }
+
+    function generateSelect(name, data) {
+      var select = '<div class="select-wrapper"><select class="' + name + '" name="' + name + '">';
+      var current;
+
+      for (var i = 0, l = data.length; i < l; i++) {
+        select += '<option value="' + data[i].value + '"' + (data[i].isCurrent ? ' selected' : '') + '>';
+        select += data[i].text;
+        select += '</option>';
+
+        if (data[i].isCurrent) {
+          current = data[i].text;
+        }
+      }
+
+      select += '</select>' + current + '</div>';
+
+      return select;
+    }
+
+    function bindEvents() {
+      box.find('.day').off("click").click(function(evt) {
+        dayClicked($(this));
+      });
+
+      box.find('.day').off("mouseenter").mouseenter(function(evt) {
+        dayHovering($(this));
+      });
+
+      box.find('.day').off("mouseleave").mouseleave(function(evt) {
+        box.find('.date-range-length-tip').hide();
+        if (opt.singleDate) {
+          clearHovering();
+        }
+      });
+
+      box.find('.week-number').off("click").click(function(evt) {
+        weekNumberClicked($(this));
+      });
+
+      box.find('.month').off("change").change(function(evt) {
+        dateChanged($(this));
+      });
+
+      box.find('.year').off("change").change(function(evt) {
+        dateChanged($(this));
+      });
+    }
+
+    function showTime(date, name) {
+      box.find('.' + name).append(getTimeHTML());
+      renderTime(name, date);
+    }
+
+    function nameMonth(m) {
+      return translate('month-name')[m];
+    }
+
+    function getDateString(d) {
+      return moment(d).format(opt.format);
+    }
+
+    function showGap() {
+      showSelectedDays();
+      var m1 = parseInt(moment(opt.month1).format('YYYYMM'));
+      var m2 = parseInt(moment(opt.month2).format('YYYYMM'));
+      var p = Math.abs(m1 - m2);
+      var shouldShow = (p > 1 && p != 89);
+      if (shouldShow) {
+        box.addClass('has-gap').removeClass('no-gap').find('.gap').css('visibility', 'visible');
+      } else {
+        box.removeClass('has-gap').addClass('no-gap').find('.gap').css('visibility', 'hidden');
+      }
+      var h1 = box.find('table.month1').height();
+      var h2 = box.find('table.month2').height();
+      box.find('.gap').height(Math.max(h1, h2) + 10);
+    }
+
+    function closeDatePicker() {
+      if (opt.alwaysOpen) return;
+
+      var afterAnim = function() {
+        $(self).data('date-picker-opened', false);
+        $(self).trigger('datepicker-closed', {
+          relatedTarget: box
+        });
+        //消除滚动穿透
+        if (!opt.inline && $(window).width() < 760 && $('body').css("position") == 'fixed') {
+          $('body').css('position', '')
+          $(window).scrollTop($('body').attr('fixed-top'))
+        }
+      };
+      if (opt.customCloseAnimation) {
+        opt.customCloseAnimation.call(box.get(0), afterAnim);
+      } else {
+        $(box).slideUp(opt.duration, afterAnim);
+      }
+      if (!opt.singleDate && (opt.end.toString() == 'NaN' || opt.end == false)) {
+        box.find('.day[time=' + parseInt(Date.parse(new Date(opt.start + 172800000))) + ']').click();
+      }
+      $(self).trigger('datepicker-close', {
+        relatedTarget: box
+      });
+    }
+
+    function redrawDatePicker() {
+      showMonth(opt.month1, 'month1');
+      showMonth(opt.month2, 'month2');
+    }
+
+    function compare_month(m1, m2) {
+      var p = parseInt(moment(m1).format('YYYYMM')) - parseInt(moment(m2).format('YYYYMM'));
+      if (p > 0) return 1;
+      if (p === 0) return 0;
+      return -1;
+    }
+
+    function compare_day(m1, m2) {
+      var p = parseInt(moment(m1).format('YYYYMMDD')) - parseInt(moment(m2).format('YYYYMMDD'));
+      if (p > 0) return 1;
+      if (p === 0) return 0;
+      return -1;
+    }
+
+    function nextMonth(month) {
+      return moment(month).add(1, 'months').toDate();
+    }
+
+    function prevMonth(month) {
+      return moment(month).add(-1, 'months').toDate();
+    }
+
+    function getTimeHTML() {
+      return '<div>' +
+        '<span>' + translate('Time') + ': <span class="hour-val">00</span>:<span class="minute-val">00</span></span>' +
+        '</div>' +
+        '<div class="hour">' +
+        '<label>' + translate('Hour') + ': <input type="range" class="hour-range" name="hour" min="0" max="23"></label>' +
+        '</div>' +
+        '<div class="minute">' +
+        '<label>' + translate('Minute') + ': <input type="range" class="minute-range" name="minute" min="0" max="59"></label>' +
+        '</div>';
+    }
+
+    function createDom() {
+      var html = '<div class="date-picker-wrapper';
+      if (opt.extraClass) html += ' ' + opt.extraClass + ' ';
+      if (opt.singleDate) html += ' single-date ';
+      if (!opt.showShortcuts) html += ' no-shortcuts ';
+      if (!opt.showTopbar) html += ' no-topbar ';
+      if (opt.customTopBar) html += ' custom-topbar ';
+      html += '">';
+
+      var _colspan = opt.showWeekNumbers ? 6 : 5;
+
+      var arrowPrev = '&lt;';
+      if (opt.customArrowPrevSymbol) arrowPrev = opt.customArrowPrevSymbol;
+
+      var arrowNext = '&gt;';
+      if (opt.customArrowNextSymbol) arrowNext = opt.customArrowNextSymbol;
+
+      html += '<div class="month-wrapper">' +
+        '   <table class="month1" cellspacing="0" border="0" cellpadding="0">' +
+        '       <thead>' +
+        '           <tr class="caption">' +
+        '               <th>' +
+        '                   <span class="prev">' + arrowPrev + '</span>' +
+        '               </th>' +
+        '               <th colspan="' + _colspan + '" class="month-name">' +
+        '               </th>' +
+        '               <th>' +
+        (opt.singleDate || !opt.stickyMonths ? '<span class="next">' + arrowNext + '</span>' : '') +
+        '               </th>' +
+        '           </tr>' +
+        '           <tr class="week-name">' + getWeekHead() +
+        '       </thead>' +
+        '       <tbody></tbody>' +
+        '   </table>';
+
+      if (hasMonth2()) {
+        html += '<div class="gap">' + getGapHTML() + '</div>' +
+          '<table class="month2" cellspacing="0" border="0" cellpadding="0">' +
+          '   <thead>' +
+          '   <tr class="caption">' +
+          '       <th>' +
+          (!opt.stickyMonths ? '<span class="prev">' + arrowPrev + '</span>' : '') +
+          '       </th>' +
+          '       <th colspan="' + _colspan + '" class="month-name">' +
+          '       </th>' +
+          '       <th>' +
+          '           <span class="next">' + arrowNext + '</span>' +
+          '       </th>' +
+          '   </tr>' +
+          '   <tr class="week-name">' + getWeekHead() +
+          '   </thead>' +
+          '   <tbody></tbody>' +
+          '</table>';
+
+      }
+      //+'</div>'
+      html += '<div class="dp-clearfix"></div>' +
+        '<div class="time">' +
+        '<div class="time1"></div>';
+      if (!opt.singleDate) {
+        html += '<div class="time2"></div>';
+      }
+      html += '</div>' +
+        '<div class="dp-clearfix"></div>' +
+        '</div>';
+
+      html += '<div class="footer">';
+      if (opt.showShortcuts) {
+        html += '<div class="shortcuts"><b>' + translate('shortcuts') + '</b>';
+
+        var data = opt.shortcuts;
+        if (data) {
+          var name;
+          if (data['prev-days'] && data['prev-days'].length > 0) {
+            html += '&nbsp;<span class="prev-days">' + translate('past');
+            for (var i = 0; i < data['prev-days'].length; i++) {
+              name = data['prev-days'][i];
+              name += (data['prev-days'][i] > 1) ? translate('days') : translate('day');
+              html += ' <a href="javascript:;" shortcut="day,-' + data['prev-days'][i] + '">' + name + '</a>';
+            }
+            html += '</span>';
+          }
+
+          if (data['next-days'] && data['next-days'].length > 0) {
+            html += '&nbsp;<span class="next-days">' + translate('following');
+            for (var i = 0; i < data['next-days'].length; i++) {
+              name = data['next-days'][i];
+              name += (data['next-days'][i] > 1) ? translate('days') : translate('day');
+              html += ' <a href="javascript:;" shortcut="day,' + data['next-days'][i] + '">' + name + '</a>';
+            }
+            html += '</span>';
+          }
+
+          if (data.prev && data.prev.length > 0) {
+            html += '&nbsp;<span class="prev-buttons">' + translate('previous');
+            for (var i = 0; i < data.prev.length; i++) {
+              name = translate('prev-' + data.prev[i]);
+              html += ' <a href="javascript:;" shortcut="prev,' + data.prev[i] + '">' + name + '</a>';
+            }
+            html += '</span>';
+          }
+
+          if (data.next && data.next.length > 0) {
+            html += '&nbsp;<span class="next-buttons">' + translate('next');
+            for (var i = 0; i < data.next.length; i++) {
+              name = translate('next-' + data.next[i]);
+              html += ' <a href="javascript:;" shortcut="next,' + data.next[i] + '">' + name + '</a>';
+            }
+            html += '</span>';
+          }
+        }
+
+        if (opt.customShortcuts) {
+          for (var i = 0; i < opt.customShortcuts.length; i++) {
+            var sh = opt.customShortcuts[i];
+            html += '&nbsp;<span class="custom-shortcut"><a href="javascript:;" shortcut="custom">' + sh.name + '</a></span>';
+          }
+        }
+        html += '</div>';
+      }
+
+      // Add Custom Values Dom
+      if (opt.showCustomValues) {
+        html += '<div class="customValues"><b>' + (opt.customValueLabel || translate('custom-values')) + '</b>';
+
+        if (opt.customValues) {
+          for (var i = 0; i < opt.customValues.length; i++) {
+            var val = opt.customValues[i];
+            html += '&nbsp;<span class="custom-value"><a href="javascript:;" custom="' + val.value + '">' + val.name + '</a></span>';
+          }
+        }
+      }
+
+      if (opt.showTopbar) {
+        html += '<div class="drp_top-bar">';
+
+        if (opt.customTopBar) {
+          if (typeof opt.customTopBar == 'function') opt.customTopBar = opt.customTopBar();
+          html += '<div class="custom-top">' + opt.customTopBar + '</div>';
+        } else {
+          html += '<div class="normal-top">' +
+            '<span class="selection-top">' + translate('selected') + ' </span> <b class="start-day">...</b>';
+          if (!opt.singleDate) {
+            html += ' <span class="separator-day">' + opt.separator + '</span> <b class="end-day">...</b> <i class="selected-days">(<span class="selected-days-num">3</span> ' + translate('days') + ')</i>';
+          }
+          html += '</div>';
+          html += '<div class="error-top">error</div>' +
+            '<div class="default-top">default</div>';
+        }
+
+        html += '<input type="button" class="apply-btn disabled' + getApplyBtnClass() + '" value="' + translate('apply') + '" />';
+        html += '</div>';
+      }
+      html += '</div></div>';
+
+
+      return $(html);
+    }
+
+    function getApplyBtnClass() {
+      var klass = '';
+      if (opt.autoClose === true && $(window).width() > 760) {
+        klass += ' hide';
+      }
+      if (opt.applyBtnClass !== '') {
+        klass += ' ' + opt.applyBtnClass;
+      }
+      return klass;
+    }
+
+    function getWeekHead() {
+      var prepend = opt.showWeekNumbers ? '<th>' + translate('week-number') + '</th>' : '';
+      if (opt.startOfWeek == 'monday') {
+        return prepend + '<th>' + translate('week-1') + '</th>' +
+          '<th>' + translate('week-2') + '</th>' +
+          '<th>' + translate('week-3') + '</th>' +
+          '<th>' + translate('week-4') + '</th>' +
+          '<th>' + translate('week-5') + '</th>' +
+          '<th>' + translate('week-6') + '</th>' +
+          '<th>' + translate('week-7') + '</th>';
+      } else {
+        return prepend + '<th>' + translate('week-7') + '</th>' +
+          '<th>' + translate('week-1') + '</th>' +
+          '<th>' + translate('week-2') + '</th>' +
+          '<th>' + translate('week-3') + '</th>' +
+          '<th>' + translate('week-4') + '</th>' +
+          '<th>' + translate('week-5') + '</th>' +
+          '<th>' + translate('week-6') + '</th>';
+      }
+    }
+
+    function isMonthOutOfBounds(month) {
+      month = moment(month);
+      if (opt.startDate && month.endOf('month').isBefore(opt.startDate)) {
+        return true;
+      }
+      if (opt.endDate && month.startOf('month').isAfter(opt.endDate)) {
+        return true;
+      }
+      return false;
+    }
+
+    function getGapHTML() {
+      var html = ['<div class="gap-top-mask"></div><div class="gap-bottom-mask"></div><div class="gap-lines">'];
+      for (var i = 0; i < 20; i++) {
+        html.push('<div class="gap-line">' +
+          '<div class="gap-1"></div>' +
+          '<div class="gap-2"></div>' +
+          '<div class="gap-3"></div>' +
+          '</div>');
+      }
+      html.push('</div>');
+      return html.join('');
+    }
+
+    function hasMonth2() {
+      return (!opt.singleMonth);
+    }
+
+    function attributesCallbacks(initialObject, callbacksArray, today) {
+      var resultObject = $.extend(true, {}, initialObject);
+
+      $.each(callbacksArray, function(cbAttrIndex, cbAttr) {
+        var addAttributes = cbAttr(today);
+        for (var attr in addAttributes) {
+          if (resultObject.hasOwnProperty(attr)) {
+            resultObject[attr] += addAttributes[attr];
+          } else {
+            resultObject[attr] = addAttributes[attr];
+          }
+        }
+      });
+
+      var attrString = '';
+
+      for (var attr in resultObject) {
+        if (resultObject.hasOwnProperty(attr)) {
+          attrString += attr + '="' + resultObject[attr] + '" ';
+        }
+      }
+
+      return attrString;
+    }
+
+    function createMonthHTML(d) {
+      var days = [];
+      d.setDate(1);
+      var lastMonth = new Date(d.getTime() - 86400000);
+      var now = new Date();
+
+      var dayOfWeek = d.getDay();
+      if ((dayOfWeek === 0) && (opt.startOfWeek === 'monday')) {
+        // add one week
+        dayOfWeek = 7;
+      }
+      var today, valid;
+
+      if (dayOfWeek > 0) {
+        for (var i = dayOfWeek; i > 0; i--) {
+          var day = new Date(d.getTime() - 86400000 * i);
+          valid = isValidTime(day.getTime());
+          if (opt.startDate && compare_day(day, opt.startDate) < 0) valid = false;
+          if (opt.endDate && compare_day(day, opt.endDate) > 0) valid = false;
+          days.push({
+            date: day,
+            type: 'lastMonth',
+            day: day.getDate(),
+            time: day.getTime(),
+            valid: valid
+          });
+        }
+      }
+      var toMonth = d.getMonth();
+      for (var i = 0; i < 40; i++) {
+        today = moment(d).add(i, 'days').toDate();
+        valid = isValidTime(today.getTime());
+        if (opt.startDate && compare_day(today, opt.startDate) < 0) valid = false;
+        if (opt.endDate && compare_day(today, opt.endDate) > 0) valid = false;
+        days.push({
+          date: today,
+          type: today.getMonth() == toMonth ? 'toMonth' : 'nextMonth',
+          day: today.getDate(),
+          time: today.getTime(),
+          valid: valid
+        });
+      }
+      var html = [];
+      for (var week = 0; week < 6; week++) {
+        if (days[week * 7].type == 'nextMonth') break;
+        html.push('<tr>');
+
+        for (var day = 0; day < 7; day++) {
+          var _day = (opt.startOfWeek == 'monday') ? day + 1 : day;
+          today = days[week * 7 + _day];
+          var highlightToday = moment(today.time).format('L') == moment(now).format('L');
+          today.extraClass = '';
+          today.tooltip = '';
+          if (today.valid && opt.beforeShowDay && typeof opt.beforeShowDay == 'function') {
+            var _r = opt.beforeShowDay(moment(today.time).toDate());
+            today.valid = _r[0];
+            today.extraClass = _r[1] || '';
+            today.tooltip = _r[2] || '';
+            if (today.tooltip !== '') today.extraClass += ' has-tooltip ';
+          }
+
+          var todayDivAttr = {
+            time: today.time,
+            'data-tooltip': today.tooltip,
+            'class': 'day ' + today.type + ' ' + today.extraClass + ' ' + (today.valid ? 'valid' : 'invalid') + ' ' + (highlightToday ? 'real-today' : '')
+          };
+
+          if (day === 0 && opt.showWeekNumbers) {
+            html.push('<td><div class="week-number" data-start-time="' + today.time + '">' + opt.getWeekNumber(today.date) + '</div></td>');
+          }
+
+          html.push('<td ' + attributesCallbacks({}, opt.dayTdAttrs, today) + '><div ' + attributesCallbacks(todayDivAttr, opt.dayDivAttrs, today) + '>' + showDayHTML(today.time, today.day) + '</div></td>');
+        }
+        html.push('</tr>');
+      }
+      return html.join('');
+    }
+
+    function showDayHTML(time, date) {
+      if (opt.showDateFilter && typeof opt.showDateFilter == 'function') return opt.showDateFilter(time, date);
+      return date;
+    }
+
+    function getLanguages() {
+      if (opt.language == 'auto') {
+        var language = navigator.language ? navigator.language : navigator.browserLanguage;
+        if (!language) {
+          return $.dateRangePickerLanguages['default'];
+        }
+        language = language.toLowerCase();
+        if (language in $.dateRangePickerLanguages) {
+          return $.dateRangePickerLanguages[language];
+        }
+
+        return $.dateRangePickerLanguages['default'];
+      } else if (opt.language && opt.language in $.dateRangePickerLanguages) {
+        return $.dateRangePickerLanguages[opt.language];
+      } else {
+        return $.dateRangePickerLanguages['default'];
+      }
+    }
+
+    /**
+     * Translate language string, try both the provided translation key, as the lower case version
+     */
+    function translate(translationKey) {
+      var translationKeyLowerCase = translationKey.toLowerCase();
+      var result = (translationKey in languages) ? languages[translationKey] : (translationKeyLowerCase in languages) ? languages[translationKeyLowerCase] : null;
+      var defaultLanguage = $.dateRangePickerLanguages['default'];
+      if (result == null) result = (translationKey in defaultLanguage) ? defaultLanguage[translationKey] : (translationKeyLowerCase in defaultLanguage) ? defaultLanguage[translationKeyLowerCase] : '';
+
+      return result;
+    }
+
+    function getDefaultTime() {
+      var defaultTime = opt.defaultTime ? opt.defaultTime : new Date();
+
+      if (opt.lookBehind) {
+        if (opt.startDate && compare_month(defaultTime, opt.startDate) < 0) defaultTime = nextMonth(moment(opt.startDate).toDate());
+        if (opt.endDate && compare_month(defaultTime, opt.endDate) > 0) defaultTime = moment(opt.endDate).toDate();
+      } else {
+        if (opt.startDate && compare_month(defaultTime, opt.startDate) < 0) defaultTime = moment(opt.startDate).toDate();
+        if (opt.endDate && compare_month(nextMonth(defaultTime), opt.endDate) > 0) defaultTime = prevMonth(moment(opt.endDate).toDate());
+      }
+
+      if (opt.singleDate) {
+        if (opt.startDate && compare_month(defaultTime, opt.startDate) < 0) defaultTime = moment(opt.startDate).toDate();
+        if (opt.endDate && compare_month(defaultTime, opt.endDate) > 0) defaultTime = moment(opt.endDate).toDate();
+      }
+
+      return defaultTime;
+    }
+
+    function resetMonthsView(time) {
+      if (!time) {
+        time = getDefaultTime();
+      }
+
+      if (opt.lookBehind) {
+        showMonth(prevMonth(time), 'month1');
+        showMonth(time, 'month2');
+      } else {
+        showMonth(time, 'month1');
+        showMonth(nextMonth(time), 'month2');
+      }
+
+      if (opt.singleDate) {
+        showMonth(time, 'month1');
+      }
+
+      showSelectedDays();
+      showGap();
+    }
+
+    function outsideClickClose(evt) {
+      if (!IsOwnDatePickerClicked(evt, self[0])) {
+        if (box.is(':visible')) closeDatePicker();
+      }
+    }
+
+  };
+}));

文件差异内容过多而无法显示
+ 0 - 0
src/main/webapp/static/datapicker/moment-2.29.min.js


文件差异内容过多而无法显示
+ 0 - 0
src/main/webapp/static/datapicker/moment.min.js


文件差异内容过多而无法显示
+ 34 - 0
src/main/webapp/static/echarts/echarts.min.js


+ 354 - 0
src/main/webapp/static/modules/cmClubPortrait/cmClubEacths.js

@@ -0,0 +1,354 @@
+/**
+ * Created 机构订单图表 by zjy on 2023/02/10.
+ */
+const getDateStr = function(dd, addCount) {
+    dd.setDate(dd.getDate() + addCount);//获取addCount天后的日期
+    var y = dd.getFullYear();
+    var m = (dd.getMonth() + 1) < 10 ? "0" + (dd.getMonth() + 1) : (dd.getMonth() + 1);//获取当前月份的日期,不足10补0
+    var d = dd.getDate() < 10 ? "0" + dd.getDate() : dd.getDate();
+    return y + "/" + m + "/" + d;
+}
+// PC
+const isPC = ($(window).width() > 768);
+//默认参数
+const defaultParams = {
+    clubID:$('#clubId').val()*1,//  机构id
+    dateType:0,//   日期类别 0日 1月 2半年 3全年
+    startTime:'',//   开始时间
+    endTime:'',//   结束时间
+    type:0//  统计类别 0订单 1搜索关键词 2咨询记录 3访问记录 4初始状态
+}
+// 默认时间
+const startDate = getDateStr(new Date(), -365),
+      endDate = getDateStr(new Date(), 0);
+// 初始化订单选择时间控件
+const getInfoOrderDate = function () {
+    $('#orderDate').dateRangePicker({
+        language: 'cn',
+        startDate: startDate,
+        endDate: endDate,
+        format: 'YYYY-MM-DD',
+        showShortcuts: false,
+        autoClose: isPC,
+        isNowrap: false,
+        getValue: function () {
+            if (defaultParams.startTime && defaultParams.endTime) {
+                return defaultParams.startTime + ' to ' + defaultParams.endTime;
+            } else {
+                return '';
+            }
+        },
+        setValue: function (s, s1, s2) {
+            defaultParams.startTime = s1;
+            defaultParams.endTime = s2;
+            $('#orderTimeStart').val(s1);
+            $('#orderTimeEnd').val(s2);
+            if (defaultParams.startTime && defaultParams.endTime) {
+                getClubEacthsData(0,0)
+            }
+        }
+    });
+}
+// 初始化关键词选择时间控件
+const getInfoKeyWordsDate = function () {
+    $('#keyWordsDate').dateRangePicker({
+        language: 'cn',
+        startDate: startDate,
+        endDate: endDate,
+        format: 'YYYY-MM-DD',
+        showShortcuts: false,
+        autoClose: isPC,
+        isNowrap: false,
+        getValue: function () {
+            if (defaultParams.startTime && defaultParams.endTime) {
+                return defaultParams.startTime + ' to ' + defaultParams.endTime;
+            } else {
+                return '';
+            }
+        },
+        setValue: function (s, s1, s2) {
+            defaultParams.startTime = s1;
+            defaultParams.endTime = s2;
+            $('#keyWordsTimeStart').val(s1);
+            $('#keyWordsTimeEnd').val(s2);
+            if (defaultParams.startTime && defaultParams.endTime) {
+                getClubEacthsData(1,0)
+            }
+        }
+    });
+}
+// 初始化咨询选择时间控件
+const getInfoServiceDate = function () {
+    $('#serviceDate').dateRangePicker({
+        language: 'cn',
+        startDate: startDate,
+        endDate: endDate,
+        format: 'YYYY-MM-DD',
+        showShortcuts: false,
+        autoClose: isPC,
+        isNowrap: false,
+        getValue: function () {
+            if (defaultParams.startTime && defaultParams.endTime) {
+                return defaultParams.startTime + ' to ' + defaultParams.endTime;
+            } else {
+                return '';
+            }
+        },
+        setValue: function (s, s1, s2) {
+            defaultParams.startTime = s1;
+            defaultParams.endTime = s2;
+            $('#serviceTimeStart').val(s1);
+            $('#serviceTimeEnd').val(s2);
+            if (defaultParams.startTime && defaultParams.endTime) {
+                getClubEacthsData(2,0)
+            }
+        }
+    });
+}
+// 初始化访问记录选择时间控件
+const getInfoVisitDate = function () {
+    $('#visitDate').dateRangePicker({
+        language: 'cn',
+        startDate: startDate,
+        endDate: endDate,
+        format: 'YYYY-MM-DD',
+        showShortcuts: false,
+        autoClose: isPC,
+        isNowrap: false,
+        getValue: function () {
+            if (defaultParams.startTime && defaultParams.endTime) {
+                return defaultParams.startTime + ' to ' + defaultParams.endTime;
+            } else {
+                return '';
+            }
+        },
+        setValue: function (s, s1, s2) {
+            defaultParams.startTime = s1;
+            defaultParams.endTime = s2;
+            $('#visitTimeStart').val(s1);
+            $('#visitTimeEnd').val(s2);
+            if (defaultParams.startTime && defaultParams.endTime) {
+                getClubEacthsData(3,0)
+            }
+        }
+    });
+}
+// 数据接口请求
+const  getClubEacthsData = function (type,dateType) {
+    defaultParams.type = type;
+    defaultParams.dateType = dateType;
+    $.ajax({
+        url: $('#eachtsAjaxUrl').val(),
+        type: "GET",
+        data: defaultParams,
+        contentType : 'application/json;charset=UTF-8', //contentType很重要
+        success: function (data) {
+            if (data.code === 0) {
+                switch (type) {
+                    case 0:
+                        if(!data.order){
+                            $('#orderEacthsNone').show();
+                            $('#orderEacths').hide();
+                            $('.eachts-total').hide();
+                        }else{
+                            setOrderData(type,data)
+                        }
+                        break;
+                    case 1:
+                        if(!data.behavior){
+                            $('#keyWordsEacthsNone').show();
+                            $('#keyWordsEacths').hide();
+                        }else{
+                            setOtherData(type,data)
+                        }
+                        break;
+                    case 2:
+                        if(!data.remarks){
+                            $('#serviceEacthsNone').show();
+                            $('#serviceEacths').hide();
+                        }else{
+                            setOtherData(type,data)
+                        }
+                        break;
+                    case 3:
+                        if(!data.pageType){
+                            $('#visitEacthsNone').show();
+                            $('#visitEacths').hide();
+                        }else{
+                            setOtherData(type,data)
+                        }
+                        break;
+                }
+                defaultParams.startTime = '';
+                defaultParams.endTime = '';
+            } else {
+                console.log('机构订单图表数据异常')
+            }
+        }
+    });
+}
+// 设置订单数据
+const  setOrderData = function (type,data) {
+    const orderMap = {
+        0:{ // 订单
+            fn:function () {
+                $('.eachts-total').show();
+                $('#orderEacths').show();
+                $('#orderEacthsNone').hide();
+                $('#orderTimeEnd').val(data.order.endTime);
+                $('#orderTimeStart').val(data.order.startTime);
+                $('#orderTotalNum').text(`${data.order.orderTotalNum}个`);
+            },
+            id:'orderEacths',
+            series:{
+                name:'订单总量',
+                color:['#3aa0ff','#36cbcb','#fad337','#4dcb73','#f2637b','#975fe4'],
+                seriesData:data.order.orderList
+            },
+        }
+    }
+    getOrderEacths(orderMap[type].fn,orderMap[type].id,orderMap[type].series);
+}
+// 基于准备好的dom,初始化echarts实例
+const getOrderEacths = function (handleFn,id,data) {
+    // 基于准备好的dom,初始化echarts实例
+    handleFn();
+    const myChart = echarts.init(document.getElementById(id));
+    const option = {
+        tooltip: {
+            trigger: 'item'
+        },
+        legend: {
+            orient: 'vertical',
+            right: '2%',
+            top:'20%',
+            textStyle: {
+                fontSize: 14,
+            },
+        },
+        color:data.color,
+        series: [
+            {
+                name: data.name,
+                type: 'pie',
+                radius: '55%',
+                center: ['25%', '50%'],
+                avoidLabelOverlap: false,
+                emphasis: {
+                    itemStyle: {
+                        shadowBlur: 10,
+                        shadowOffsetX: 0,
+                        shadowColor: 'rgba(0, 0, 0, 0.5)'
+                    }
+                },
+                label: {
+                    show: false,
+                    position: 'center'
+                },
+                data:data.seriesData
+            }
+        ]
+    };
+    // 使用刚指定的配置项和数据显示图表。
+    myChart.setOption(option);
+    window.onresize = myChart.resize;//移动适配
+};
+// 其他三个图表
+const setOtherData = function (type,data) {
+    const dataMap = {
+        1:{// 关键词
+            fn:function () {
+                $('#keyWordsEacths').show();
+                $('#keyWordsEacthsNone').hide();
+                $('#keyWordsTimeEnd').val(data.behavior.endTime);
+                $('#keyWordsTimeStart').val(data.behavior.startTime);
+            },
+            id:'keyWordsEacths',
+            series:{
+                name:'搜索关键词',
+                color:'#e15616',
+                yAxisData:data.behavior.name,
+                seriesData:data.behavior.value
+            },
+        },
+        2:{// 咨询记录
+            fn:function () {
+                $('#serviceEacths').show();
+                $('#serviceEacthsNone').hide();
+                $('#serviceTimeEnd').val(data.remarks.endTime);
+                $('#serviceTimeStart').val(data.remarks.startTime);
+            },
+            id:'serviceEacths',
+            series:{
+                name:'咨询记录',
+                color:'#36cbcb',
+                yAxisData:data.remarks.name,
+                seriesData:data.remarks.value
+            },
+        },
+        3:{// 访问记录
+            fn:function () {
+                $('#visitEacths').show();
+                $('#visitEacthsNone').hide();
+                $('#visitTimeEnd').val(data.pageType.endTime);
+                $('#visitTimeStart').val(data.pageType.startTime);
+            },
+            id:'visitEacths',
+            series:{
+                name:'访问记录',
+                color:'#3aa0ff',
+                yAxisData:data.pageType.name,
+                seriesData:data.pageType.value
+            },
+        }
+    }
+    getOtherEacths(dataMap[type].fn,dataMap[type].id,dataMap[type].series);
+}
+// 其他三个图表
+const getOtherEacths = function (handleFn,id,data) {
+    // 基于准备好的dom,初始化echarts实例
+    handleFn();
+    const myChart = echarts.init(document.getElementById(id));
+    const option = {
+        title: {
+            show:false
+        },
+        tooltip: {
+            trigger: 'axis',
+            axisPointer: {
+                type: 'shadow'
+            }
+        },
+        legend: {
+            show:false,
+        },
+        grid: {
+            left: '3%',
+            right: '4%',
+            bottom: '3%',
+            containLabel: true
+        },
+        xAxis: {
+            type: 'value',
+            boundaryGap: [0, 0.01]
+        },
+        yAxis: {
+            type: 'category',
+            data: data.yAxisData
+        },
+        series: [
+            {
+                type: 'bar',
+                name: data.name,
+                data: data.seriesData,
+                itemStyle:{
+                    color:data.color,
+                    fontSize: 14,
+                }
+            }
+        ]
+    };
+    // 使用刚指定的配置项和数据显示图表。
+    myChart.setOption(option);
+    window.onresize = myChart.resize;//移动适配
+};

+ 136 - 0
src/main/webapp/static/modules/cmClubPortrait/cmClubPortrait.css

@@ -0,0 +1,136 @@
+/**
+ * Created 机构画像 by zjy on 2023/02/10.
+ */
+/***************cmClubPortrait.jsp************/
+.main-content{
+    width: 100%;
+    height: auto;
+    box-sizing: border-box;
+    padding: 0 40px;
+}
+.flex-content{
+    width: 100%;
+    height: 100%;
+    display: flex;
+}
+.flex-content .flex-box{
+    width: 700px;
+    height: 400px;
+    border:1px solid #e1e1e1 ;
+    margin-left: 20px;
+    margin-top: 20px;
+    box-shadow: 0px 3px 6px 0px rgb(0,0,0,0.07);
+    padding: 10px;
+    box-sizing: border-box;
+}
+.flex-box .box-title{
+    width: 100%;
+    height: 24px;
+    float: left;
+    line-height: 24px;
+}
+.flex-box .box-title span{
+    font-weight: bold;
+    font-size: 14px;
+    color: #333333;
+    margin-right: 20px;
+}
+.flex-box .box-title span a{
+    font-weight: normal;
+    color: #2fa4e7;
+}
+.flex-box .box-title span em{
+    font-style: normal;
+    font-weight: normal;
+    color: #2fa4e7;
+}
+.flex-box .box-title span a.line{
+    text-decoration: underline;
+}
+.flex-box .box-tabmain{
+    width: 100%;
+    height: 40px;
+    float: left;
+    line-height: 40px;
+}
+.flex-box .box-tabmain .box-tabs{
+    float: left;
+    color: #333333;
+}
+.flex-box .box-tabmain .box-tabs .box-tabs-li{
+    margin: 0 5px;
+    color: #333333;
+}
+.flex-box .box-tabmain .box-tabs-li.active{
+    color: #2fa4e7;
+}
+.flex-box .box-tabmain .box-time{
+    width: 320px;
+    height: 40px;
+    float: right;
+    box-sizing: border-box;
+    padding: 5px 0;
+}
+.flex-box .box-tabmain .box-time .time-input{
+    width: 148px;
+    box-sizing: border-box;
+    float: left;
+    position: relative;
+    border-radius: 2px;
+    height: 100%;
+}
+.flex-box .box-tabmain .box-time .time-input .input{
+    width: 100%;
+    height: 100%;
+    padding: 0 10px;
+    font-size: 12px;
+    line-height: 30px;
+    border-radius: 2px;
+    cursor: pointer;
+    margin-bottom: 0;
+    box-sizing: border-box;
+    float: left;
+}
+.flex-box .box-tabmain .box-time .line{
+    line-height: 30px;
+    font-size: 12px;
+    color: #627386;
+    margin: 0 5px;
+    display: inline-block;
+    float: left;
+}
+.flex-box .box-eachts{
+    width: 100%;
+    height: 316px;
+    float: left;
+    position: relative;
+}
+.flex-box .box-eachts .eachts-total{
+    color: #333333;
+    width: 50%;
+    height: 40px;
+    line-height: 40px;
+    font-size: 14px;
+    position: absolute;
+    bottom: 0;
+    left: 17%;
+}
+.flex-box .box-eachts .eachts-total span{
+    color: #3aa0ff;
+}
+.flex-box .box-eachts .eachts-data{
+    width: 100%;
+    height: 316px;
+}
+.flex-box .box-eachts .eachts-none{
+    width: 100%;
+    height: 316px;
+    display: none;
+}
+.flex-box .box-eachts .eachts-none p{
+    font-size: 30px;
+    font-weight: bold;
+    text-align: center;
+    line-height: 316px;
+    color: #333333;
+}

+ 55 - 0
src/main/webapp/static/modules/cmClubPortrait/cmClubPortrait.js

@@ -0,0 +1,55 @@
+/**
+ * Created 机构画像 by zjy on 2023/02/10.
+ */
+$(function(){
+    // 机构订单初始化时间
+    getInfoOrderDate();
+    // 机构搜索关键词初始化时间
+    getInfoKeyWordsDate();
+    // 机构咨询记录初始化时间
+    getInfoServiceDate();
+    // 机构访问记录初始化时间
+    getInfoVisitDate();
+    // 第一次执行查所有
+    getClubEacthsData(0,0);
+    getClubEacthsData(1,0);
+    getClubEacthsData(2,0);
+    getClubEacthsData(3,0);
+    // 点击筛选机构订单数据
+    $('#orderTabs').children("a").each(function (index) {
+        $(this).click(function () {
+            //alert(index);
+            $(this).addClass('active').siblings('a').removeClass('active');
+            let dateType = $(this).attr('data-type');
+            getClubEacthsData(0,dateType)
+        });
+    });
+    // 点击筛选机构搜索关键词数据
+    $('#keyWordTabs').children("a").each(function (index) {
+        $(this).click(function () {
+            //alert(index);
+            $(this).addClass('active').siblings('a').removeClass('active');
+            let dateType = $(this).attr('data-type');
+            getClubEacthsData(1,dateType)
+        });
+    });
+    // 点击筛选咨询记录数据
+    $('#serviceTabs').children("a").each(function (index) {
+        $(this).click(function () {
+            //alert(index);
+            $(this).addClass('active').siblings('a').removeClass('active');
+            let dateType = $(this).attr('data-type');
+            getClubEacthsData(2,dateType)
+        });
+    });
+    // 点击筛选机构访问记录数据
+    $('#visitTabs').children("a").each(function (index) {
+        $(this).click(function () {
+            //alert(index);
+            $(this).addClass('active').siblings('a').removeClass('active');
+            let dateType = $(this).attr('data-type');
+            getClubEacthsData(3,dateType)
+        });
+    });
+
+})

部分文件因为文件数量过多而无法显示