diff --git a/src/main/java/com/nis/domain/basics/ServiceDictInfo.java b/src/main/java/com/nis/domain/basics/ServiceDictInfo.java index 019d7ac11..c07a7aba4 100644 --- a/src/main/java/com/nis/domain/basics/ServiceDictInfo.java +++ b/src/main/java/com/nis/domain/basics/ServiceDictInfo.java @@ -10,6 +10,7 @@ import com.nis.domain.BaseEntity; import com.nis.domain.SysMenu; import com.nis.domain.SysUser; import com.nis.util.Configurations; +import com.nis.util.StringUtil; /** * 业务辅助表-业务字典信息表 * @author zsl @@ -33,7 +34,6 @@ public class ServiceDictInfo extends BaseEntity{ private Date editTime; //edit_time 修改时间 date Y private Integer levelNo; //层级 private List childrenList = new ArrayList();//子列表 - private Date beginDate; // 开始日期 private Date endDate; // 结束日期 @@ -42,14 +42,20 @@ public class ServiceDictInfo extends BaseEntity{ private String showSequence; //显示序号 - + private String pNames;//父节点名称 /** * 封装参数数据类型, * */ private List conditionType; - + @JsonIgnore + public String getpNames() { + return pNames; + } + public void setpNames(String pNames) { + this.pNames = pNames; + } public Integer getServiceDictId() { return serviceDictId; } @@ -250,5 +256,23 @@ public class ServiceDictInfo extends BaseEntity{ } + //获取所有父节点 + @JsonIgnore + public static String getPNames(List list,Integer pid,String pNames) { + String pName=""; + for (ServiceDictInfo serviceDictInfo : list) { + if(pid==serviceDictInfo.getServiceDictId()){ + pid=serviceDictInfo.getParent().getServiceDictId(); + pName=serviceDictInfo.getItemValue(); + pNames="/"+pName+pNames; + } + } + if(pid==0){ + if(!StringUtil.isEmpty(pNames)) pNames=pNames.substring(1); + return pNames; + }else{ + return getPNames(list, pid, pNames); + } + } } diff --git a/src/main/java/com/nis/exceptions/MultiPartNewException.java b/src/main/java/com/nis/exceptions/MultiPartNewException.java new file mode 100644 index 000000000..33af68d0b --- /dev/null +++ b/src/main/java/com/nis/exceptions/MultiPartNewException.java @@ -0,0 +1,59 @@ +package com.nis.exceptions; + +import static java.lang.String.format; + +import java.util.Properties; + +import org.springframework.web.multipart.MultipartException; + +public class MultiPartNewException extends MultipartException { + + private static final long serialVersionUID = 8922896505285617384L; + + public MultiPartNewException(String msg) { + super(msg); + } + public MultiPartNewException(Properties prop,Throwable ex) { + super(prop.get("file_upload_error").toString(),ex); + } + public MultiPartNewException(String msg,Throwable ex) { + + super(msg,ex); + } + + /** + * @param message The detail message. + * @param actual The actual request size. + * @param permitted The maximum permitted request size. + */ + public MultiPartNewException(String msg,long actual,long permitted,Properties prop,Throwable ex) { + + super(format(prop.get("total_file_upload_size_error").toString(), + Long.valueOf(actual),Long.valueOf(permitted)),ex); + } + + /**single file + * @param fileName + * @param message The detail message. + * @param actual The actual request size. + * @param permitted The maximum permitted request size. + */ + public MultiPartNewException(String msg,String fileName,long actual,long permitted,Properties prop,Throwable ex) { + + super(format(prop.get("single_file_upload_size_error").toString(), + fileName,Long.valueOf(actual), Long.valueOf(permitted)),ex); + } + + /**single file + * @param fileName + * @param message The detail message. + * @param permitted fileType. + */ + public MultiPartNewException(String msg,String fileName,String fileType,Properties prop,Throwable ex) { + + super(format(prop.get("file_upload_type_error").toString(), + fileName, fileType),ex); + } + + +} diff --git a/src/main/java/com/nis/interceptor/MultipartFileIntercepter.java b/src/main/java/com/nis/interceptor/MultipartFileIntercepter.java new file mode 100644 index 000000000..151757413 --- /dev/null +++ b/src/main/java/com/nis/interceptor/MultipartFileIntercepter.java @@ -0,0 +1,161 @@ +package com.nis.interceptor; + + +import static java.lang.String.format; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Properties; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.fileupload.FileUpload; +import org.apache.commons.fileupload.FileUploadBase; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.UploadContext; +import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.apache.commons.fileupload.servlet.ServletRequestContext; +import org.apache.log4j.Logger; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.util.MultiValueMap; +import org.springframework.web.multipart.MultipartException; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.commons.CommonsFileUploadSupport; +import org.springframework.web.multipart.commons.CommonsMultipartResolver; + +import com.nis.exceptions.MultiPartNewException; +import com.nis.util.Configurations; +import com.nis.util.Constants; +import com.nis.util.FileUtils; + + +public class MultipartFileIntercepter extends CommonsMultipartResolver{ + Logger logger = Logger.getLogger(MultipartFileIntercepter.class); + + + protected CommonsFileUploadSupport.MultipartParsingResult parseRequest(HttpServletRequest request)throws MultipartException{ + String encoding = determineEncoding(request); + //是否是样例文件 + boolean isSampleFileUpload = request.getRequestURI().contains(Constants.SAMPLE_UPLOAD_URL_KEYWORD); + FileUpload fileUpload = this.prepareFileUpload(encoding,isSampleFileUpload); + long fileUploadTotalSize=0l; + Properties languageProp=getMsgProp(); + try { + /*****************预先获取上传文件的总的大小************/ + FileUpload fileUploadTotal = fileUpload; + + ServletRequestContext ctx = new ServletRequestContext(request); + InputStream input=ctx.getInputStream(); + @SuppressWarnings("deprecation") // still has to be backward compatible + int contentLengthInt = ctx.getContentLength(); + + fileUploadTotalSize = UploadContext.class.isAssignableFrom(input.getClass()) + // Inline conditional is OK here CHECKSTYLE:OFF + ? ((UploadContext) ctx).contentLength() + : contentLengthInt; + // CHECKSTYLE:ON + logger.error("上传文件总大小为"+fileUploadTotalSize); + /*****************预先获取上传文件的总的大小************/ + //验证文件总大小 + if(fileUploadTotalSize > fileUpload.getSizeMax()){ + throw new MultiPartNewException("", fileUploadTotalSize, fileUpload.getSizeMax(),languageProp, null); + } + //设置文件上传SizeMax为总文件的大小,否则无法通过SizeLimit(总的文件大小)校验,就无法进行下面单个文件大小的校验 + fileUploadTotal.setSizeMax(fileUploadTotalSize); + + List fileItems = ((ServletFileUpload) fileUploadTotal).parseRequest(request); + MultipartParsingResult multipartParsingResult=parseFileItems(fileItems, encoding); + MultiValueMap files=multipartParsingResult.getMultipartFiles(); + //单个文件验证文件格式和文件大小 + validFileList(files,fileUpload,languageProp,isSampleFileUpload); + + return multipartParsingResult; + + } catch (FileUploadBase.SizeLimitExceededException ex) { + throw new MultiPartNewException("",fileUploadTotalSize,fileUpload.getSizeMax(),languageProp,ex); + } catch (FileUploadException ex) { + throw new MultiPartNewException(languageProp, ex); + }catch (IOException ex) { + throw new MultiPartNewException(languageProp, ex); + }catch (MultiPartNewException ex) { + throw ex; + }catch (Exception ex) { + throw new MultiPartNewException(languageProp, ex); + } + + } + /** + * 校验文件大小、类型 + * @return + * @throws FileSizeLimitExceededException + */ + protected void validFileList(MultiValueMap multipartFile,FileUpload fileUpload,Properties prop,boolean isSampleFileUpload) throws FileSizeLimitExceededException{ + String errorInfo=""; + + String fileType=""; + long fileMaxSize=0l; + if(isSampleFileUpload){ + fileType=Constants.SAMPLE_FILE_TYPE; + fileMaxSize=Constants.SAMPLE_SINGLE_FILE_MAX_SIZE; + }else{ + fileType=Constants.DIGEST_FILE_TYPE; + fileMaxSize=Constants.DIGEST_SINGLE_FILE_MAX_SIZE; + } + for (String fileName : multipartFile.keySet()) { + MultipartFile file= multipartFile.getFirst(fileName); + //文件类型错误 + if(fileType.indexOf(","+FileUtils.getSuffix(file.getOriginalFilename(), false)+",") == -1){ + throw new MultiPartNewException(errorInfo,file.getOriginalFilename(),fileType.substring(0,fileType.length()-1).substring(1),prop,null); + } + if(file.getSize() > fileMaxSize){ + throw new MultiPartNewException(errorInfo, file.getOriginalFilename(), file.getSize(), fileMaxSize,prop, null); + } + } + } + /** + * 构造FileUpload + * @param encoding + * @param isSampleFileUpload + * @return + */ + protected FileUpload prepareFileUpload(String encoding,boolean isSampleFileUpload) { + FileUpload fileUpload = getFileUpload(); + FileUpload actualFileUpload = fileUpload; + if (encoding != null && !encoding.equals(fileUpload.getHeaderEncoding())) { + actualFileUpload = newFileUpload(getFileItemFactory()); + actualFileUpload.setHeaderEncoding(encoding); + if(isSampleFileUpload){ + actualFileUpload.setSizeMax(Constants.SAMPLE_TOTAL_FILE_MAX_SIZE); + }else{ + actualFileUpload.setSizeMax(Constants.DIGEST_TOTAL_FILE_MAX_SIZE); + } + } + return actualFileUpload; + } + + /** + * 获取国际化配置文件 + * @return + */ + public Properties getMsgProp(){ + Properties msgProp = new Properties(); + try { + String language = LocaleContextHolder.getLocale().getLanguage(); + if(language.equals("zh_cn")||language.equals("zh")){ + msgProp.load(Configurations.class.getResourceAsStream("/messages/message_zh_CN.properties")); + }else if(language.equals("ru")){ + msgProp.load(Configurations.class.getResourceAsStream("/messages/message_ru.properties")); + }else{ + msgProp.load(Configurations.class.getResourceAsStream("/messages/message_en.properties")); + } + + } catch (Exception e) { + msgProp = null; + logger.error("未知i18n消息配置文件,请确定文件是否存在!",e); + } + return msgProp; + } + +} diff --git a/src/main/java/com/nis/util/Constants.java b/src/main/java/com/nis/util/Constants.java index 888426e03..75d2cd224 100644 --- a/src/main/java/com/nis/util/Constants.java +++ b/src/main/java/com/nis/util/Constants.java @@ -408,4 +408,12 @@ public final class Constants { public static final String REDIRECT_URL_KEY = Configurations.getStringProperty("redirect_url_key","url"); public static final String REDIRECT_CONTENT_KEY = Configurations.getStringProperty("redirect_content_key","content"); public static final String REDIRECT_RESPONSE_CODE_STARTWITH = Configurations.getStringProperty("redirect_response_code_startwith","30"); + + public static final String SAMPLE_UPLOAD_URL_KEYWORD = Configurations.getStringProperty("sample_upload_url_keyword","av"); + public static final String SAMPLE_FILE_TYPE = Configurations.getStringProperty("sample_file_type",""); + public static final long SAMPLE_SINGLE_FILE_MAX_SIZE = Configurations.getLongProperty("sample_single_file_max_size",10485760l);//10M + public static final long SAMPLE_TOTAL_FILE_MAX_SIZE = Configurations.getLongProperty("sample_total_file_max_size",52428800l);//50M + public static final String DIGEST_FILE_TYPE = Configurations.getStringProperty("digest_file_type",""); + public static final long DIGEST_SINGLE_FILE_MAX_SIZE = Configurations.getLongProperty("digest_single_file_max_size",10485760l);//10M + public static final long DIGEST_TOTAL_FILE_MAX_SIZE = Configurations.getLongProperty("digest_total_file_max_size",52428800l);//50M } diff --git a/src/main/java/com/nis/web/controller/BaseController.java b/src/main/java/com/nis/web/controller/BaseController.java index 0fbcc368e..359bf0282 100644 --- a/src/main/java/com/nis/web/controller/BaseController.java +++ b/src/main/java/com/nis/web/controller/BaseController.java @@ -48,6 +48,7 @@ import com.nis.util.Constants; import com.nis.util.DateUtils; import com.nis.util.DictUtils; import com.nis.util.JsonMapper; +import com.nis.util.StringUtil; import com.nis.util.excel.ExportExcel; import com.nis.web.service.ArchiveServcie; import com.nis.web.service.AreaService; @@ -277,20 +278,52 @@ public class BaseController { List requestInfos=requestInfoService.getAllRequestInfo(); model.addAttribute("requestInfos", requestInfos); List fls=serviceDictInfoService.findAllFlDict(); + String pNames=""; + for (ServiceDictInfo serviceDictInfo : fls) { + pNames=""; + pNames=serviceDictInfo.getPNames(fls, serviceDictInfo.getParent().getServiceDictId(), pNames); + serviceDictInfo.setpNames(pNames); + } model.addAttribute("fls", fls); List xzs=serviceDictInfoService.findAllXzDict(); + for (ServiceDictInfo serviceDictInfo : xzs) { + pNames=""; + pNames=serviceDictInfo.getPNames(xzs, serviceDictInfo.getParent().getServiceDictId(), pNames); + serviceDictInfo.setpNames(pNames); + } model.addAttribute("xzs", xzs); List lables=serviceDictInfoService.findAllLableDict(); + for (ServiceDictInfo serviceDictInfo : lables) { + pNames=""; + pNames=serviceDictInfo.getPNames(lables, serviceDictInfo.getParent().getServiceDictId(), pNames); + serviceDictInfo.setpNames(pNames); + } model.addAttribute("lables", lables); } protected void initPageCondition(Model model,BaseCfg cfg){ List requestInfos=requestInfoService.getAllRequestInfo(); model.addAttribute("requestInfos", requestInfos); List fls=serviceDictInfoService.findAllFlDict(); + String pNames=""; + for (ServiceDictInfo serviceDictInfo : fls) { + pNames=""; + pNames=serviceDictInfo.getPNames(fls, serviceDictInfo.getParent().getServiceDictId(), pNames); + serviceDictInfo.setpNames(pNames); + } model.addAttribute("fls", fls); List xzs=serviceDictInfoService.findAllXzDict(); + for (ServiceDictInfo serviceDictInfo : xzs) { + pNames=""; + pNames=serviceDictInfo.getPNames(xzs, serviceDictInfo.getParent().getServiceDictId(), pNames); + serviceDictInfo.setpNames(pNames); + } model.addAttribute("xzs", xzs); List lables=serviceDictInfoService.findAllLableDict(); + for (ServiceDictInfo serviceDictInfo : lables) { + pNames=""; + pNames=serviceDictInfo.getPNames(lables, serviceDictInfo.getParent().getServiceDictId(), pNames); + serviceDictInfo.setpNames(pNames); + } model.addAttribute("lables", lables); List regionList = DictUtils.getFunctionRegionDictList(cfg.getFunctionId()); model.addAttribute("regionList", regionList); @@ -315,10 +348,26 @@ public class BaseController { List requestInfos=requestInfoService.getValidRequestInfo(); model.addAttribute("requestInfos", requestInfos); List fls=serviceDictInfoService.findFlDict(); + String pNames=""; + for (ServiceDictInfo serviceDictInfo : fls) { + pNames=""; + pNames=serviceDictInfo.getPNames(fls, serviceDictInfo.getParent().getServiceDictId(), pNames); + serviceDictInfo.setpNames(pNames); + } model.addAttribute("fls", fls); List xzs=serviceDictInfoService.findXzDict(); + for (ServiceDictInfo serviceDictInfo : xzs) { + pNames=""; + pNames=serviceDictInfo.getPNames(xzs, serviceDictInfo.getParent().getServiceDictId(), pNames); + serviceDictInfo.setpNames(pNames); + } model.addAttribute("xzs", xzs); List lables=serviceDictInfoService.findLableDict(); + for (ServiceDictInfo serviceDictInfo : lables) { + pNames=""; + pNames=serviceDictInfo.getPNames(lables, serviceDictInfo.getParent().getServiceDictId(), pNames); + serviceDictInfo.setpNames(pNames); + } model.addAttribute("lables", lables); List itTypeList=new ArrayList(); itTypeList.add(Constants.ITEM_TYPE_AREA); @@ -337,10 +386,26 @@ public class BaseController { List requestInfos=requestInfoService.getValidRequestInfo(); model.addAttribute("requestInfos", requestInfos); List fls=serviceDictInfoService.findFlDict(); + String pNames=""; + for (ServiceDictInfo serviceDictInfo : fls) { + pNames=""; + pNames=serviceDictInfo.getPNames(fls, serviceDictInfo.getParent().getServiceDictId(), pNames); + serviceDictInfo.setpNames(pNames); + } model.addAttribute("fls", fls); List xzs=serviceDictInfoService.findXzDict(); + for (ServiceDictInfo serviceDictInfo : xzs) { + pNames=""; + pNames=serviceDictInfo.getPNames(xzs, serviceDictInfo.getParent().getServiceDictId(), pNames); + serviceDictInfo.setpNames(pNames); + } model.addAttribute("xzs", xzs); List lables=serviceDictInfoService.findLableDict(); + for (ServiceDictInfo serviceDictInfo : lables) { + pNames=""; + pNames=serviceDictInfo.getPNames(lables, serviceDictInfo.getParent().getServiceDictId(), pNames); + serviceDictInfo.setpNames(pNames); + } model.addAttribute("lables", lables); List itTypeList=new ArrayList(); itTypeList.add(Constants.ITEM_TYPE_AREA); @@ -399,10 +464,26 @@ public class BaseController { List requestInfos=requestInfoService.getValidRequestInfo();//只查询有效的 model.addAttribute("requestInfos", requestInfos); List fls=serviceDictInfoService.findFlDict();//只查询有效分类字典 + String pNames=""; + for (ServiceDictInfo serviceDictInfo : fls) { + pNames=""; + pNames=serviceDictInfo.getPNames(fls, serviceDictInfo.getParent().getServiceDictId(), pNames); + serviceDictInfo.setpNames(pNames); + } model.addAttribute("fls", fls); List xzs=serviceDictInfoService.findXzDict();//只查询有效性质字典 + for (ServiceDictInfo serviceDictInfo : xzs) { + pNames=""; + pNames=serviceDictInfo.getPNames(xzs, serviceDictInfo.getParent().getServiceDictId(), pNames); + serviceDictInfo.setpNames(pNames); + } model.addAttribute("xzs", xzs); List lables=serviceDictInfoService.findLableDict();//只查询有效标签字典 + for (ServiceDictInfo serviceDictInfo : lables) { + pNames=""; + pNames=serviceDictInfo.getPNames(lables, serviceDictInfo.getParent().getServiceDictId(), pNames); + serviceDictInfo.setpNames(pNames); + } model.addAttribute("lables", lables); List regionList = DictUtils.getFunctionRegionDictList(cfg.getFunctionId()); model.addAttribute("regionList", regionList); @@ -920,4 +1001,5 @@ public class BaseController { } return msg.toString(); } + } diff --git a/src/main/resources/messages/message_en.properties b/src/main/resources/messages/message_en.properties index b1d420d23..fc82a66db 100644 --- a/src/main/resources/messages/message_en.properties +++ b/src/main/resources/messages/message_en.properties @@ -728,5 +728,11 @@ userregion1=user region 1 userregion2=user region 2 userregion3=user region 3 userregion4=user region 4 -userregion5=user region 5 -#=============userregions=============== \ No newline at end of file +userregion5=user region 5 +#=============userregions=============== +#=============multipart upload error info================= +single_file_upload_size_error=The size of the file %s is %s,allowing the maximum value of a single file to be %s ! +total_file_upload_size_error=The total size of uploaded files is %s,allowing the total size of uploaded to be %s ! +file_upload_type_error=%s file type of error,allowing uploaded file type with %s! +file_upload_error=File upload failure ! +#=============multipart upload error info================= diff --git a/src/main/resources/messages/message_ru.properties b/src/main/resources/messages/message_ru.properties index 817e29bc6..7b3182b26 100644 --- a/src/main/resources/messages/message_ru.properties +++ b/src/main/resources/messages/message_ru.properties @@ -712,5 +712,11 @@ userregion1=user region 1 userregion2=user region 2 userregion3=user region 3 userregion4=user region 4 -userregion5=user region 5 -#=============userregions=============== \ No newline at end of file +userregion5=user region 5 +#=============userregions=============== +#=============multipart upload error info================= +single_file_upload_size_error=The size of the file %s is %s,allowing the maximum value of a single file to be %s ! +total_file_upload_size_error=The total size of uploaded files is %s,allowing the total size of uploaded to be %s ! +file_upload_type_error=%s file type of error,allowing uploaded file type with %s! +file_upload_error=File upload failure ! +#=============multipart upload error info================= diff --git a/src/main/resources/messages/message_zh_CN.properties b/src/main/resources/messages/message_zh_CN.properties index ef58bc120..511b6f996 100644 --- a/src/main/resources/messages/message_zh_CN.properties +++ b/src/main/resources/messages/message_zh_CN.properties @@ -829,5 +829,11 @@ userregion1=\u81EA\u5B9A\u4E49\u57DF1 userregion2=\u81EA\u5B9A\u4E49\u57DF2 userregion3=\u81EA\u5B9A\u4E49\u57DF3 userregion4=\u81EA\u5B9A\u4E49\u57DF4 -userregion5=\u81EA\u5B9A\u4E49\u57DF5 -#=============userregions=============== \ No newline at end of file +userregion5=\u81EA\u5B9A\u4E49\u57DF5 +#=============userregions=============== +#=============multipart upload error info================= +single_file_upload_size_error=\u6587\u4EF6%s\u7684\u5927\u5C0F\u4E3A%s\uFF0C\u5141\u8BB8\u5355\u4E2A\u6587\u4EF6\u7684\u6700\u5927\u503C\u4E3A%s\uFF01 +total_file_upload_size_error=\u4E0A\u4F20\u6587\u4EF6\u7684\u603B\u5927\u5C0F\u6700\u5927\u4E3A%s\uFF0C\u5141\u8BB8\u4E0A\u4F20\u7684\u6587\u4EF6\u603B\u5927\u5C0F\u4E3A%s\uFF01 +file_upload_type_error=%s\u6587\u4EF6\u7C7B\u578B\u51FA\u9519\uFF0C\u5141\u8BB8\u4E0A\u4F20\u7684\u6587\u4EF6\u7C7B\u578B\u6709%s\uFF01 +file_upload_error=\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25\uFF01 +#=============multipart upload error info================= \ No newline at end of file diff --git a/src/main/resources/nis.properties b/src/main/resources/nis.properties index ecf79fc71..2f2356be7 100644 --- a/src/main/resources/nis.properties +++ b/src/main/resources/nis.properties @@ -313,4 +313,17 @@ ipv6_ip_regexp=^\\s*((([0-9A-Fa-f]{1,4}\:){7}(([0-9A-Fa-f]{1,4})|\:))|(([0-9A-Fa redirect_response_code_key=code redirect_url_key=url redirect_content_key=content -redirect_response_code_startwith=30 +redirect_response_code_startwith=30 +#样例文件上传的uri关键词 +sample_upload_url_keyword=/av +#样例和摘要文件大小类型设置 +sample_file_type=,mp4,flv,ivf,mp2v, +#10M 10485760 +sample_single_file_max_size=10485760 +#12M 12582912 +sample_total_file_max_size=12582912 +digest_file_type=,txt,doc,img, +#10M10485760 +digest_single_file_max_size=10485760 +#12M12582912 +digest_total_file_max_size=12582912 \ No newline at end of file diff --git a/src/main/resources/spring-mvc.xml b/src/main/resources/spring-mvc.xml index 1d7acde45..edced67b4 100644 --- a/src/main/resources/spring-mvc.xml +++ b/src/main/resources/spring-mvc.xml @@ -157,7 +157,6 @@ - @@ -245,7 +244,11 @@ --> - + + + + @@ -257,15 +260,6 @@ - - - - - - - - diff --git a/src/main/webapp/WEB-INF/include/form/basicInfo.jsp b/src/main/webapp/WEB-INF/include/form/basicInfo.jsp index 1fd82e678..7e1881a82 100644 --- a/src/main/webapp/WEB-INF/include/form/basicInfo.jsp +++ b/src/main/webapp/WEB-INF/include/form/basicInfo.jsp @@ -1,6 +1,5 @@ <%@ page contentType="text/html;charset=UTF-8"%> - <%@ include file="/WEB-INF/include/taglib.jsp"%> -

