Browse Source

多画面展示功能调整

zhuth 6 years ago
parent
commit
c4c58e6037
25 changed files with 1450 additions and 174 deletions
  1. 78 0
      kanban-common/src/main/java/com/uas/kanban/util/ObjectUtils.java
  2. 13 0
      kanban-console/src/main/java/com/uas/kanban/controller/KanbanController.java
  3. 58 0
      kanban-console/src/main/java/com/uas/kanban/controller/PanelViewController.java
  4. 13 0
      kanban-console/src/main/java/com/uas/kanban/controller/ParameterController.java
  5. 13 0
      kanban-console/src/main/java/com/uas/kanban/dao/KanbanDao.java
  6. 47 0
      kanban-console/src/main/java/com/uas/kanban/dao/PanelViewDao.java
  7. 0 1
      kanban-console/src/main/java/com/uas/kanban/model/Logo.java
  8. 144 0
      kanban-console/src/main/java/com/uas/kanban/model/PanelView.java
  9. 65 0
      kanban-console/src/main/java/com/uas/kanban/model/ViewConfig.java
  10. 7 0
      kanban-console/src/main/java/com/uas/kanban/service/KanbanService.java
  11. 0 3
      kanban-console/src/main/java/com/uas/kanban/service/LogoService.java
  12. 33 0
      kanban-console/src/main/java/com/uas/kanban/service/PanelViewService.java
  13. 8 0
      kanban-console/src/main/java/com/uas/kanban/service/ParameterService.java
  14. 6 0
      kanban-console/src/main/java/com/uas/kanban/service/impl/KanbanServiceImpl.java
  15. 242 0
      kanban-console/src/main/java/com/uas/kanban/service/impl/PanelViewServiceImpl.java
  16. 91 0
      kanban-console/src/main/java/com/uas/kanban/service/impl/ParameterServiceImpl.java
  17. 1 1
      kanban-console/src/main/webapp/resources/app/controller/desktop.js
  18. 1 1
      kanban-console/src/main/webapp/resources/app/store/desktopboard.js
  19. 169 0
      kanban-console/src/main/webapp/resources/app/view/desktop/AreaView.js
  20. 411 164
      kanban-console/src/main/webapp/resources/app/view/desktop/BoardParamWindow.js
  21. 5 2
      kanban-console/src/main/webapp/resources/app/view/desktop/BoardWindow.js
  22. 2 2
      kanban-console/src/main/webapp/resources/app/view/user/UserInfo.js
  23. 43 0
      kanban-console/src/main/webapp/resources/css/desktop.css
  24. 0 0
      kanban-console/src/main/webapp/resources/js/boardshow/main.bundle.js
  25. 0 0
      kanban-console/src/main/webapp/resources/lib/boardshow/vendor.js

+ 78 - 0
kanban-common/src/main/java/com/uas/kanban/util/ObjectUtils.java

@@ -4,10 +4,13 @@ import com.alibaba.fastjson.JSONArray;
 import com.uas.kanban.annotation.NotEmpty;
 
 import java.io.*;
+import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 import java.util.*;
 import java.util.Map.Entry;
 
+import org.springframework.util.ClassUtils;
+
 /**
  * 对象工具类
  *
@@ -283,4 +286,79 @@ public class ObjectUtils {
         }
         return fields;
     }
+
+	public static boolean equals(Object obj, Object other) {
+		if (obj == null && other == null) {
+			return true;
+		}
+
+		if (obj != null && other == null) {
+			return false;
+		}
+		if (obj != null && other == null) {
+			return false;
+		}
+
+		return compareNotNull(obj, other);
+	}
+
+	// 非空比较
+	private static boolean compareNotNull(Object obj, Object other) {
+		if (obj.equals(other)) {
+			return true;
+		}
+		Class type = obj.getClass();
+		if (type != other.getClass()) {
+			return false;
+		}
+
+		// 简单类型
+		if (ClassUtils.isPrimitiveOrWrapper(type)) {
+			return comparePrimitiveType(obj, other);
+		}
+		// 数组
+		if (type.isArray()) {
+			return compareArray(obj, other);
+		}
+
+		Field[] fields = obj.getClass().getDeclaredFields();
+		for (Field field : fields) {
+			try {
+				field.setAccessible(true);
+				Object tmp1 = field.get(obj);
+				Object tmp2 = field.get(other);
+				if (!equals(tmp1, tmp2)) {
+					return false;
+				}
+			} catch (Exception e) {
+				e.printStackTrace();
+				return false;
+			}
+
+		}
+		return true;
+	}
+
+	private static boolean comparePrimitiveType(Object obj, Object other) {
+		if (obj.getClass().isPrimitive()) {
+			return obj == other;
+		} else {
+			return obj.equals(other);
+		}
+	}
+
+	private static boolean compareArray(Object obj, Object other) {
+		int len = Array.getLength(obj);
+		if (len != Array.getLength(other)) {
+			return false;
+		}
+		for (int i = 0; i < len; i++) {
+			Object o1 = Array.get(obj, i);
+			Object o2 = Array.get(other, i);
+			if(!equals(o1, o2)) {
+				return false;
+			}
+		}
+		return true;
+	}
 }

+ 13 - 0
kanban-console/src/main/java/com/uas/kanban/controller/KanbanController.java

@@ -44,6 +44,19 @@ public class KanbanController extends BaseController<Kanban> {
     public List<Kanban> getByPanelCode(@PathVariable("panelCode") String panelCode, HttpServletRequest request) {
         return kanbanService.getByPanelCode(panelCode);
     }
+    
+    /**
+     * 获取指定面板的已启用的看板
+     *
+     * @param panelCode 所指定的面板 code
+     * @param request   request
+     * @return 已启用的看板
+     */
+    @RequestMapping("/getEnableKanbans/byPanel/{panelCode}")
+    @ResponseBody
+    public List<Kanban> getEnableKanbansByPanelCode(@PathVariable("panelCode") String panelCode, HttpServletRequest request) {
+    	return kanbanService.getEnableKanbansByPanelCode(panelCode);
+    }
 
     /**
      * 校验 sql

+ 58 - 0
kanban-console/src/main/java/com/uas/kanban/controller/PanelViewController.java

@@ -0,0 +1,58 @@
+package com.uas.kanban.controller;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.uas.kanban.base.BaseController;
+import com.uas.kanban.exception.OperationException;
+import com.uas.kanban.model.PanelView;
+import com.uas.kanban.service.PanelViewService;
+
+/**
+ * 
+ * @author zhuth
+ * @since 2018/5/24/ 9:53
+ */
+@Controller
+@RequestMapping("/panelView")
+public class PanelViewController extends BaseController<PanelView> {
+	
+	@Autowired
+	PanelViewService panelViewService;
+	
+	/**
+     * 获取指定面板的多画面配置
+     *
+     * @param panelCode 所指定的面板 code
+     * @param request   request
+     * @return  多画面配置
+	 * @throws OperationException 
+     */
+    @RequestMapping("/get/byPanel/{panelCode}")
+    @ResponseBody
+    public PanelView getByPanelCode(@PathVariable("panelCode") String panelCode, HttpServletRequest request) throws OperationException {
+        return panelViewService.getByPanelCode(panelCode);
+    }
+    
+    /**
+     * 获取指定面板的多画面配置
+     *
+     * @param panelCode 所指定的面板 code
+     * @param request   request
+     * @return  多画面配置
+	 * @throws OperationException 
+     */
+    @RequestMapping("/parseData/{code}")
+    @ResponseBody
+    public Map<String, Object> parseData(@PathVariable("code") String code, Integer index, String kanbanCode, HttpServletRequest request) throws OperationException  {
+    	return panelViewService.parseData(code, index, kanbanCode);
+    }
+}

+ 13 - 0
kanban-console/src/main/java/com/uas/kanban/controller/ParameterController.java

@@ -44,6 +44,19 @@ public class ParameterController extends BaseController<Parameter> {
     public List<Parameter> getByPanelCode(@PathVariable("panelCode") String panelCode, HttpServletRequest request) {
         return parameterService.getByPanelCode(panelCode);
     }
+    
+    /**
+     * 获取指定面板解析了下拉项的参数
+     *
+     * @param panelCode 所指定的面板 code
+     * @param request   request
+     * @return 参数
+     */
+    @RequestMapping("/getParseSQLData/byPanel/{panelCode}")
+    @ResponseBody
+    public List<Parameter> getParseDataByPanelCode(@PathVariable("panelCode") String panelCode, HttpServletRequest request) {
+        return parameterService.getParseDataByPanelCode(panelCode);
+    }
 
     /**
      * 校验 sql

+ 13 - 0
kanban-console/src/main/java/com/uas/kanban/dao/KanbanDao.java

@@ -51,4 +51,17 @@ public class KanbanDao extends BaseDao<Kanban> {
         return findField(code, "panelCode", String.class);
     }
 
+
+	/**
+	 * 获取指定面板已启用的看板
+	 * @param panelCode  面板code
+	 * @return  已启用的看板
+	 */
+	public List<Kanban> findEnableKanbanByPanelCode(String panelCode) {
+		Query<Kanban> query = createQuery();
+        query.filter("panelCode", panelCode);
+        query.filter("enabled", true);
+        return find(query);
+	}
+
 }

+ 47 - 0
kanban-console/src/main/java/com/uas/kanban/dao/PanelViewDao.java

@@ -0,0 +1,47 @@
+package com.uas.kanban.dao;
+
+import com.uas.kanban.annotation.NotEmpty;
+import com.uas.kanban.base.BaseDao;
+import com.uas.kanban.model.PanelView;
+import com.uas.kanban.model.User;
+import com.uas.kanban.support.SystemSession;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * 面板画面
+ *
+ * @author zhuth
+ * @since 2018/5/24 9:54
+ */
+@Component
+public class PanelViewDao extends BaseDao<PanelView> {
+
+	@Override
+    protected Map<String, Object> globalFilter() {
+        User user = SystemSession.checkUser();
+        Map<String, Object> filters = new HashMap<>();
+        // 所有用户只能操作自己的画面
+        filters.put("userCode", user.codeNotEmpty());
+        return filters;
+    }
+	
+	@Override
+	public PanelView parse(String json) {
+		// TODO Auto-generated method stub
+		return super.parse(json);
+	}
+	
+	/**
+     * 获取指定面板的画面
+     *
+     * @param panelCode 所指定的面板 code
+     * @return 面板画面
+     */
+    public PanelView findByPanelCode(@NotEmpty("panelCode") String panelCode) {
+        return findOneBy("panelCode", panelCode);
+    }
+}

+ 0 - 1
kanban-console/src/main/java/com/uas/kanban/model/Logo.java

@@ -2,7 +2,6 @@ package com.uas.kanban.model;
 
 import org.mongodb.morphia.annotations.Entity;
 import com.uas.kanban.annotation.CollectionProperty;
-import com.uas.kanban.annotation.FieldProperty;
 import com.uas.kanban.base.BaseEntity;
 
 /**

+ 144 - 0
kanban-console/src/main/java/com/uas/kanban/model/PanelView.java

@@ -0,0 +1,144 @@
+package com.uas.kanban.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.mongodb.morphia.annotations.Entity;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.uas.kanban.annotation.CollectionProperty;
+import com.uas.kanban.annotation.FieldProperty;
+import com.uas.kanban.base.BaseEntity;
+
+/**
+ * 
+ * @author zhuth
+ * @since 2018/5/24 9:54
+ */
+@Entity
+@CollectionProperty(simpleName = "分屏画面")
+public class PanelView extends BaseEntity {
+	
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+
+	/**
+     * 所属面板
+     */
+	@FieldProperty(nullable = false)
+    private String panelCode;
+    
+    /**
+     * 面板的版本号
+     */
+    @FieldProperty(nullable = false)
+    private Long panelVersion;
+    
+    /**
+     * 关联用户
+     */
+    @FieldProperty(nullable = false)
+    private String userCode;
+    
+    /**
+     * 展示类型
+     */
+    private String viewType;
+    
+    /**
+     * 分屏展示数量
+     */
+    private int areaCount;
+    
+    /**
+     * 多画面行数
+     */
+    private int areaRows;
+    
+    /**
+     * 多画面列数
+     */
+    private int areaCols;
+    
+    /**
+     * 多画面配置
+     */
+    private List<ViewConfig> areaConfig;
+    
+    public String getPanelCode() {
+		return panelCode;
+	}
+	public void setPanelCode(String panelCode) {
+		this.panelCode = panelCode;
+	}
+	public Long getPanelVersion() {
+		return panelVersion;
+	}
+	public void setPanelVersion(Long panelVersion) {
+		this.panelVersion = panelVersion;
+	}
+	public String getUserCode() {
+		return userCode;
+	}
+	public void setUserCode(String userCode) {
+		this.userCode = userCode;
+	}
+	public String getViewType() {
+		return viewType;
+	}
+	public void setViewType(String viewType) {
+		this.viewType = viewType;
+	}
+	public int getAreaCount() {
+		return areaCount;
+	}
+	public void setAreaCount(int areaCount) {
+		this.areaCount = areaCount;
+	}
+	public int getAreaRows() {
+		return areaRows;
+	}
+	public void setAreaRows(int areaRows) {
+		this.areaRows = areaRows;
+	}
+	public int getAreaCols() {
+		return areaCols;
+	}
+	public void setAreaCols(int areaCols) {
+		this.areaCols = areaCols;
+	}
+	public List<ViewConfig> getAreaConfig() {
+		return areaConfig;
+	}
+	public void setAreaConfig(List<ViewConfig> areaConfig) {
+		this.areaConfig = areaConfig;
+	}
+	
+	@Override
+	public String toString() {
+		return "PanelView{"
+				+ "panelCode=" + panelCode
+				+ "panelVersion=" + panelVersion
+				+ "userCode=" + userCode
+				+ "viewType=" + viewType
+				+ "areaCount=" + areaCount
+				+ "areaRows=" + areaRows
+				+ "areaCols=" + areaCols
+				+ "areaConfig=" + areaConfig
+				+ "}" + super.toString();
+	}
+	
+    public List<JSONObject> getParameters() {
+    	List<ViewConfig> viewConfigs = this.areaConfig;
+    	List<JSONObject> parameterList = new ArrayList<JSONObject>();
+    	for(ViewConfig vc : viewConfigs) {
+    		String viewParameters = vc.getViewParameters();
+    		JSONObject obj = JSON.parseObject(viewParameters);
+    		parameterList.add(obj);
+    	}
+    	return parameterList;
+    }
+	
+}

+ 65 - 0
kanban-console/src/main/java/com/uas/kanban/model/ViewConfig.java

@@ -0,0 +1,65 @@
+package com.uas.kanban.model;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 
+ * @author zhuth
+ * @since 2018/5/28/ 2:53
+ */
+public class ViewConfig implements Serializable {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 画面顺序
+	 */
+	private int viewIndex;
+	
+	/**
+	 * 画面参数
+	 */
+	private String viewParameters;
+	
+	/**
+	 * 画面看板
+	 */
+	private List<String> viewKanbans;
+
+	public int getViewIndex() {
+		return viewIndex;
+	}
+
+	public void setViewIndex(int viewIndex) {
+		this.viewIndex = viewIndex;
+	}
+
+	public String getViewParameters() {
+		return viewParameters;
+	}
+
+	public void setViewParameters(String viewParameters) {
+		this.viewParameters = viewParameters;
+	}
+
+	public List<String> getViewKanbans() {
+		return viewKanbans;
+	}
+
+	public void setViewKanbans(List<String> viewKanbans) {
+		this.viewKanbans = viewKanbans;
+	}
+	
+	@Override
+	public String toString() {
+		return "ViewConfig{"
+				+ "viewIndex=" + viewIndex
+				+ "viewParameters=" + viewParameters
+				+ "viewKanbans=" + viewKanbans
+				+ "}";
+	}
+}

+ 7 - 0
kanban-console/src/main/java/com/uas/kanban/service/KanbanService.java

@@ -31,4 +31,11 @@ public interface KanbanService {
      */
     List<Kanban> getByPanelCode(@NotEmpty("panelCode") String panelCode);
 
+	/**
+	 * 获取指定面板已启用的看板
+	 * @param panelCode
+	 * @return 已启用的看板
+	 */
+	List<Kanban> getEnableKanbansByPanelCode(@NotEmpty("panelCode") String panelCode);
+
 }

+ 0 - 3
kanban-console/src/main/java/com/uas/kanban/service/LogoService.java

@@ -3,9 +3,6 @@
  */
 package com.uas.kanban.service;
 