+ <%@ include file="/WEB-INF/include/taglib.jsp"%>

@@ -162,7 +161,95 @@ --%> +
+
+ + + <%--
+
+
+ +
+
+ + + +
+ +
+ +
+
+
+
+ +
+
+ +
+ + +
+
+
--%> diff --git a/src/main/webapp/WEB-INF/include/header.jsp b/src/main/webapp/WEB-INF/include/header.jsp index 8283ffc77..76e97a4bc 100644 --- a/src/main/webapp/WEB-INF/include/header.jsp +++ b/src/main/webapp/WEB-INF/include/header.jsp @@ -32,6 +32,7 @@ + - \ No newline at end of file + + + \ No newline at end of file diff --git a/src/main/webapp/static/global/plugins/jquery-tree-multiselect/jquery.tree-multiselect.js b/src/main/webapp/static/global/plugins/jquery-tree-multiselect/jquery.tree-multiselect.js new file mode 100644 index 000000000..8b55354f7 --- /dev/null +++ b/src/main/webapp/static/global/plugins/jquery-tree-multiselect/jquery.tree-multiselect.js @@ -0,0 +1,1186 @@ +/* jQuery Tree Multiselect v2.5.2 | (c) Patrick Tsai | MIT Licensed */ +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 0 ? section.split(self.params.sectionDelimiter) : []; + for (var ii = 0; ii < sectionParts.length; ++ii) { + var sectionPart = sectionParts[ii]; + if (lookupPosition.children[sectionPart]) { + lookupPosition = lookupPosition.children[sectionPart]; + } else { + var newSection = Ast.createSection({ + treeId: self.id, + id: sectionId, + name: sectionPart + }); + ++sectionId; + + lookupPosition.arr.push(newSection); + var newLookupNode = Ast.createLookup(newSection.items); + lookupPosition.children[sectionPart] = newLookupNode; + lookupPosition = newLookupNode; + } + } + lookupPosition.arr.push(item); + }); + this.keysToAdd = Util.array.flatten(initialIndexItems); + Util.array.removeFalseyExceptZero(this.keysToAdd); + (_keysToAdd = this.keysToAdd).push.apply(_keysToAdd, keysToAddAtEnd); + Util.array.uniq(this.keysToAdd); + return data; +}; + +Tree.prototype.generateHtml = function (astArr, parentNode) { + for (var ii = 0; ii < astArr.length; ++ii) { + var astObj = astArr[ii]; + if (astObj.isSection()) { + this.astSections[astObj.id] = astObj; + + var createCheckboxes = this.params.allowBatchSelection; + var disableCheckboxes = this.params.freeze; + var node = astObj.render(createCheckboxes, disableCheckboxes); + parentNode.appendChild(node); + this.generateHtml(astObj.items, node); + } else if (astObj.isItem()) { + this.astItems[astObj.id] = astObj; + + var _createCheckboxes = !this.params.onlyBatchSelection; + var _disableCheckboxes = this.params.freeze; + var _node = astObj.render(_createCheckboxes, _disableCheckboxes); + parentNode.appendChild(_node); + } + } + +}; + +Tree.prototype.popupDescriptionHover = function () { + this.$selectionContainer.on('mouseenter', 'div.item > span.description', function () { + var $item = jQuery(this).parent(); + var description = $item.attr('data-description'); + + var descriptionDiv = document.createElement('div'); + descriptionDiv.className = 'temp-description-popup'; + descriptionDiv.innerHTML = description; + + descriptionDiv.style.position = 'absolute'; + + $item.append(descriptionDiv); + }); + + this.$selectionContainer.on('mouseleave', 'div.item > span.description', function () { + var $item = jQuery(this).parent(); + $item.find('div.temp-description-popup').remove(); + }); +}; + +Tree.prototype.handleSectionCheckboxMarkings = function () { + var self = this; + this.$selectionContainer.on('click', 'input.section[type=checkbox]', function () { + var $section = jQuery(this).closest('div.section'); + var $items = $section.find('div.item'); + var keys = $items.map(function (idx, el) { + var key = Util.getKey(el); + var astItem = self.astItems[key]; + if (!astItem.disabled && !astItem.isNotSearchHit()) { + return key; + } + }).get(); + + if (this.checked) { + var _self$keysToAdd; + + // TODO why does this always take this branch + (_self$keysToAdd = self.keysToAdd).push.apply(_self$keysToAdd, _toConsumableArray(keys)); + Util.array.uniq(self.keysToAdd); + } else { + var _self$keysToRemove; + + (_self$keysToRemove = self.keysToRemove).push.apply(_self$keysToRemove, _toConsumableArray(keys)); + Util.array.uniq(self.keysToRemove); + } + self.render(); + }); +}; + +Tree.prototype.redrawSectionCheckboxes = function ($section) { + $section = $section || this.$selectionContainer; + + // returns array; bit 1 is all children are true, bit 0 is all children are false + var returnVal = 3; + + var self = this; + var $childSections = $section.find('> div.section'); + $childSections.each(function () { + var result = self.redrawSectionCheckboxes(jQuery(this)); + returnVal &= result; + }); + + if (returnVal) { + var $childCheckboxes = $section.find('> div.item > input[type=checkbox]'); + for (var ii = 0; ii < $childCheckboxes.length; ++ii) { + if ($childCheckboxes[ii].disabled) { + // do nothing + } else if ($childCheckboxes[ii].checked) { + returnVal &= ~2; + } else { + returnVal &= ~1; + } + + if (returnVal === 0) { + break; + } + } + } + + var sectionCheckbox = $section.find('> div.title > input[type=checkbox]'); + if (sectionCheckbox.length) { + sectionCheckbox = sectionCheckbox[0]; + if (returnVal & 1) { + sectionCheckbox.checked = true; + sectionCheckbox.indeterminate = false; + } else if (returnVal & 2) { + sectionCheckbox.checked = false; + sectionCheckbox.indeterminate = false; + } else { + sectionCheckbox.checked = false; + sectionCheckbox.indeterminate = true; + } + } + + return returnVal; +}; + +Tree.prototype.addCollapsibility = function () { + var titleSelector = 'div.title'; + var $titleDivs = this.$selectionContainer.find(titleSelector); + + var collapseSpan = Util.dom.createNode('span', { class: 'collapse-section' }); + $titleDivs.prepend(collapseSpan); + + var sectionSelector = 'div.section'; + var $sectionDivs = this.$selectionContainer.find(sectionSelector); + + if (this.params.startCollapsed) { + $sectionDivs.addClass('collapsed'); + } + + this.$selectionContainer.on('click', titleSelector, function (event) { + if (event.target.nodeName === 'INPUT') { + return; + } + + var $section = jQuery(this).parent(); + $section.toggleClass('collapsed'); + event.stopPropagation(); + }); +}; + +Tree.prototype.createSearchBar = function (parentNode) { + var searchObj = new Search(SEARCH_HIT_ATTR, this.astItems, this.astSections, this.params.searchParams); + var searchDiv = Util.dom.createNode('div', { class: 'bs-searchbox'}); + var searchNode = Util.dom.createNode('input', { class: 'search form-control',type:'text', placeholder: 'Search...' }); + searchDiv.appendChild(searchNode); + parentNode.appendChild(searchDiv); + + this.$selectionContainer.on('input', 'input.search', function () { + var searchText = this.value; + searchObj.search(searchText); + }); +}; + +Tree.prototype.createSelectAllButtons = function (parentNode) { + var selectAllNode = Util.dom.createNode('span', { class: 'select-all', text: this.params.selectAllText }); + var unselectAllNode = Util.dom.createNode('span', { class: 'unselect-all', text: this.params.unselectAllText }); + + var selectAllContainer = Util.dom.createNode('div', { class: 'select-all-container' }); + selectAllContainer.appendChild(selectAllNode); + selectAllContainer.appendChild(unselectAllNode); + + parentNode.appendChild(selectAllContainer); + + var self = this; + this.$selectionContainer.on('click', 'span.select-all', function () { + var _self$keysToAdd2; + + (_self$keysToAdd2 = self.keysToAdd).push.apply(_self$keysToAdd2, _toConsumableArray(self.unfilteredNodeIds())); + self.render(); + }); + + this.$selectionContainer.on('click', 'span.unselect-all', function () { + var _self$keysToRemove2; + + (_self$keysToRemove2 = self.keysToRemove).push.apply(_self$keysToRemove2, _toConsumableArray(self.unfilteredNodeIds())); + self.render(); + }); +}; + +Tree.prototype.unfilteredNodeIds = function () { + var self = this; + return Object.keys(self.astItems).filter(function (key) { + return !self.astItems[key].node.hasAttribute(SEARCH_HIT_ATTR) || self.astItems[key].node.getAttribute(SEARCH_HIT_ATTR) === 'true'; + }); +}; + +Tree.prototype.armRemoveSelectedOnClick = function () { + var self = this; + this.$selectedContainer.on('click', 'span.remove-selected', function () { + var parentNode = this.parentNode; + var key = Util.getKey(parentNode); + self.keysToRemove.push(key); + self.render(); + }); +}; + +Tree.prototype.updateSelectedAndOnChange = function () { + var self = this; + this.$selectionContainer.on('click', 'input.option[type=checkbox]', function () { + var checkbox = this; + var selection = checkbox.parentNode; + var key = Util.getKey(selection); + Util.assert(key || key === 0); + + if (checkbox.checked) { + self.keysToAdd.push(key); + } else { + self.keysToRemove.push(key); + } + + self.render(); + }); + + if (this.params.sortable && !this.params.freeze) { + var startIndex = null; + var endIndex = null; + this.$selectedContainer.sortable({ + start: function start(event, ui) { + startIndex = ui.item.index(); + }, + + stop: function stop(event, ui) { + endIndex = ui.item.index(); + if (startIndex === endIndex) { + return; + } + Util.array.moveEl(self.selectedKeys, startIndex, endIndex); + self.render(); + } + }); + } +}; + +Tree.prototype.render = function (noCallbacks) { + var _selectedKeys, + _this = this; + + // fix arrays first + Util.array.uniq(this.keysToAdd); + Util.array.uniq(this.keysToRemove); + + Util.array.subtract(this.keysToAdd, this.selectedKeys); + Util.array.intersect(this.keysToRemove, this.selectedKeys); + + // check for max number of selections + if (Util.isInteger(this.params.maxSelections) && this.params.maxSelections > 0) { + var currentLength = this.keysToAdd.length - this.keysToRemove.length + this.selectedKeys.length; + if (currentLength > this.params.maxSelections) { + var _keysToRemove; + + var lengthToCut = currentLength - this.params.maxSelections; + var keysToCut = []; + if (lengthToCut > this.selectedKeys.length) { + keysToCut.push.apply(keysToCut, _toConsumableArray(this.selectedKeys)); + lengthToCut -= this.selectedKeys.length; + keysToCut.push.apply(keysToCut, _toConsumableArray(this.keysToAdd.splice(0, lengthToCut))); + } else { + keysToCut.push.apply(keysToCut, _toConsumableArray(this.selectedKeys.slice(0, lengthToCut))); + } + (_keysToRemove = this.keysToRemove).push.apply(_keysToRemove, keysToCut); + } + } + + // remove items first + for (var ii = 0; ii < this.keysToRemove.length; ++ii) { + // remove the selected divs + var node = this.selectedNodes[this.keysToRemove[ii]]; + if (node) { + // slightly more verbose than node.remove(), but more browser support + node.parentNode.removeChild(node); + this.selectedNodes[this.keysToRemove[ii]] = null; + } + + // uncheck these checkboxes + var selectionNode = this.astItems[this.keysToRemove[ii]].node; + selectionNode.getElementsByTagName('INPUT')[0].checked = false; + } + + Util.array.subtract(this.selectedKeys, this.keysToRemove); + + // now add items + for (var jj = 0; jj < this.keysToAdd.length; ++jj) { + // create selected divs + var key = this.keysToAdd[jj]; + var astItem = this.astItems[key]; + this.selectedKeys.push(key); + + var selectedNode = Util.dom.createSelected(astItem, this.params.freeze, this.params.showSectionOnSelected); + this.selectedNodes[astItem.id] = selectedNode; + this.$selectedContainer.append(selectedNode); + + // check the checkboxes + var inputNode = astItem.node.getElementsByTagName('INPUT')[0]; + if (inputNode) { + inputNode.checked = true; + } + } + + (_selectedKeys = this.selectedKeys).push.apply(_selectedKeys, _toConsumableArray(this.keysToAdd)); + Util.array.uniq(this.selectedKeys); + + // redraw section checkboxes + this.redrawSectionCheckboxes(); + + // now fix original select + var originalValsHash = {}; + // valHash hashes a value to an index + var valHash = {}; + for (var kk = 0; kk < this.selectedKeys.length; ++kk) { + var value = this.astItems[this.selectedKeys[kk]].value; + originalValsHash[this.selectedKeys[kk]] = true; + valHash[value] = kk; + } + // TODO is there a better way to sort the values other than by HTML? + // NOTE: the following does not work since jQuery duplicates option values with the same value + // this.$originalSelect.val(vals); + var options = this.$originalSelect.find('option').toArray(); + options.sort(function (a, b) { + var aValue = valHash[a.value] || 0; + var bValue = valHash[b.value] || 0; + return aValue - bValue; + }); + + this.$originalSelect.html(options); + this.$originalSelect.find('option').each(function (idx, el) { + this.selected = !!originalValsHash[Util.getKey(el)]; + }); + this.$originalSelect.change(); + + if (!noCallbacks && this.params.onChange) { + var optionsSelected = this.selectedKeys.map(function (key) { + return _this.astItems[key]; + }); + var optionsAdded = this.keysToAdd.map(function (key) { + return _this.astItems[key]; + }); + var optionsRemoved = this.keysToRemove.map(function (key) { + return _this.astItems[key]; + }); + this.params.onChange(optionsSelected, optionsAdded, optionsRemoved); + } + + this.keysToRemove = []; + this.keysToAdd = []; +}; + +module.exports = Tree; + +},{"./ast":3,"./search":7,"./ui-builder":9,"./utility":12}],9:[function(require,module,exports){ +'use strict'; + +function UiBuilder($el, hideSidePanel) { + var $tree = jQuery(''); + + var $selections = jQuery('
'); + if (hideSidePanel) { + $selections.addClass('no-border'); + } + $tree.append($selections); + + var $selected = jQuery('
'); + if (!hideSidePanel) { + $tree.append($selected); + } + + this.$el = $el; + this.$treeContainer = $tree; + this.$selectionContainer = $selections; + this.$selectedContainer = $selected; +} + +UiBuilder.prototype.attach = function () { + this.$el.after(this.$treeContainer); +}; + +UiBuilder.prototype.remove = function () { + this.$treeContainer.remove(); +}; + +module.exports = UiBuilder; + +},{}],10:[function(require,module,exports){ +"use strict"; + +// keeps if pred is true +function filterInPlace(arr, pred) { + var idx = 0; + for (var ii = 0; ii < arr.length; ++ii) { + if (pred(arr[ii])) { + arr[idx] = arr[ii]; + ++idx; + } + } + arr.length = idx; +} + +exports.flatten = function (arr, r) { + if (!Array.isArray(arr)) { + return arr; + } + + r = r || []; + + for (var ii = 0; ii < arr.length; ++ii) { + if (Array.isArray(arr[ii])) { + r.concat(exports.flatten(arr[ii], r)); + } else { + r.push(arr[ii]); + } + } + + return r; +}; + +exports.uniq = function (arr) { + var hash = {}; + + var pred = function pred(val) { + var returnVal = !hash[val]; + hash[val] = true; + return returnVal; + }; + filterInPlace(arr, pred); +}; + +exports.removeFalseyExceptZero = function (arr) { + var pred = function pred(val) { + return val || val === 0; + }; + filterInPlace(arr, pred); +}; + +exports.moveEl = function (arr, oldPos, newPos) { + var el = arr[oldPos]; + arr.splice(oldPos, 1); + arr.splice(newPos, 0, el); +}; + +exports.subtract = function (arr, arrExcluded) { + var hash = {}; + + for (var ii = 0; ii < arrExcluded.length; ++ii) { + hash[arrExcluded[ii]] = true; + } + + var pred = function pred(val) { + return !hash[val]; + }; + filterInPlace(arr, pred); +}; + +exports.intersect = function (arr, arrExcluded) { + var hash = {}; + + for (var ii = 0; ii < arrExcluded.length; ++ii) { + hash[arrExcluded[ii]] = true; + } + + var pred = function pred(val) { + return hash[val]; + }; + filterInPlace(arr, pred); +}; + +// takes in array of arrays +// arrays are presorted +exports.intersectMany = function (arrays) { + var indexLocations = []; + var maxIndexLocations = []; + arrays.forEach(function (array) { + indexLocations.push(0); + maxIndexLocations.push(array.length - 1); + }); + + var finalOutput = []; + for (; indexLocations.length > 0 && indexLocations[0] <= maxIndexLocations[0]; ++indexLocations[0]) { + // advance indices to be at least equal to first array element + var terminate = false; + for (var ii = 1; ii < arrays.length; ++ii) { + while (arrays[ii][indexLocations[ii]] < arrays[0][indexLocations[0]] && indexLocations[ii] <= maxIndexLocations[ii]) { + ++indexLocations[ii]; + } + if (indexLocations[ii] > maxIndexLocations[ii]) { + terminate = true; + break; + } + } + + if (terminate) { + break; + } + + // check element equality + var shouldAdd = true; + for (var jj = 1; jj < arrays.length; ++jj) { + if (arrays[0][indexLocations[0]] !== arrays[jj][indexLocations[jj]]) { + shouldAdd = false; + break; + } + } + + if (shouldAdd) { + finalOutput.push(arrays[0][indexLocations[0]]); + } + } + + return finalOutput; +}; + +},{}],11:[function(require,module,exports){ +'use strict'; + +exports.createNode = function (tag, props) { + var node = document.createElement(tag); + + if (props) { + for (var key in props) { + if (props.hasOwnProperty(key) && key !== 'text') { + node.setAttribute(key, props[key]); + } + } + if (props.text) { + node.textContent = props.text; + } + } + return node; +}; + +exports.createSelection = function (astItem, createCheckboxes, disableCheckboxes) { + var props = { + class: 'item', + 'data-key': astItem.id, + 'data-value': astItem.value + }; + var hasDescription = !!astItem.description; + if (hasDescription) { + props['data-description'] = astItem.description; + } + if (astItem.initialIndex) { + props['data-index'] = astItem.initialIndex; + } + var selectionNode = exports.createNode('div', props); + + if (hasDescription) { + var popup = exports.createNode('span', { class: 'description', text: '?' }); + selectionNode.appendChild(popup); + } + if (!createCheckboxes) { + selectionNode.innerText = astItem.text || astItem.value; + } else { + var optionLabelCheckboxId = 'treemultiselect-' + astItem.treeId + '-' + astItem.id; + var inputCheckboxProps = { + class: 'option', + type: 'checkbox', + id: optionLabelCheckboxId + }; + if (disableCheckboxes || astItem.disabled) { + inputCheckboxProps.disabled = true; + } + var inputCheckbox = exports.createNode('input', inputCheckboxProps); + // prepend child + selectionNode.insertBefore(inputCheckbox, selectionNode.firstChild); + + var labelProps = { + class: astItem.disabled ? 'disabled' : '', + for: optionLabelCheckboxId, + text: astItem.text || astItem.value + }; + var label = exports.createNode('label', labelProps); + selectionNode.appendChild(label); + } + + return selectionNode; +}; + +exports.createSelected = function (astItem, disableRemoval, showSectionOnSelected) { + var node = exports.createNode('div', { + class: 'item', + 'data-key': astItem.id, + 'data-value': astItem.value, + text: astItem.text + }); + + if (!disableRemoval && !astItem.disabled) { + var removalSpan = exports.createNode('span', { class: 'remove-selected', text: '×' }); + node.insertBefore(removalSpan, node.firstChild); + } + + if (showSectionOnSelected) { + var sectionSpan = exports.createNode('span', { class: 'section-name', text: astItem.section }); + node.appendChild(sectionSpan); + } + + return node; +}; + +exports.createSection = function (astSection, createCheckboxes, disableCheckboxes) { + var sectionNode = exports.createNode('div', { class: 'section', 'data-key': astSection.id }); + + var titleNode = exports.createNode('div', { class: 'title', text: astSection.name }); + if (createCheckboxes) { + var checkboxProps = { + class: 'section', + type: 'checkbox' + }; + if (disableCheckboxes) { + checkboxProps.disabled = true; + } + var checkboxNode = exports.createNode('input', checkboxProps); + titleNode.insertBefore(checkboxNode, titleNode.firstChild); + } + sectionNode.appendChild(titleNode); + return sectionNode; +}; + +},{}],12:[function(require,module,exports){ +'use strict'; + +exports.array = require('./array'); + +exports.assert = function (bool, message) { + if (!bool) { + throw new Error(message || 'Assertion failed'); + } +}; + +exports.dom = require('./dom'); + +exports.getKey = function (el) { + exports.assert(el); + return parseInt(el.getAttribute('data-key')); +}; + +exports.isInteger = function (value) { + var x; + if (isNaN(value)) { + return false; + } + x = parseFloat(value); + return (x | 0) === x; +}; + +},{"./array":10,"./dom":11}]},{},[1]); diff --git a/src/main/webapp/static/global/plugins/jquery-tree-multiselect/jquery.tree-multiselect.min.css b/src/main/webapp/static/global/plugins/jquery-tree-multiselect/jquery.tree-multiselect.min.css new file mode 100644 index 000000000..4fe45da4b --- /dev/null +++ b/src/main/webapp/static/global/plugins/jquery-tree-multiselect/jquery.tree-multiselect.min.css @@ -0,0 +1,2 @@ +/* jQuery Tree Multiselect v2.5.2 | (c) Patrick Tsai | MIT Licensed */ +div.tree-multiselect{border-radius:5px;display:table;height:inherit;width:100%}div.tree-multiselect>div.selected,div.tree-multiselect>div.selections{display:inline-block;box-sizing:border-box;overflow:auto;vertical-align:top;width:100%}div.tree-multiselect>div.selections div.item{margin-left:16px}div.tree-multiselect>div.selections div.item label{cursor:pointer;display:inline}div.tree-multiselect>div.selections div.item label.disabled{color:#D8D8D8}div.tree-multiselect>div.selections *[searchhit=false]{display:none}div.tree-multiselect>div.selections.no-border{border-right:none}div.tree-multiselect>div.selected>div.item{background:#EAEAEA;border-radius:2px;padding:2px 5px;overflow:auto}div.tree-multiselect>div.selected.ui-sortable>div.item:hover{cursor:move}div.tree-multiselect div.section>div.section,div.tree-multiselect div.section>div.item{padding-left:20px}div.tree-multiselect div.section.collapsed>div.title span.collapse-section:after{content:"+"}div.tree-multiselect div.section.collapsed:not([searchhit])>.item,div.tree-multiselect div.section.collapsed:not([searchhit])>.section{display:none}div.tree-multiselect div.title,div.tree-multiselect div.item{margin-bottom:2px}div.tree-multiselect div.title{background:#f6f6f6;color:#555;padding:2px}div.tree-multiselect div.title>*{display:inline-block}div.tree-multiselect div.title>span.collapse-section{margin:0 3px;width:8px}div.tree-multiselect div.title>span.collapse-section:after{content:"-"}div.tree-multiselect div.title:hover{cursor:pointer}div.tree-multiselect input[type=checkbox]{display:inline;margin-right:5px}div.tree-multiselect input[type=checkbox]:not([disabled]):hover{cursor:pointer}div.tree-multiselect span.remove-selected,div.tree-multiselect span.description{background:#777;border-radius:2px;color:white;margin-right:5px;padding:0 3px}div.tree-multiselect span.remove-selected:hover{cursor:pointer}div.tree-multiselect span.description:hover{cursor:help}div.tree-multiselect div.temp-description-popup{background:#EAEAEA;border:1px solid #676767;border-radius:3px;padding:5px}div.tree-multiselect span.section-name{float:right;font-style:italic}div.tree-multiselect .auxiliary{display:table;width:100%}div.tree-multiselect .auxiliary input.search{border-width:1px;border-style: solid solid solid solid;border-color: #D8D8D8;display:table-cell;margin:0;padding:5px;width:100%}div.tree-multiselect .auxiliary .select-all-container{display:table-cell;text-align:right}div.tree-multiselect .auxiliary .select-all-container span.select-all,div.tree-multiselect .auxiliary .select-all-container span.unselect-all{margin-right:5px;padding-right:5px}div.tree-multiselect .auxiliary .select-all-container span.select-all:hover,div.tree-multiselect .auxiliary .select-all-container span.unselect-all:hover{cursor:pointer}div.tree-multiselect .auxiliary .select-all-container span.select-all{border-right:2px solid #D8D8D8} .selectionsDiv{max-height: 169.367px; overflow-y: auto; min-height: 103px;} diff --git a/src/main/webapp/static/global/scripts/common.js b/src/main/webapp/static/global/scripts/common.js index 059eb9632..6f4e6c694 100644 --- a/src/main/webapp/static/global/scripts/common.js +++ b/src/main/webapp/static/global/scripts/common.js @@ -1,7 +1,14 @@ $(function(){ -/* var tree2 = $("#test-select-2").treeMultiselect({ - searchable: true - });*/ + var tree2 = $("select[name=lableTest]").treeMultiselect({ + searchable: true, + hideSidePanel:true, + startCollapsed:true + }); + var tree1 = $("select[name=classifyTest]").treeMultiselect({ + searchable: true, + hideSidePanel:true, + startCollapsed:true + }); //全选及取消 $("#checkAll").change(function(){ if($("#checkAll").prop("checked")){ @@ -874,6 +881,10 @@ var downLoadXLS=function(){ var pathName=window.document.location.pathname.substring(0,window.document.location.pathname.lastIndexOf("/")); window.location =pathName+"/import/template?functionId="+$("#functionId").val()+"&cfgRegionCode="+$("#cfgRegionCode").val(); } +//下载模板 +var openSelct=function(obj){ + $(obj).parent().parent().find(".tree-multiselect").removeClass("hidden"); +} //导入配置 var importCfg=function(){ if($("#serviceId").val()==""){