-import java.util.List;
-
-import com.uas.kanban.annotation.NotEmpty;
 import com.uas.kanban.exception.OperationException;
 import com.uas.kanban.model.Logo;
 

+ 33 - 0
kanban-console/src/main/java/com/uas/kanban/service/PanelViewService.java

@@ -0,0 +1,33 @@
+package com.uas.kanban.service;
+
+import java.util.Map;
+
+import com.uas.kanban.annotation.NotEmpty;
+import com.uas.kanban.exception.OperationException;
+import com.uas.kanban.model.PanelView;
+
+/**
+ * 面板画面
+ *
+ * @author zhuth
+ * @since 2018/5/24 13:59
+ */
+public interface PanelViewService {
+	
+	/**
+     * 根据指定的面板画面code和顺序号,解析生成json数据传给前台
+     *
+     * @param index 画面index,可为空,为空时解析第一个画面数据
+     * @param code  画面 code, 可为空,为空时解析画面配置的第一个看板
+     * @return 解析生成的json
+     */
+	public Map<String, Object> parseData(@NotEmpty("code") String code, Integer index, String kanbanCode) throws OperationException;
+	
+	/**
+     * 获取指定面板的画面
+     *
+     * @param panelCode 所指定的面板 code
+     * @return 面板画面
+     */
+    PanelView getByPanelCode(@NotEmpty("panelCode") String panelCode) throws OperationException;
+}

+ 8 - 0
kanban-console/src/main/java/com/uas/kanban/service/ParameterService.java

@@ -21,4 +21,12 @@ public interface ParameterService {
      */
     List<Parameter> getByPanelCode(@NotEmpty("panelCode") String panelCode);
 
+	/**
+	 * 获取指定面板解析后的的参数
+	 * @param panelCode 所指定的面板 code
+	 * @return 解析后的参数
+	 */
+	List<Parameter> getParseDataByPanelCode(@NotEmpty("panelCode") String panelCode);
+
+    
 }

+ 6 - 0
kanban-console/src/main/java/com/uas/kanban/service/impl/KanbanServiceImpl.java

@@ -125,4 +125,10 @@ public class KanbanServiceImpl extends BaseService<Kanban> implements KanbanServ
         return kanbanDao.findByPanelCode(panelCode);
     }
 
+	@Override
+	public List<Kanban> getEnableKanbansByPanelCode(String panelCode) {
+		panelDao.checkExist(panelCode);
+        return kanbanDao.findEnableKanbanByPanelCode(panelCode);
+	}
+
 }

+ 242 - 0
kanban-console/src/main/java/com/uas/kanban/service/impl/PanelViewServiceImpl.java

@@ -0,0 +1,242 @@
+package com.uas.kanban.service.impl;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import javax.xml.transform.TransformerException;
+
+import org.dom4j.DocumentException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.uas.kanban.annotation.NotEmpty;
+import com.uas.kanban.base.BaseDao;
+import com.uas.kanban.base.BaseService;
+import com.uas.kanban.dao.KanbanDao;
+import com.uas.kanban.dao.PanelDao;
+import com.uas.kanban.dao.PanelViewDao;
+import com.uas.kanban.exception.OperationException;
+import com.uas.kanban.model.Kanban;
+import com.uas.kanban.model.Panel;
+import com.uas.kanban.model.PanelView;
+import com.uas.kanban.model.Parameter;
+import com.uas.kanban.model.ViewConfig;
+import com.uas.kanban.service.PanelViewService;
+import com.uas.kanban.service.ParameterService;
+import com.uas.kanban.support.DataSourceManager;
+import com.uas.kanban.support.KanbanParser;
+import com.uas.kanban.support.SystemSession;
+import com.uas.kanban.util.CollectionUtils;
+import com.uas.kanban.util.ObjectUtils;
+import com.uas.kanban.util.StringUtils;
+
+import me.chyxion.jdbc.NewbieJdbcSupport;
+
+/**
+ * 面板画面
+ *
+ * @author zhuth
+ * @since 2018/5/24 14:04
+ */
+@Service
+public class PanelViewServiceImpl extends BaseService<PanelView> implements PanelViewService {
+
+    @Autowired
+    private PanelViewDao panelViewDao;
+    
+    @Autowired
+    private PanelDao panelDao;
+    
+    @Autowired
+    private KanbanDao kanbanDao;
+    
+    @Autowired
+    private ParameterService parameterService;
+    
+    @Autowired
+    private DataSourceManager dataSourceManager;
+    
+    @Autowired
+    private KanbanParser kanbanParser;
+
+	@Override
+	public PanelView save(@NotEmpty("json") String json) {
+		PanelView panelView = panelViewDao.parse(json);
+		Panel panel = panelDao.checkExist(panelView.getPanelCode());
+		panelView.setPanelVersion(panel.getVersion());
+		return panelViewDao.save(panelView);
+	}
+
+	@Override
+	public int update(@NotEmpty("json") String json) throws IllegalArgumentException, OperationException {
+		PanelView newPanelView = panelViewDao.parse(json);
+		PanelView oldPanelView = panelViewDao.checkExist(newPanelView.getCode());
+		if(ObjectUtils.equals(newPanelView, oldPanelView)) {
+			return 0;
+		}
+		return panelViewDao.update(newPanelView);
+	}
+
+	@Override
+	public Map<String, Object> parseData(@NotEmpty("code") String code, Integer index, String kanbanCode) throws OperationException {
+		index = index == null ? 0 : index;
+		PanelView panelView = panelViewDao.checkExist(code);
+		BaseDao.checkFields(panelView);
+		Panel panel = panelDao.checkExist(panelView.getPanelCode());
+		List<ViewConfig> areaConfigs = panelView.getAreaConfig();
+		ViewConfig viewConfig = areaConfigs.get(index);
+		List<String> viewKanbans = viewConfig.getViewKanbans();
+		if(CollectionUtils.isEmpty(viewKanbans)) {
+			throw new IllegalStateException("该画面未配置可展示看板");
+		}
+		if (!StringUtils.isEmpty(kanbanCode)) {
+            if (!viewKanbans.contains(kanbanCode)) {
+                throw new IllegalArgumentException("看板不存在或未启用:" + kanbanCode);
+            }
+        } else {
+            kanbanCode = viewKanbans.get(0);
+        }
+		Kanban kanban = kanbanDao.checkExist(kanbanCode);
+        BaseDao.checkFields(kanban);
+        String content = kanban.getContent();
+        String title = kanban.getTitle();
+        if (StringUtils.isEmpty(content)) {
+            throw new IllegalStateException("看板内容为空:" + kanbanCode);
+        }
+        List<Parameter> parameters = parameterService.getParseDataByPanelCode(panel.getCode());
+        List<JSONObject> pvalues = panelView.getParameters();
+        JSONObject values = pvalues.get(index); 
+        for(Parameter parameter : parameters) {
+        	String value = values.getString(parameter.getCode());
+        	parameter.setValue(value);
+        }
+        // 解析看板
+        String kanbanContent;
+        try {
+            NewbieJdbcSupport jdbc = dataSourceManager.getJdbc(panel.getDataSourceCode());
+            kanbanContent = kanbanParser.parseXml(content, title, parameters, jdbc);
+        } catch (DocumentException e) {
+            throw new IllegalStateException("xml 解析出错", e);
+        } catch (TransformerException e) {
+            throw new IllegalStateException("xml 映射出错", e);
+        } catch (IOException e) {
+            throw new IllegalStateException("xml 转换出错", e);
+        } catch (SQLException e) {
+            throw new IllegalStateException("SQL 查询错误", e);
+        }
+        Map<String, Object> result = new HashMap<>();
+        Map<String, Object> instance = new HashMap<>();
+        instance.put("parameters", parameters);
+        instance.put("enabledKanbanCodes", viewKanbans);
+        instance.put("display", panel.getDisplay());
+        instance.put("switchFrequency", values.get("refreshFrequency"));
+        instance.put("refreshFrequency", values.get("refreshFrequency"));
+        result.put("instance", instance);
+        List<JSONObject> data = new ArrayList<>();
+        data.add(JSONObject.parseObject(kanbanContent));
+        result.put("data", data);
+        return result;
+	}
+
+	@Override
+	public PanelView getByPanelCode(String panelCode) throws OperationException {
+		PanelView panelView = panelViewDao.findByPanelCode(panelCode);
+		Panel panel = panelDao.checkExist(panelCode);
+		if(panelView == null || panel.getVersion() > panelView.getPanelVersion()) {
+			if(panelView != null) {
+				panelView = updatePanelView(panelCode, panelView);
+			} else {
+				panelView = generatePanelView(panelCode);
+			}
+		}
+        return panelView;
+	}
+
+	/**
+     * 更新面板多画面配置
+     *
+     * @param panelCode        面板 code
+     * @param oldPanelView 旧的画面配置
+     * @return 新的画面配置
+	 * @throws OperationException 
+	 * @throws IllegalArgumentException 
+     */
+	private PanelView updatePanelView(@NotEmpty("panelCode") String panelCode, @NotEmpty("oldPanelView") PanelView oldPanelView) throws IllegalArgumentException, OperationException {
+		Panel panel = panelDao.checkExist(panelCode);
+		PanelView panelView;
+		try{
+			panelView = ObjectUtils.clone(oldPanelView);
+		} catch (IOException | ClassNotFoundException e) {
+			throw new IllegalStateException("更新画面配置时,旧画面克隆失败", e);
+		}
+		panelView.setPanelVersion(panel.getVersion());
+		List<ViewConfig> viewConfigs = panelView.getAreaConfig();
+		List<Parameter> newParameter = parameterService.getParseDataByPanelCode(panel.getCode());
+		Iterator<Parameter> i = newParameter.iterator();
+		while(i.hasNext()) {
+			Parameter p = i.next();
+			for(ViewConfig viewConfig : viewConfigs) {
+				if(viewConfig.getViewParameters() == null) {
+					break;
+				}
+				JSONObject jsonObj = JSON.parseObject(viewConfig.getViewParameters());
+				// TODO 这里只取了String类型的值
+				if(jsonObj.getString(p.getCode()) != null) {
+					String value = jsonObj.getString(p.getCode());
+					List<Object> optionalValues = p.getOptionalValues();
+					List<String> values = new ArrayList<String>();
+					for(Object obj : optionalValues) {
+						values.add(obj.toString());
+					}
+					if(values.contains(value)) {
+						// 使用原值
+					} else {
+						// 使用新值
+						jsonObj.put(p.getCode(), values.get(0));
+					}
+				}
+				viewConfig.setViewParameters(JSON.toJSONString(jsonObj));
+			}
+		}
+		panelView.setAreaConfig(viewConfigs);
+		panelViewDao.update(panelView);
+		return panelView;
+	}
+	
+	/**
+     * 初始化面板多画面配置
+     *
+     * @param panelCode        面板 code
+     * @return 画面配置
+     */
+	private PanelView generatePanelView(@NotEmpty("panelCode") String panelCode) {
+		Panel panel = panelDao.checkExist(panelCode);
+		PanelView panelView = new PanelView();
+		panelView.setViewType("single");
+		panelView.setPanelCode(panel.getCode());
+		panelView.setPanelVersion(panel.getVersion());
+		panelView.setAreaRows(1);
+		panelView.setAreaCols(1);
+		panelView.setUserCode(SystemSession.getUser().codeNotEmpty());
+		List<ViewConfig> areaConfig = new ArrayList<ViewConfig>();
+		ViewConfig v = new ViewConfig();
+		v.setViewIndex(0);
+		v.setViewKanbans(new ArrayList<String>());
+		List<Parameter> parameters = parameterService.getParseDataByPanelCode(panelCode);
+		String parametersStr = "{";
+		for(Parameter p: parameters) {
+			parametersStr += ("\"" + p.getCode() + "\":\"" + p.getValue() + "\",");
+		}
+		parametersStr += "\"refreshFrequency\":5}";
+		v.setViewParameters(parametersStr);
+		areaConfig.add(v);
+		panelView.setAreaConfig(areaConfig);
+		return panelView;
+	}
+}

+ 91 - 0
kanban-console/src/main/java/com/uas/kanban/service/impl/ParameterServiceImpl.java

@@ -5,14 +5,27 @@ import com.uas.kanban.base.BaseService;
 import com.uas.kanban.dao.PanelDao;
 import com.uas.kanban.dao.ParameterDao;
 import com.uas.kanban.exception.OperationException;
+import com.uas.kanban.model.Panel;
 import com.uas.kanban.model.Parameter;
+import com.uas.kanban.model.Type;
 import com.uas.kanban.service.ParameterService;
+import com.uas.kanban.support.DataSourceManager;
+import com.uas.kanban.support.KanbanParser;
 import com.uas.kanban.util.CollectionUtils;
+
+import me.chyxion.jdbc.NewbieJdbcSupport;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.sql.SQLException;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * 参数
@@ -28,6 +41,14 @@ public class ParameterServiceImpl extends BaseService<Parameter> implements Para
 
     @Autowired
     private PanelDao panelDao;
+    
+    @Autowired
+    private KanbanParser kanbanParser;
+    
+    @Autowired
+    private DataSourceManager dataSourceManager;
+    
+    private Logger logger = LoggerFactory.getLogger(getClass());
 
     @Override
     public Parameter save(@NotEmpty("json") String json) {
@@ -119,4 +140,74 @@ public class ParameterServiceImpl extends BaseService<Parameter> implements Para
         return parameterDao.findByPanelCode(panelCode);
     }
 
+	@Override
+	public List<Parameter> getParseDataByPanelCode(String panelCode) {
+		Panel panel = panelDao.checkExist(panelCode);
+		List<Parameter> parameters = parameterDao.findByPanelCode(panelCode);
+		
+		try {
+			NewbieJdbcSupport jdbc = dataSourceManager.getJdbc(panel.getDataSourceCode());
+			parseSQLParameters(parameters, jdbc);
+		} catch (SQLException e) {
+			throw new IllegalStateException("参数解析错误", e);
+		}
+		return parameters;
+	}
+	
+	/**
+     * 解析 SQL 类型的参数
+     *
+     * @param parameters 参数
+     * @param jdbc       jdbc
+     */
+    private void parseSQLParameters(List<Parameter> parameters, NewbieJdbcSupport jdbc) {
+        if (CollectionUtils.isEmpty(parameters)) {
+            return;
+        }
+        for (Parameter parameter : parameters) {
+            parameter.mayInitValue();
+            // 如果是 SQL 类型,需要解析参数
+            if (parameter.getType() == Type.SQL) {
+                // 需要解析 optionalValues 里可选择的值
+                List<Object> optionalValues = parameter.getOptionalValues();
+                if (!CollectionUtils.isEmpty(optionalValues)) {
+                    if (optionalValues.size() > 1) {
+                        throw new IllegalArgumentException("SQL 类型的参数多于一个");
+                    }
+                    Object optionValue = optionalValues.get(0);
+                    optionalValues = getValue(jdbc, String.valueOf(optionValue));
+                    parameter.setOptionalValues(optionalValues);
+                    if (CollectionUtils.isEmpty(optionalValues)) {
+                        parameter.setValue(null);
+                        continue;
+                    }
+                    // 如果之前没有值,或者之前的值不是可选值的一项,取第一个可选值
+                    if (parameter.getValue() == null || !optionalValues.contains(parameter.getValue())) {
+                        parameter.setValue(CollectionUtils.isEmpty(optionalValues) ? null : optionalValues.get(0));
+                    }
+                }
+            }
+        }
+    }
+    
+    /**
+     * 获取 sql 执行结果
+     *
+     * @param jdbc jdbc
+     * @param sql  sql 查询语句
+     * @return 执行结果
+     */
+    private List<Object> getValue(@NotEmpty("jdbc") NewbieJdbcSupport jdbc, @NotEmpty("sql") String sql) {
+        List<Map<String, Object>> listMap = jdbc.listMap(kanbanParser.removeLastSemicolon(sql));
+        Map<String, List<Object>> map = kanbanParser.convert(listMap);
+        Set<String> keySet = map.keySet();
+        if (CollectionUtils.isEmpty(map)) {
+            return new ArrayList<>();
+        }
+        if (keySet.size() > 1) {
+            logger.error("参数解析结果不止一列:" + map);
+        }
+        return map.get(keySet.iterator().next());
+    }
+
 }

+ 1 - 1
kanban-console/src/main/webapp/resources/app/controller/desktop.js

@@ -2,7 +2,7 @@ Ext.QuickTips.init();
 Ext.define('erp.controller.desktop', {
     extend: 'Ext.app.Controller',
     views:['desktop.Desktop', 'desktop.BoardManageLeftPanel', 'desktop.BoardManageMainPanel', 'desktop.BoardManageRightPanel','user.UserSetting',
-    'core.trigger.TextTrigger', 'desktop.DataSourceWin'],
+    'core.trigger.TextTrigger', 'desktop.DataSourceWin', 'desktop.AreaView'],
     stores:['desktopboard','user'],
     init:function(){
     	var me = this;

+ 1 - 1
kanban-console/src/main/webapp/resources/app/store/desktopboard.js

@@ -1,6 +1,6 @@
 Ext.define('erp.store.desktopboard', {
 	extend: 'Ext.data.Store',
-    fields:['name', 'code', 'display', 'switchFrequency', 'iconCls','type', 'dataSourceCode'],
+    fields:['name', 'code', 'display', 'switchFrequency', 'iconCls','type', 'dataSourceCode', 'version'],
     proxy:{
     	type:'ajax',
     	url:'panel/get/all/',

+ 169 - 0
kanban-console/src/main/webapp/resources/app/view/desktop/AreaView.js

@@ -0,0 +1,169 @@
+Ext.define('erp.view.desktop.AreaView', {
+	extend: 'Ext.panel.Panel',
+	alias: 'widget.areaview',
+	id: 'areaView',
+	layout: 'column',
+	arearows: 1,
+	areacols: 1,
+	selectedCls: 'x-areaview-selected',
+	areaConfig: [],
+	initComponent: function() {
+		var me = this;
+		
+		Ext.apply(me, {
+			items: []
+		});
+		me.callParent(arguments);
+	},
+	listeners: {
+		layoutHeight: function(areaview) {
+			var panels = areaview.items.items;
+			Ext.Array.each(panels, function(panel) {
+				panel.fireEvent('layoutHeight', panel);
+			});
+		}
+	},
+	createArea: function(values) {
+		var me = this, panels = [], num = 1,
+			viewtype = values.viewtype,
+			areacount = values.areacount,
+			rows = values.arearows, 
+			cols = values.areacols;
+		
+		if(viewtype == 'more') {
+			rows = 1;
+			cols = areacount;
+		}
+		
+		var viewHeight = Ext.getCmp('areaView').getHeight(),
+			panelHeight = viewHeight / rows;
+		for(var i = 0; i < rows; i++) {
+			for(var j = 0; j < cols; j++) {
+				panels.push({
+					xtype: 'panel',
+					height: panelHeight,
+					columnWidth: 1/cols,
+					bodyCls: 'x-area-view',
+					areaConfig: me.oldAreaConfig[num-1] || {
+						viewIndex: num-1,
+						viewParameters: Ext.getCmp('paramForm').getDefaultValues(),
+						viewKanbans: []
+					},
+					index: num-1,
+					html: num++,
+					listeners: {
+						afterlayout: function(panel) {
+							if(me.layoutHeighted) {
+								return;
+							}
+							var viewHeight = Ext.getCmp('areaView').getHeight(),
+								panelHeight = viewHeight / rows;
+							me.layoutHeighted = true;
+							panel.setHeight(panelHeight);
+							setTimeout(function() {
+								me.layoutHeighted = false;
+							}, 50);
+						},
+						layoutHeight: function(panel) {
+							var viewHeight = Ext.getCmp('areaView').getHeight(),
+								panelHeight = viewHeight / rows;
+							panel.setHeight(panelHeight);
+						},
+						click: {
+							element: 'el',
+							fn: function(e,dom,el){
+								var panelEl = this, panel = Ext.getCmp(panelEl.id);
+								// 选中样式
+								me.clearSelected();
+								me.setSelected(panel.index);
+							}
+						},
+						mouseenter: {
+							element: 'el',
+							fn: function(e,dom,el){
+								var panelEl = this, panel = Ext.getCmp(panelEl.id);
+								/*debugger;*/
+							}
+						}
+					}
+				});
+			}
+		}
+		
+		me.clearSelected();
+		me.removeAll();
+		me.add(panels);
+		me.doLayout();
+		
+		me.setAreaConfig();
+		me.setSelected(me.currentSelectedIndex);
+	},
+	setAreaConfig: function() {
+		var me = this;
+		me.areaConfig = me.items.items.map(function(p, i) {
+			return p.areaConfig;
+		});
+	},
+	getAreaConfig: function() {
+		var me = this;
+		return me.areaConfig;
+	},
+	clearSelected: function() {
+		var me = this, areaPanels = me.items.items;
+		Ext.Array.each(areaPanels, function(areaPanel) {
+			areaPanel.removeCls(me.selectedCls);
+		});
+		var paramForm = Ext.getCmp('paramForm');
+		var template = Ext.getCmp('template');
+		template.addParamCombo(paramForm, []);
+	},
+	setSelected: function(index) {
+		var me = this;
+		if(index == undefined || index < 0) {
+			index = 0;
+		}
+		if((index+1 > me.items.items.length)) {
+			index = 0;
+		}
+		var panel = me.items.items[index];
+		panel.addCls(me.selectedCls);
+		me.currentSelectedIndex = index;
+		var areaConfig = me.areaConfig[index];
+		// 获得配置的参数数据以及勾选的看板
+		var paramForm = Ext.getCmp('paramForm');
+		var template = Ext.getCmp('template');
+		template.addParamCombo(paramForm, template.parameterItems, index+1);
+		// 赋值
+		if(areaConfig) {
+			if(areaConfig.viewParameters) {
+				var p = {
+					data: areaConfig.viewParameters,
+					getData: function() {
+						return this.data;
+					}
+				}
+				paramForm.loadRecord(p);
+			}
+			if(areaConfig.viewKanbans) {
+				// 勾选看板
+				var grid = Ext.getCmp('modelGrid');
+				grid.selectModels(areaConfig.viewKanbans);
+			}
+		}else {
+			Ext.getCmp('refreshFrequency').setValue(0);
+			Ext.getCmp('refreshFrequency').setValue(5);
+		}
+	},
+	setViewParameters: function(viewParameters) {
+		var me = this, index = me.currentSelectedIndex; me.areaConfig[index] = me.areaConfig[index] || {
+			viewIndex: index
+		};
+		me.areaConfig[index].viewParameters = viewParameters || me.areaConfig[index].viewParameters;
+	},
+	setViewModel: function(codes) {
+		codes = codes || [];
+		var me = this, index = me.currentSelectedIndex, panel = me.items.items[index];
+		panel.areaConfig.viewKanbans = codes;
+		me.areaConfig[index].viewKanbans = codes;
+	}
+});

+ 411 - 164
kanban-console/src/main/webapp/resources/app/view/desktop/BoardParamWindow.js

@@ -1,8 +1,9 @@
 Ext.define('erp.view.desktop.BoardParamWindow',{
     extend:'Ext.window.Window',
     alias:'widget.boardparamwin',
-    width:800,
-    height:450,
+    width: '80%',
+    height: '80%',
+    resizable: false,
     modal:true,
     layout:'border',
     id:'template',
@@ -11,9 +12,182 @@ Ext.define('erp.view.desktop.BoardParamWindow',{
     initComponent:function(){
         var me = this;
         me.items = [{
-            xtype:'form',
+        	xtype: 'panel',
+        	region: 'west',
+        	id: 'areaPanel',
+        	title: '多画面配置',
+        	collapsible: true,
+        	animCollapse: false,
+        	collapsed: true,
+        	layout: 'anchor',
+        	width: 300,
+        	items: [{
+        		xtype: 'form',
+        		id: 'areaForm',
+	        	layout: 'vbox',
+	        	anchor: '100% 40%',
+	        	defaults: {
+	        		margin: 5
+	        	},
+	        	items: [{
+	        		xtype: 'hidden',
+	        		fieldLabel: '多画面code',
+	        		name: 'viewcode'
+	        	}, {
+	        		xtype: 'combobox',
+	        		fieldLabel: '多画面展示方式',
+	        		name: 'viewtype',
+	        		editable: false,
+	        		allowBlank: false,
+	        		store: Ext.create('Ext.data.Store', {
+	        			fields: ['value', 'name'],
+	        			data: [{value: 'single', name: '单屏显示'}, {value: 'more', name: '多屏显示'}]
+	        		}),
+	        		queryMode: 'local',
+				    displayField: 'name',
+				    valueField: 'value',
+				    value: 'single',
+				    listeners: {
+				    	change: function(typefield) {
+				    		var areaForm = Ext.getCmp('areaForm'),
+				    			f = areaForm.getForm(),
+				    			countfield = f.findField('areacount'),
+				    			rowsfield = f.findField('arearows'),
+				    			colsfield = f.findField('areacols');
+				    		
+				    		if(typefield.getValue() == 'more') {
+				    			countfield.setValue(1);
+				    			countfield.show();
+				    			rowsfield.hide();
+				    			rowsfield.setValue(1);
+				    			colsfield.hide();
+				    			colsfield.setValue(1);
+				    		}else {
+				    			countfield.setValue(1);
+				    			countfield.hide();
+				    			rowsfield.setValue(1);
+				    			rowsfield.show();
+				    			colsfield.setValue(1);
+				    			colsfield.show();
+				    		}
+				    		var areaForm = Ext.getCmp('areaForm'),
+	        					areaView = Ext.getCmp('areaView'),
+				    			f = areaForm.getForm();
+	        				var values = f.getValues();
+		                    areaView.createArea(values);
+				    	}
+				    }
+	        	}, {
+	        		xtype: 'numberfield',
+	        		fieldLabel: '分屏数量',
+	        		name: 'areacount',
+	        		value: 1,
+	        		minValue: 1,
+	        		maxValue: 8,
+	        		hidden: true,
+	        		listeners: {
+	        			change: function(countfiedl) {
+	        				if(!countfiedl.isValid()) {
+	        					return;
+	        				}
+	        				var areaForm = Ext.getCmp('areaForm'),
+	        					areaView = Ext.getCmp('areaView'),
+				    			f = areaForm.getForm();
+	        				var values = f.getValues();
+		                    areaView.createArea(values);
+	        			}
+	        		}
+	        	}, {
+	        		xtype: 'numberfield',
+	        		fieldLabel: '多画面展示行数',
+	        		name: 'arearows',
+	        		value: 1,
+	        		minValue: 1,
+	        		maxValue: 2,
+	        		listeners: {
+	        			change: function(rowsfield) {
+	        				var colsfield = rowsfield.nextSibling();
+	        				if(!colsfield.isValid() || !rowsfield.isValid()) {
+	        					return;
+	        				}
+	        				me.refreshAreaView();
+	        			}
+	        		}
+	        	}, {
+	        		xtype: 'numberfield',
+	        		fieldLabel: '多画面展示列数',
+	        		name: 'areacols',
+	        		value: 1,
+	        		minValue: 1,
+	        		maxValue: 4,
+	        		listeners: {
+	        			change: function(colsfield) {
+	        				var rowsfield = colsfield.previousSibling();
+	        				if(!colsfield.isValid() || !rowsfield.isValid()) {
+	        					return;
+	        				}
+	        				me.refreshAreaView();
+	        			}
+	        		}
+	        	}],
+	        	loadData: function() {
+	        		var form = this,
+	        			record = me.record,
+	        			code = record.get('code');
+	        		
+	        		Ext.Ajax.request({
+		                url:'panelView/get/byPanel/' + code,
+		                method:'POST',
+		                callback:function(options, success, response){
+		                	Ext.getCmp('desktopDataView').getEl().unmask();
+		                    var f = form.getForm(),
+		                    	areaView = Ext.getCmp('areaView');
+		                    	
+		                    if(response.responseText){
+		                    	var res = Ext.decode(response.responseText),
+		                    		areaConfig = res.areaConfig,
+		                    		length = areaConfig.length;
+		                    	
+		                    	// 存在多画面展示时才默认打开多画面配置
+		                    	if(length > 1 || res.viewType == 'more') {
+		                    		var areaPanel = Ext.getCmp('areaPanel');
+		                    		areaPanel.expand();
+		                    		areaPanel.animCollapse = true;
+		                    	}
+		                    	areaConfig = areaConfig.map(function(c, i) {
+		                    		var p = c.viewParameters;
+		                    		c.viewParameters = Ext.decode(p);
+		                    		return c;
+		                    	});
+		                    	areaView.oldAreaConfig = areaConfig;
+		                    	
+		                    	f.findField('viewcode').setValue(res.code);
+		                    	f.findField('viewtype').setValue(res.viewType);
+		                    	f.findField('areacount').setValue(res.areaCount);
+		                    	f.findField('arearows').setValue(res.areaRows);
+		                    	f.findField('areacols').setValue(res.areaCols);
+		                    }
+		                    var values = f.getValues();
+		                    areaView.createArea(values);
+		                }
+	                });
+	        	}
+        	}, {
+        		xtype: 'areaview',
+        		id: 'areaView',
+        		anchor: '100% 60%'
+        	}],
+        	listeners: {
+        		expand: function() {
+        			var areaview = Ext.getCmp('areaView');
+        			areaview.fireEvent('layoutHeight', areaview);
+        		}
+        	}
+        }, {
+        	xtype:'form',
+        	region: 'center',
             id:'paramForm',
-            region: 'center',
+            anchor: '100% 100%',
             layout:'column',
             autoScroll: true,
             defaults:{
@@ -22,7 +196,7 @@ Ext.define('erp.view.desktop.BoardParamWindow',{
             },
             items:[{
                 xtype:'fieldset',
-                title:'参数设置',
+                title:'画面1参数设置',
                 hidden: true
             },{
                 xtype:'fieldset',
@@ -37,53 +211,25 @@ Ext.define('erp.view.desktop.BoardParamWindow',{
                     fieldLabel:'刷新/切换频率(秒/次)',
                     value:'5',
                     minValue:1,
-                    allowBlank:false
-                },/*{
-                    xtype:'numberfield',
-                    id:'switchFrequency',
-                    name:'switchFrequency',
-                    fieldLabel:'切换频率(秒/次)',
-                    minValue:3,
-                    value:'30',
-                    minValue:1
-                }*/]
+                    allowBlank:false,
+                    listeners: {
+                    	change: function(field) {
+                    		if(field.isValid())
+                    			me.setViewParameters();
+                    	}
+                    }
+                }]
             }],
-            /**
-             * 添加面板参数下拉组件
-             */
-            addParamCombo: function() {
-                var form = this;
-                var items = me.resData.parameters;
-                var paramFieldSet = form.items.items[0];
-                paramFieldSet.removeAll();
-                var comboxs = [];
-                Ext.Array.each(items, function(item, index) {
-                    var data = item.optionalValues ? item.optionalValues.map(function (v) {
-                        return {
-                            value: v,
-                            name: v
-                        }
-                    }) : []
-                    var combox = new Ext.form.field.ComboBox({
-                        fieldLabel: item.name,
-                        name: item.code,
-                        store: Ext.create('Ext.data.Store', {
-                            fields: ['value', 'name'],
-                            data: data
-                        }),
-                        queryMode: 'local',
-                        displayField: 'name',
-                        valueField: 'value',
-                        value: item.value || '',
-                        allowBlank: false,
-                    });
-                    comboxs.push(combox);
-                });
-                paramFieldSet.add(comboxs);
-                if(comboxs.length != 0) {
-                    paramFieldSet.show();
-                }
-                form.doLayout();
+            setDefaultValues: function(values) {
+            	this.defaultValues = values;
+            },
+            getDefaultValues: function() {
+            	return this.defaultValues;
+            },
+            getCusParams: function() {
+            	var values = this.getForm().getValues();
+            	delete values[refreshFrequency];
+            	return values;
             }
         },{
             xtype: 'grid',
@@ -107,38 +253,52 @@ Ext.define('erp.view.desktop.BoardParamWindow',{
                 }
             ],
             listeners: {
-                afterLayout: function(grid) {
-                    grid.getSelectionModel().deselectAll();
-                    grid.selectModel();
-                },
+                selectionchange: function(selectModel) {
+                	Ext.getCmp('areaView').setViewModel(selectModel.getSelection().map(function(s) {
+                		return s.get('code');
+                	}));
+                }
             },
-            loadGridData: function() {
+            loadGridData: function(callbackFunc) {
                 var grid = this;
-                res = me.resData.relatedKanbans || [];
-                grid.getStore().loadData(res);
-                grid.getStore().sort('enabled', 'DESC');
+                var record = me.record;
+        		var code = record.get('code');
+                Ext.Ajax.request({
+	                url:'kanban/getEnableKanbans/byPanel/' + code,
+	                method:'POST',
+	                callback:function(options, success, response){
+	                    if(response.responseText){
+	                    	var res = Ext.decode(response.responseText);
+                        	if(success) {
+                        		me.relatedKanbans = res;
+                        		grid.getStore().loadData(res);
+                        		
+                        		callbackFunc.call();
+                        	}else {
+                        		Ext.getCmp('desktopDataView').getEl().unmask();
+                        		showErrorMsg('失败', res.message);
+                        	}
+	                    }
+	                }
+                });
             },
-            selectModel: function() {
-                var grid = this;
-                if(!me.resData) {
-                    return;
+            selectModels: function(codes) {
+                var grid = this, allRecords = grid.store.data.items, selectRecords, selectRecord = [],
+                	selectModel = grid.getSelectionModel();
+                for(var i = 0; i < allRecords.length; i++) {
+                	var record = allRecords[i];
+                	if(codes.indexOf(record.get('code')) != -1) {
+                		selectRecord.push(record);
+                	}
                 }
-                var selectedModels = me.resData.relatedKanbans || [];
-                var modelStore = grid.getStore();
-                var records = [];
-                selectedModels.map(function(model) {
-                    var record = modelStore.findRecord('code',model['code']);
-                    if(record && model.enabled) {
-                        records.push(record);
-                    }
-                });
-                grid.getSelectionModel().select(records || []);
+                selectModel.deselectAll()
+                selectModel.select(selectRecord || []);
             },
             getSelectedModels: function() {
                 var grid = this;
                 var selectedModels = grid.getSelectionModel().getSelection();
                 return selectedModels || [];
-            },
+            }
         }];
         me.callParent(arguments);
     },
@@ -147,21 +307,16 @@ Ext.define('erp.view.desktop.BoardParamWindow',{
         text:'确定',
         formBind:true,
         handler:function(){
-            var me = Ext.getCmp('template');
-            var formpanel = Ext.getCmp('paramForm');
-            if(formpanel.isValid()) {
-				var modelGrid = Ext.getCmp('modelGrid');
-				if(modelGrid.getSelectedModels().length == 0) {
-					showErrorMsg('警告','请至少选中一个看板!');
-					return;
-				}
-				if(!me.checkFrequency()) {
-					return;
-				}
-				me.setFullScreen();
-                me.savePanelInstance();
-            }else {
-                showErrorMsg('警告', '有必填项未填!');
+            var me = Ext.getCmp('template'),
+            	areaView = Ext.getCmp('areaView'),
+                	areaConfig = areaView.getAreaConfig(),
+                	emptyKanbanIndex = [];
+                	
+            if(me.checkAreaConfig(areaConfig)) {
+            	if(Ext.getCmp('areaForm').getForm().findField('viewtype').getValue()=='single') {
+            		me.setFullScreen();
+            	}
+            	me.saveAreaView();
             }
         }
     },{
@@ -171,18 +326,73 @@ Ext.define('erp.view.desktop.BoardParamWindow',{
         }
     }],
     listeners: {
-        afterLayout: function(me) {
+        afterrender: function(me) {
             me.init();
         }
     },
+    /**
+     * 添加面板参数下拉组件
+     */
+    addParamCombo: function(form, items, areaIndex) {
+    	var me = this;
+        var paramFieldSet = form.items.items[0];
+        paramFieldSet.removeAll();
+        var comboxs = [];
+        Ext.Array.each(items, function(item, index) {
+            var data = item.optionalValues ? item.optionalValues.map(function (v) {
+                return {
+                    value: v,
+                    name: v
+                }
+            }) : []
+            var combox = new Ext.form.field.ComboBox({
+                fieldLabel: item.name,
+                name: item.code,
+                store: Ext.create('Ext.data.Store', {
+                    fields: ['value', 'name'],
+                    data: data
+                }),
+                queryMode: 'local',
+                displayField: 'name',
+                valueField: 'value',
+                value: item.value || '',
+                allowBlank: false,
+                areaIndex: areaIndex,
+                listeners: {
+                	change: function(field) {
+                		if(field.isValid())
+                			me.setViewParameters();
+                	}
+                }
+            });
+            comboxs.push(combox);
+        });
+        if(areaIndex) {
+        	paramFieldSet.setTitle('画面'+areaIndex+'参数设置');
+        }else {
+        	paramFieldSet.setTitle('参数设置');
+        }
+        paramFieldSet.add(comboxs);
+        if(comboxs.length != 0) {
+            paramFieldSet.show();
+        }
+        form.doLayout();
+        form.setDefaultValues(form.getForm().getValues());
+    },
     load: function() {
         var me = this;
+   		
         // 添加参数下拉框
         var paramForm = Ext.getCmp('paramForm');
-        paramForm.addParamCombo();
+        var items = me.parameterItems;
+        me.addParamCombo(paramForm, items, 1);
         // 读取看板grid数据
         var modelGrid = Ext.getCmp('modelGrid');
-        modelGrid.loadGridData();
+        modelGrid.loadGridData(function() {
+	        // 多画面配置
+	        var areaForm = Ext.getCmp('areaForm');
+	        areaForm.loadData();
+        });
     },
     init: function() {
         var me = this;
@@ -193,28 +403,17 @@ Ext.define('erp.view.desktop.BoardParamWindow',{
         view.getEl().mask('loading...');
         if(me.record){
             Ext.Ajax.request({
-                url:'panelInstance/get/byPanel/'+code,
+                url:'parameter/getParseSQLData/byPanel/'+code,
                 method:'POST',
                 callback:function(options, success, response){
-                    view.getEl().unmask();
                     if(response.responseText){
                         var res = Ext.decode(response.responseText);
                         if(success) {
                             var form = Ext.getCmp('paramForm');
-                            var formData = {
-                                data: {
-                                    refreshFrequency: res.refreshFrequency,
-                                    switchFrequency: res.refreshFrequency,
-                                },
-                                getData: function() {
-                                    return this.data
-                                }
-                            }
-                            form.loadRecord(formData);
-                            res.parameters = Ext.decode(res.parameters) || [];
-                            me.resData = res;
+                            me.parameterItems = res;
                             me.load();
                         }else {
+                        	view.getEl().unmask();
                             showErrorMsg('失败', res.message, Ext.getCmp('template'));
                         }
                     }
@@ -222,16 +421,29 @@ Ext.define('erp.view.desktop.BoardParamWindow',{
             });
         }
     },
-
-    /**
-     * 生成面板实例后打开展示界面
-     */
-    savePanelInstance: function() {
-        var me = this;
-        
-        var params = me.getBoardConfig();
+	saveAreaView: function() {
+		var me = this,
+			areaForm = Ext.getCmp('areaForm'),
+			areaFormValues = areaForm.getForm().getValues(),
+			areaCode = areaFormValues.viewcode,
+			type = areaCode ? 'update' : 'save',
+			areaView = Ext.getCmp('areaView'),
+			areaConfig = areaView.getAreaConfig();
+        var params = {
+        	panelCode: me.record.get('code'),
+        	panelVersion: me.record.get('version'),
+        	userCode: getCookie('code'),
+        	viewType: areaFormValues.viewtype,
+        	areaCount: areaFormValues.areacount,
+        	areaRows: areaFormValues.arearows,
+        	areaCols: areaFormValues.areacols,
+        	areaConfig: areaConfig
+        };
+        if(type == 'update') {
+        	params.code = areaCode;
+        }
         Ext.Ajax.request({
-            url:'panelInstance/updatePart/',
+            url:'panelView/' + type + '/',
             method:'POST',
             params:{
                 json:Ext.encode(params)
@@ -239,65 +451,88 @@ Ext.define('erp.view.desktop.BoardParamWindow',{
             callback:function(options,success,response){
                 var res = JSON.parse(response.responseText);
                 if(success) {
-                    me.viewBoard();
+                	var viewData = res;
+                	if(type == 'update') {
+			        	viewData = params;
+			        }else {
+			        	areaForm.getForm().findField('viewcode').setValue(res.code);
+			        }
+                    me.viewBoard(viewData);
                 }else {
                     showErrorMsg('失败', res.message);
                 }
             }
         });
-    },
-    getBoardConfig: function() {
-        var me = this;
-        var modelGrid = Ext.getCmp('modelGrid');
-        var selectedModelCodes = modelGrid.getSelectedModels().map(function(model) {
-            return model.get('code');
-        });
-        var relatedKanbans = me.resData.relatedKanbans.map(function(kanban) {
-            kanban.enabled = selectedModelCodes.indexOf(kanban.code) != -1;
-            return kanban;
-        });
-        var paramForm = Ext.getCmp('paramForm');
-        var config = paramForm.getForm().getValues();
-
-        var parameters = me.resData.parameters.map(function(p) {
-            p.value = config[p.code];
-            return p
-        })
-        return {
-            code: me.resData.code,
-            parameters: Ext.encode(parameters),
-            refreshFrequency: config.refreshFrequency,
-            switchFrequency: config.refreshFrequency,
-            relatedKanbans: relatedKanbans
+	},
+    /**
+     * 检查画面配置是否合法
+     */
+    checkAreaConfig: function(areaConfig) {
+    	var me = this,
+        	errorKanbanIndex = [],
+        	errorParamIndex = [],
+        	message = '';
+        	
+        for(var i = 0; i < areaConfig.length; i++) {
+        	var config = areaConfig[i],
+        		viewKanbans = config.viewKanbans;
+        	if(!(viewKanbans instanceof Array) || viewKanbans.length == 0) {
+        		errorKanbanIndex.push(i + 1);
+        	}
         }
-    },
-    checkFrequency:function(){
-        var me = this;
-        var refreshFreq = Ext.getCmp('refreshFrequency').value;
-        var switchFreq = Ext.getCmp('refreshFrequency').value;
-        if(switchFreq){
-            if(refreshFreq>switchFreq){
-                showErrorMsg('警告','刷新频率必须小于切换频率!');
-                return false;
-            }
+        if(errorKanbanIndex.length > 0 || errorParamIndex.length > 0) {
+        	message += errorKanbanIndex.length > 0 ? (areaConfig.length == 1 ? '' : ('画面[' + errorKanbanIndex.join() + ']')) + '未勾选看板' : '';
+        	showErrorMsg('错误', message);
+        	return false;
         }else {
-            var modelGrid = Ext.getCmp('modelGrid');
-            // 看板数量为2个以上时切换频率不可为空
-            if(modelGrid.getSelectedModels().length >= 2) {
-                showErrorMsg('警告','切换频率不可为空');
-                return false;
-            }
+        	return true;
         }
-        return true;
     },
-    viewBoard:function(){
-        var me = this;
-        // Ext.getCmp('template').close();
-        Ext.create('erp.view.desktop.BoardWindow',{
-            instanceCode:me.resData.code,
-            html:'<iframe src="boardshow?code=' + me.resData.code + '" width="100%" height="100%" style="border:none"></iframe>'
-        }).show();
+    viewBoard:function(viewData){
+        var me = this,
+        	viewType = viewData.viewType;
+        if(viewType == 'single') {
+        	Ext.create('erp.view.desktop.BoardWindow',{
+	        	items: me.createViewPanels(viewData)
+	        }).show();
+        }else if(viewType == 'more') {
+        	var code = viewData.code,
+        		areaConfig = viewData.areaConfig;
+        		
+        	areaConfig.map(function(c, i) {
+        		setTimeout(function() {
+        			window.open(basePath+'boardshow?code='+code+'&index='+i, code+'_'+i);
+        		}, 20);
+        	});
+        }
     },
+    createViewPanels: function(viewData) {
+		var code = viewData.code,
+			rows = viewData.areaRows,
+			cols = viewData.areaCols;
+		
+		//TODO 判断行*列是否=看板数
+		var me = this, panels = [], num = 1;
+		for(var i = 0; i < rows; i++) {
+			for(var j = 0; j < cols; j++) {
+				panels.push({
+					xtype: 'panel',
+					height: 80,
+					columnWidth: 1/cols,
+					bodyCls: 'x-board-view',
+					index: num-1,
+					html: '<iframe src="boardshow?code=' + code + '&index=' + (num-1) + '" width="100%" height="100%" style="border:none"></iframe>',
+					listeners: {
+						viewresize: function(panel, viewHeight) {
+							panel.setHeight(viewHeight / rows);
+						}
+					}
+				});
+				num++;
+			}
+		}
+		return panels;
+	},
     setFullScreen: function () {
         var element = document.documentElement;
         if (element.requestFullscreen) {
@@ -309,5 +544,17 @@ Ext.define('erp.view.desktop.BoardParamWindow',{
         } else if (element.msRequestFullscreen) {
             element.msRequestFullscreen();
         }
+    },
+    setViewParameters: function() {
+    	var areaView = Ext.getCmp('areaView');
+		var values = Ext.getCmp('paramForm').getForm().getValues();
+		areaView.setViewParameters(values);
+    },
+    refreshAreaView: function() {
+    	var form = Ext.getCmp('areaForm');
+    	var values = form.getForm().getValues();
+    	var view = Ext.getCmp('areaView');
+    	
+    	view.createArea(values);
     }
 }); 

+ 5 - 2
kanban-console/src/main/webapp/resources/app/view/desktop/BoardWindow.js

@@ -1,7 +1,6 @@
 Ext.define('erp.view.desktop.BoardWindow',{
 	extend:'Ext.window.Window',
 	alias:'widget.boardwindow',
-	instanceCode:null,
 	width:'100%',
 	height:'100%',
 	modal:true,
@@ -12,8 +11,9 @@ Ext.define('erp.view.desktop.BoardWindow',{
 	bodyBorder:false,
 	style:'border:none!important',
 	maximized:true,
-	id:'win',
+	id:'boardwin',
 	fullscreen:false,
+	layout: 'column',
 	listeners:{
 		resize:function( win, width, height, eOpts ){
 			Ext.Array.each(win.dockedItems.items,function(item){
@@ -23,6 +23,9 @@ Ext.define('erp.view.desktop.BoardWindow',{
 					item.show();
 				}
 			});
+			Ext.Array.each(win.items.items, function(item) {
+				item.fireEvent('viewresize', item, win.body.getHeight());
+			});
 		}
 	},
 	buttonAlign:'center',

+ 2 - 2
kanban-console/src/main/webapp/resources/app/view/user/UserInfo.js

@@ -10,7 +10,7 @@ Ext.apply(Ext.form.VTypes, {
             return false;
         }
     },
-    confirmPwdText: '两次输入的密码不一致!',
+    confirmPwdText: '两次输入的密码不一致!'
 });
 Ext.define('erp.view.user.UserInfo',{
 	extend:'Ext.window.Window',
@@ -58,7 +58,7 @@ Ext.define('erp.view.user.UserInfo',{
                 blankText: '请输入新密码',
                 fieldLabel: '新密码',
                 regex: /^[\s\S]{0,16}$/,
-                regexText: '密码长度不能超过16个字符',
+                regexText: '密码长度不能超过16个字符'
             }, {  
                 xtype: 'textfield',
                 name: 'newpassword2',

+ 43 - 0
kanban-console/src/main/webapp/resources/css/desktop.css

@@ -420,6 +420,49 @@ div.ux-taskbar div.x-toolbar {
     border-color:#c1bfc1
 }
 
+/*----------------------------------------------------
+    boardParamWin
+*/
+.x-area-view > span > div {
+	vertical-align: middle !important;
+	text-align: center;
+}
+.x-areaview-selected > div {
+	background-color: #4bc1c7;
+}
+#areaview-body + div +div {
+	top: 0 !important;
+	left: 0 !important;
+}
+#template-body .x-panel-header-default-horizontal .x-tool-after-title {
+	margin-left: 0 !important;
+}
+#template-body .x-panel-header-default-vertical {
+	padding: 5px 3px 5px 2px;
+}
+#template-body .x-panel-header-default-vertical .x-tool-before-title {
+	margin-left: 0 !important;
+}
+#template-body .x-tool-expand-right, .x-tool-collapse-right {
+	background-position-x: 0 !important;
+	background-position-y: -176px !important;
+	width: 16px !important;
+	height: 16px !important;
+}
+
+#template-body .x-tool-collapse-left {
+	background-position-x: 0 !important;
+	background-position-y: -192px !important;
+	width: 16px !important;
+	height: 16px !important;
+}
+/*----------------------------------------------------
+    boardview
+*/
+.x-board-view {
+	border: 0.5px solid black !important;
+}
+
 /*----------------------------------------------------
     boardModel GridSelecter
 */

File diff suppressed because it is too large
+ 0 - 0
kanban-console/src/main/webapp/resources/js/boardshow/main.bundle.js


File diff suppressed because it is too large
+ 0 - 0
kanban-console/src/main/webapp/resources/lib/boardshow/vendor.js


Some files were not shown because too many files changed in this diff