diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..5c3ac53 --- /dev/null +++ b/.classpath @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eaa19e7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target/* +.idea/* diff --git a/.project b/.project new file mode 100644 index 0000000..8817c2e --- /dev/null +++ b/.project @@ -0,0 +1,48 @@ + + + svnadmin + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + org.springframework.ide.eclipse.boot.validation.springbootbuilder + + + + + + org.springframework.ide.eclipse.core.springnature + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/.settings/.jsdtscope b/.settings/.jsdtscope new file mode 100644 index 0000000..2418123 --- /dev/null +++ b/.settings/.jsdtscope @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..29abf99 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..6e80039 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component new file mode 100644 index 0000000..c8a6ba1 --- /dev/null +++ b/.settings/org.eclipse.wst.common.component @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml b/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml new file mode 100644 index 0000000..6d59853 --- /dev/null +++ b/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..ca8d96f --- /dev/null +++ b/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.container b/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 0000000..3bd5d0a --- /dev/null +++ b/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.name b/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 0000000..05bd71b --- /dev/null +++ b/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/.settings/org.eclipse.wst.validation.prefs b/.settings/org.eclipse.wst.validation.prefs new file mode 100644 index 0000000..04cad8c --- /dev/null +++ b/.settings/org.eclipse.wst.validation.prefs @@ -0,0 +1,2 @@ +disabled=06target +eclipse.preferences.version=1 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f7baecd --- /dev/null +++ b/LICENSE @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "{}" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright 2017 微笑风采 + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d73dbb4 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# SvnAdmin frok from `https://git.oschina.net/hpboys/svnadmin.git` + +## 说明:本系统用于配合silksvn服务器使用,不支持Visual SvnServer。 + +#### 致力于成为一个安全流畅,极简可靠的SVN管理工具 +> 主要功能 +- SVN仓库创建,管理; +- SVN用户,用户组创建,管理; +- SVN资源权限授权; +- 用户权限查看,密码更改; +- SVN仓库支持多库模式; + +> 获取老司机的带路: + +SVN管理系统-交流群 + + +> 一、使用源码开发部署步骤: +1. 下载项目源码; +1. 找到文件 test\resources\svnadmin_init.sql 进行执行初始化; +1. 默认root账户:root/root +1. 删除所有账户,进行登录,则可以重新初始化管理员账号; +1. SVN认证账户和登录账户默认一致; + + +> 二、使用部署包直接部署步骤: +1. 下载最新部署包([点此下载]());TODO +1. 找到文件 sql\svnadmin_init.sql 进行执行初始化; +1. 配置数据库连接信息,配置文件位置:WEB-INF/classes/jdbc.properties +1. 部署到tomcat等Web容器中即可;环境推荐JDK1.8 / Tomcat8 +1. 默认root账户:root/root +1. 删除所有账户,进行登录,则可以重新初始化管理员账号; +1. SVN认证账户和登录账户默认一致; + + +> 三、使用多库启动模式: +TODO diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..758eb52 --- /dev/null +++ b/pom.xml @@ -0,0 +1,336 @@ + + 4.0.0 + org.svnadmin + svnadmin + 3.0.6 + war + + + svnadmin + UTF-8 + + true + + 1.7.6 + 3.2.18.RELEASE + 4.8.2 + 2.6 + 1.4 + 1.5.5 + 2.0.1 + 1.1.1 + 1.2.16 + + 1.9.13 + + 6.0.37 + + 1.2 + + 7.0 + + 6.0.37 + + 5.1.14 + 10.2.0.3.0 + + + 5.2.4.Final + + + + + + javax + javaee-api + ${javaee-api.version} + + + + jstl + jstl + ${jstl.version} + + + + org.apache.tomcat + servlet-api + ${servlet-api-version} + + + + org.apache.tomcat + jsp-api + ${jsp-api-version} + + + + org.tmatesoft.svnkit + svnkit + ${svnkit.version} + + + + + org.springframework + spring-core + ${spring.version} + + + org.springframework + spring-beans + ${spring.version} + + + org.springframework + spring-context + ${spring.version} + + + + org.apache.geronimo.specs + geronimo-annotation_1.0_spec + 1.1.1 + + + + + org.springframework + spring-aop + ${spring.version} + + + org.aspectj + aspectjweaver + 1.6.8 + + + cglib + cglib-nodep + 2.2 + + + + + org.springframework + spring-orm + ${spring.version} + + + + org.springframework + spring-web + ${spring.version} + + + + org.springframework + spring-webmvc + ${spring.version} + + + + + org.springframework + spring-jdbc + ${spring.version} + + + + + + + org.codehaus.jackson + jackson-mapper-asl + ${jackson-version} + + + + commons-lang + commons-lang + ${commons-lang.version} + jar + + + commons-dbcp + commons-dbcp + ${commons-dbcp.version} + + + + commons-pool + commons-pool + ${commons-pool.version} + jar + + + commons-io + commons-io + ${commons-io.version} + + + + + commons-logging + commons-logging + ${commons-logging.version} + + + log4j + log4j + ${log4j.version} + + + + + mysql + mysql-connector-java + ${jdbc.mysql.version} + jar + runtime + + + + + org.hibernate + hibernate-validator + ${hibernate-validator.version} + + + + + + + + + svnkit_repository + + true + + + false + + http://maven.svnkit.com/maven2/ + + + + + ${war.name} + + + src/main/resources + true + + version.properties + + + + src/main/resources + false + + version.properties + + + + + + org.apache.maven.plugins + maven-war-plugin + 2.1.1 + + ${war.archiveClasses} + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.8 + 1.8 + ${project.build.sourceEncoding} + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.5 + + ${project.build.sourceEncoding} + + + + + org.apache.maven.plugins + maven-source-plugin + 2.1.2 + + + attach-sources + package + + jar + + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + true + + ${project.build.outputDirectory}/META-INF/zip.xml + + + + + package + + single + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/svnadmin/common/annotation/AdminAuthPassport.java b/src/main/java/org/svnadmin/common/annotation/AdminAuthPassport.java new file mode 100644 index 0000000..12b6e18 --- /dev/null +++ b/src/main/java/org/svnadmin/common/annotation/AdminAuthPassport.java @@ -0,0 +1,22 @@ +package org.svnadmin.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @描述: 管理员未登录可访问资源标识. + * @作者: Zoro. + * @创建时间: 2016-04-21 22:24. + * @版本: 1.0.0. + */ +@Documented +@Inherited +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface AdminAuthPassport { + boolean validate() default true; +} \ No newline at end of file diff --git a/src/main/java/org/svnadmin/common/annotation/AuthPassport.java b/src/main/java/org/svnadmin/common/annotation/AuthPassport.java new file mode 100644 index 0000000..11b1b62 --- /dev/null +++ b/src/main/java/org/svnadmin/common/annotation/AuthPassport.java @@ -0,0 +1,22 @@ +package org.svnadmin.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @描述: 用户未登录可访问资源标识. + * @作者: Zoro. + * @创建时间: 2016-04-21 22:24. + * @版本: 1.0.0. + */ +@Documented +@Inherited +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface AuthPassport { + boolean validate() default true; +} \ No newline at end of file diff --git a/src/main/java/org/svnadmin/common/entity/PageBean.java b/src/main/java/org/svnadmin/common/entity/PageBean.java new file mode 100644 index 0000000..77b091f --- /dev/null +++ b/src/main/java/org/svnadmin/common/entity/PageBean.java @@ -0,0 +1,195 @@ +package org.svnadmin.common.entity; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @ClassName: PageBean + * @Description: 分页工具类 + * @author hpboys + * @date 2015年6月6日 下午3:34:22 + * @version V1.0 + * @param + */ +public class PageBean implements Serializable { + private int currentPage;//第几页,即当前页 + private int pageSize;//每页大小 + private int beginRow;//开始取的行数 + private int pageCount;//共几页 + private int recordCount;//记录总数 + private List dataList;//数据 + private Map footer;//底部统计区 + + private int startPage;//开始页码数 + private int endPage;//结束页码数 + private List pages;//动态页码 + private int maxShowPageNum = 6;//最大显示页码数 + private Map queryMap;//查询参数 + private String sqlWhere; + + public PageBean(){} + + public PageBean(int pageNumber, int pageSize) { + this.currentPage = pageNumber; + this.pageSize = pageSize; + } + + public PageBean(int pageNumber, int pageSize,int maxShowPageNum) { + this.currentPage = pageNumber; + this.pageSize = pageSize; + this.maxShowPageNum = maxShowPageNum; + } + + private void initPages(){ + int startPage = 0; + int endPage = 0; + int ban_page_Num = (this.maxShowPageNum % 2)==0? (this.maxShowPageNum / 2):(this.maxShowPageNum / 2)+1; + if ( this.currentPage <= ban_page_Num) { + // 如果当前页码小于显示最大页码数的一半 + startPage = 1; + if (pageCount <= this.maxShowPageNum) { + endPage = pageCount+1; + } else { + endPage = this.maxShowPageNum; + } + } else if ( this.currentPage > (pageCount - ban_page_Num) ) { + // 如果当前页面大于最大页数-显示最大页码数的一半 + startPage = pageCount - this.maxShowPageNum; + endPage = pageCount; + } else { + // 否则,保持当前页码在输出页码数的中间 + startPage = this.currentPage - ban_page_Num + 1; + endPage = this.currentPage + ban_page_Num; + } + if (startPage < 1) startPage = 1; + if (endPage > pageCount) endPage = pageCount; + this.startPage = startPage; + this.endPage = endPage; + this.pages = new ArrayList(); + for (int i = this.startPage; i <= this.endPage; i++) { + this.pages.add(i); + } + } + + + public int getCurrentPage() { + return currentPage; + } + public void setCurrentPage(int currentPage) { + this.currentPage = currentPage; + } + public int getPageSize() { + return pageSize; + } + public void setPageSize(int pageSize) { + this.pageSize = pageSize; + } + public int getPageCount() { + return pageCount; + } + + public void setPageCount(int recordCount) { + if(recordCount%pageSize==0){ + this.pageCount = recordCount/pageSize; + }else{ + this.pageCount = recordCount/pageSize+1; + } + initPages(); + } + public int getRecordCount() { + return recordCount; + } + public void setRecordCount(int recordCount) { + this.recordCount = recordCount; + } + public List getDataList() { + if(null==dataList){ + return new ArrayList(0); + } + return dataList; + } + public void setDataList(List dataList) { + this.dataList = dataList; + } + + public Map getFooter() { + return footer; + } + + public void setFooter(Map footer) { + this.footer = footer; + } + + public int getStartPage() { + return this.startPage; + } + + public void setStartPage(int startPage) { + this.startPage = startPage; + } + + public int getEndPage() { + return endPage; + } + + public void setEndPage(int endPage) { + this.endPage = endPage; + } + + public void setPages(List pages) { + this.pages = pages; + } + + public List getPages() { + return pages; + } + + public int getMaxShowPageNum() { + return maxShowPageNum; + } + + public void setMaxShowPageNum(int maxShowPageNum) { + this.maxShowPageNum = maxShowPageNum; + } + + public int getBeginRow() { + this.beginRow = (this.getCurrentPage()<=1?0:this.getCurrentPage()-1)*this.getPageSize(); + return this.beginRow; + } + + public void setQuery(String queryKey,String queryVal) { + if(this.queryMap == null){ + this.queryMap = new HashMap(); + } + this.queryMap.put(queryKey,queryVal); + } + + public void setQueryMap(Map queryMap) { + this.queryMap = queryMap; + } + + public Map getQueryMap() { + return queryMap; + } + + /** + * @Description: 传入查询参数KEY,得到值 + * @return String 返回类型 + */ + public String get(String key){ + return this.queryMap==null? null:this.queryMap.get(key); + } + + public String getSqlWhere() { + return sqlWhere; + } + + public void setSqlWhere(String sqlWhere) { + this.sqlWhere = sqlWhere; + } + + +} diff --git a/src/main/java/org/svnadmin/common/entity/PushMsg.java b/src/main/java/org/svnadmin/common/entity/PushMsg.java new file mode 100644 index 0000000..32bfd5e --- /dev/null +++ b/src/main/java/org/svnadmin/common/entity/PushMsg.java @@ -0,0 +1,112 @@ +package org.svnadmin.common.entity; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +public class PushMsg implements Serializable { + private Object info;// 主信息 + private Boolean status;// 状态 + private String code;//CODE状态 + private int arg1;//附加值 + private Map attr = new HashMap(); + + public PushMsg() {} + + public PushMsg(Boolean status) { + this.status = status; + } + + public PushMsg(String info, Boolean status) { + this.info = info; + this.status = status; + } + + public PushMsg(Object info, Boolean status) { + this.info = info; + this.status = status; + } + + public PushMsg(String info, String code) { + this.info = info; + this.code = code; + } + + public PushMsg(String info, Boolean status, String code) { + this.info = info; + this.status = status; + this.code = code; + } + + public PushMsg(Object info, String code) { + this.info = info; + this.code = code; + } + + public PushMsg(Object info,Boolean status,Object... entrys){ + this.arg1 = 0; + this.info = info; + this.status = status; + for (int i = 0; i < entrys.length; i+=2) { + this.getAttr().put(String.valueOf(entrys[i]), entrys[i+1]); + } + } + + public Object getInfo() { + return info; + } + + public void setInfo(Object info) { + this.info = info; + } + + public Boolean getStatus() { + return status; + } + + public void setStatus(Boolean status) { + this.status = status; + } + + public int getArg1() { + return arg1; + } + + public void setArg1(int arg1) { + this.arg1 = arg1; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + /** + * 加入反馈属性 + * @return + */ + public Map getAttr() { + return attr; + } + + public void setAttr(Map attr) { + this.attr = attr; + } + + /** + * 得到消息对象 + * @param info + * @param status + * @return + */ + public static PushMsg getPushMsg(String info, Boolean status) { + PushMsg msg = new PushMsg(); + msg.setInfo(info); + msg.setStatus(status); + return msg; + } + +} diff --git a/src/main/java/org/svnadmin/common/mapper/SimpleDateFormatMapper.java b/src/main/java/org/svnadmin/common/mapper/SimpleDateFormatMapper.java new file mode 100644 index 0000000..fb8982e --- /dev/null +++ b/src/main/java/org/svnadmin/common/mapper/SimpleDateFormatMapper.java @@ -0,0 +1,38 @@ +package org.svnadmin.common.mapper; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.ser.CustomSerializerFactory; +import org.springframework.stereotype.Component; + +/** + * 解决SpringMVC使用@ResponseBody返回json时, + * 日期格式默认显示为时间戳的问题。需配合使用 + * @author Zoro + * @date 2016-02-29 下午04:17:52 + */ +@Component("simpleDateFormatMapper") +public class SimpleDateFormatMapper extends ObjectMapper { + + private final static String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; + + public SimpleDateFormatMapper() { + CustomSerializerFactory factory = new CustomSerializerFactory(); + factory.addGenericMapping(Date.class, new JsonSerializer() { + @Override + public void serialize(Date value, JsonGenerator jsonGenerator, + SerializerProvider provider) throws IOException, JsonProcessingException { + SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_FORMAT); + jsonGenerator.writeString(sdf.format(value)); + } + }); + this.setSerializerFactory(factory); + } +} \ No newline at end of file diff --git a/src/main/java/org/svnadmin/common/util/HttpUtils.java b/src/main/java/org/svnadmin/common/util/HttpUtils.java new file mode 100644 index 0000000..5f7f73d --- /dev/null +++ b/src/main/java/org/svnadmin/common/util/HttpUtils.java @@ -0,0 +1,255 @@ +package org.svnadmin.common.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.log4j.Logger; + +/** + * @ClassName: HttpUtils + * @Description: Http网络操作 + * @author hpboys + * @date 2015年6月10日 下午2:12:33 + * @version V1.0 + */ +public class HttpUtils { + private static Logger logger = Logger.getLogger(HttpUtils.class); + + /** + * @Title: getDoGetFullUrl + * @Description: 得到GET请求网站URL + * @return String 返回类型 + */ + public static String getGetFullUrl(String url,String... postParams){ + if(postParams!=null){ + for (int i = 0; i < postParams.length; i=i+2) { + if(!url.contains("?") && i==0){ + url += "?"+postParams[i]+"="+postParams[i+1]; + }else{ + url += "&"+postParams[i]+"="+postParams[i+1]; + } + } + } + return url; + } + + /** + * @Title: getDoGetFullUrl + * @Description: 得到GET请求网站URL + * @return String 返回类型 + */ + public static String getGetFullUrl(String url,Map postParams){ + if(postParams!=null){ + int i = 0; + for (String key : postParams.keySet()) { + if(!url.contains("?") && i==0){ + url += "?"+key+"="+String.valueOf(postParams.get(key)); + }else{ + url += "&"+key+"="+String.valueOf(postParams.get(key)); + } + i++; + } + } + return url; + } + + /** + * 将请求中的参数封装成Map + * @param request Http请求对象 + * @return 将所有请求参数封装为Map集合并返回 + */ + public static Map getParams(HttpServletRequest request){ + Map params = new HashMap(); + for (String key : request.getParameterMap().keySet()) { + params.put(key, HttpUtils.urlDecode(request.getParameter(key), "UTF-8")); + } + return params; + } + + /** + * 将请求中的参数封装成Map + * @param request Http请求对象 + * @return 将所有请求参数封装为Map集合并返回 + */ + public static Map getParamters(HttpServletRequest request){ + Map params = new HashMap(); + try { + for (String key : request.getParameterMap().keySet()) { + String value = request.getParameter(key); + value = java.net.URLDecoder.decode(value, "UTF-8"); + params.put(key, value); + } + } catch (UnsupportedEncodingException e) { + } + return params; + } + + /** + * 将请求中的参数封装成Map + * @param request Http请求对象 + * @return 将所有请求参数封装为Map集合并返回 + */ + public static Map getParams(ServletRequest request){ + Map params = new HashMap(); + for (String key : request.getParameterMap().keySet()) { + params.put(key, HttpUtils.urlDecode(request.getParameter(key), "UTF-8")); + } + return params; + } + + /** + * 将Session域中的参数封装成Map + * @param session HttpSession请求对象 + * @return + */ + public static Map getParams(HttpSession session) { + Map params = new HashMap(); + Enumeration enumeration = session.getAttributeNames(); + while(enumeration.hasMoreElements()){ + String key = enumeration.nextElement(); + params.put(key, session.getAttribute(key)); + } + return params; + } + + /** + * 得到客户端IP地址 + * @param request + * @return + */ + public static String getRemoteIpAddr(HttpServletRequest request) { + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + return ip; + } + + /** + * isAjaxRequest:判断请求是否为Ajax请求.
+ * @param request 请求对象 + * @return boolean + */ + public static boolean isAjaxRequest(HttpServletRequest request){ + String header = request.getHeader("X-Requested-With"); + boolean isAjax = "XMLHttpRequest".equals(header) ? true:false; + return isAjax; + } + + /** + * 进行UrlDecode解码 + * @param text 字符串 + * @param charset 编码 + * @return + */ + public static String urlDecode(String text, String charset) { + try { + return URLDecoder.decode(text,charset); + } catch (Exception e) { + return text; + } + } + + /** + * 进行urlEncode加码 + * @param text 字符串 + * @param charset 编码 + * @return + */ + public static String urlEncode(String text, String charset) { + try { + return URLEncoder.encode(text,charset); + } catch (Exception e) { + return text; + } + } + + /** + * @Title: inputStream2String + * @Description: 将InputStream转换为字符串 + * @return String 返回类型 + */ + public static String inputStream2String(InputStream is) { + int i = -1; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + while ((i = is.read()) != -1) { + baos.write(i); + } + String content = baos.toString(); + baos.flush(); + baos.close(); + return content; + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + /** + * @Description: 后台进行POST请求(请写在代码执行结尾) + * @return void 返回类型 + */ + public static void doBgPostReq(HttpServletResponse response,String postUrl,Map paramMap) throws IOException { + response.setContentType( "text/html;charset=utf-8"); + PrintWriter out = response.getWriter(); + out.println("
"); + for (String key : paramMap.keySet()) { + out.println(""); + } + out.println("
"); + out.println(""); + } + + /** + * 得到访问请求根域名 + * @param request + * @return + */ + public static String getRootHost(HttpServletRequest request){ + return request.getRequestURL().toString().split(request.getRequestURI())[0]; + } + + /** + * 得到访问请求项目根域名 + * @param request + * @return + */ + public static String getSysHost(HttpServletRequest request){ + return request.getRequestURL().toString().split(request.getRequestURI())[0] + request.getContextPath(); + } + + /** + * 将请求中的参数封装成Map,并去掉前后空格 + * @param request Http请求对象 + * @return 将所有请求参数封装为Map集合并返回 + */ + public static Map getTrimedParams(HttpServletRequest request){ + Map params = new HashMap(); + for (String key : request.getParameterMap().keySet()) { + params.put(key, HttpUtils.urlDecode(request.getParameter(key), "UTF-8").trim()); + } + return params; + } +} diff --git a/src/main/java/org/svnadmin/common/util/PrintUtils.java b/src/main/java/org/svnadmin/common/util/PrintUtils.java new file mode 100644 index 0000000..c47ef71 --- /dev/null +++ b/src/main/java/org/svnadmin/common/util/PrintUtils.java @@ -0,0 +1,139 @@ +package org.svnadmin.common.util; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.springframework.web.method.HandlerMethod; + +/** + * @author hpboys + * @version V1.0 + * @ClassName: PrintUtils + * @Description: 打印信息工具类 + * @date 2015年6月13日 下午2:04:43 + */ +public class PrintUtils { + + public static Logger logger = Logger.getLogger(PrintUtils.class); + + /** + * 打印请求情况 print(request, handler); + * + * @param request + */ + public static String print (HttpServletRequest request, HandlerMethod handler) { + // 打印请求情况 + String reqInfo = printForHandler(handler); + reqInfo += printForRequest(request); + logger.info("\n" + reqInfo); + return reqInfo; + } + + /** + * 打印请求情况 print(request); + * + * @param request + */ + public static String print (HttpServletRequest request) { + // 打印请求情况 + String reqInfo = printForRequest(request); + logger.info("\n" + reqInfo); + return reqInfo; + } + + private static String printForHandler (HandlerMethod handler) { + if (handler == null) { + return ""; + } + StringBuilder handlerInfo = new StringBuilder("\n控制器类:" + handler.getBeanType().getName() + "." + handler.getMethod().getName() + "(" + handler.getBeanType().getSimpleName() + ".java:1)"); + handlerInfo.append("\n页面URL类方法名:" + handler.getMethod().getName()); + return handlerInfo.toString(); + } + + + private static String printForRequest (HttpServletRequest request) { + StringBuilder reqInfo = new StringBuilder("\n完整请求:" + getFullUrl(request)); + reqInfo.append("\n请求 方式:" + request.getMethod() + " " + (isAjaxRequest(request) ? "Ajax请求" : "常规请求")); + reqInfo.append("\n请求 URL:" + request.getRequestURI()); + String paramsTxt = "\n请求参数:[ "; + int i = 0; + for (String key : request.getParameterMap().keySet()) { + String value = reqGetParam(request, key); + if (i++ == 0) { + paramsTxt += key + "=" + value; + } else { + paramsTxt += " | " + key + "=" + value; + } + } + reqInfo.append(paramsTxt + " ]"); + reqInfo.append("\n\n ================ 请求参数信息结束 ================ "); + return reqInfo.toString(); + } + + /** + * @return String 返回类型 + * @throws + * @Description: 超过指定长度,自动省略 + */ + private static String reqGetParam (HttpServletRequest req, String key) { + String val = req.getParameter(key); + int maxLength = 128;//允许显示最大长度 + if (val != null && val.length() > maxLength) { + return val.substring(0, maxLength) + "..."; + } + return val; + } + + /** + * 得到一个完整URL(包含参数) + * + * @param request + * @return + */ + public static String getFullUrl (HttpServletRequest request) { + StringBuilder url = new StringBuilder(); + int i = 0; + url.append(request.getRequestURL()); + for (String key : request.getParameterMap().keySet()) { + if (i++ == 0) { + url.append("?" + key + "=" + reqGetParam(request, key)); + } else { + url.append("&" + key + "=" + reqGetParam(request, key)); + } + } + return url.toString(); + } + + /** + * 得到一个请求的所有参数信息,参数值长度超过200则截断 + * + * @param request + * @return + */ + public static String getUrlAllparams (HttpServletRequest request) { + StringBuilder url = new StringBuilder(); + String value; + for (String key : request.getParameterMap().keySet()) { + value = request.getParameter(key); + if (StringUtils.isNotEmpty(value) && value.length() > 200) { + value = value.substring(0, 200) + "..."; + } + url.append(key + "=" + value + "&"); + } + return url.toString(); + } + + /** + * isAjaxRequest:判断请求是否为Ajax请求.
+ * + * @param request 请求对象 + * @return boolean + */ + private static boolean isAjaxRequest (HttpServletRequest request) { + String header = request.getHeader("X-Requested-With"); + boolean isAjax = "XMLHttpRequest".equals(header) ? true : false; + return isAjax; + } + +} diff --git a/src/main/java/org/svnadmin/common/util/PropUtils.java b/src/main/java/org/svnadmin/common/util/PropUtils.java new file mode 100644 index 0000000..722b933 --- /dev/null +++ b/src/main/java/org/svnadmin/common/util/PropUtils.java @@ -0,0 +1,38 @@ +package org.svnadmin.common.util; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + + +/** + * @ClassName: PropUtils + * @Description: 常用配置文件操作 + * @author hpboys + * @date 2015年7月8日 下午5:12:38 + * @version V1.0 + */ +public class PropUtils { + + private static Map properties = new HashMap(); + + public static void initConfigProperties(Properties props) { + for (Object key : props.keySet()) { + String keyTemp = String.valueOf(key); + String valueTemp = props.getProperty(keyTemp); + properties.put(keyTemp, valueTemp); + } + } + + public static Map getProperties() { + return properties; + } + + public static String getProperty(String key) { + return properties.get(key); + } + + public static String get(String key) { + return properties.get(key); + } +} diff --git a/src/main/java/org/svnadmin/common/util/SpringUtils.java b/src/main/java/org/svnadmin/common/util/SpringUtils.java new file mode 100644 index 0000000..c7487e8 --- /dev/null +++ b/src/main/java/org/svnadmin/common/util/SpringUtils.java @@ -0,0 +1,79 @@ +package org.svnadmin.common.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +/** + * Spring 工具类 + * + * @author Huiwu Yuan + * @since 1.0 + */ +public class SpringUtils implements ApplicationContextAware { + + /** + * 日志 + */ + private final Log LOG = LogFactory.getLog(SpringUtils.class); + + /** + * ApplicationContext + */ + private static ApplicationContext applicationContext; + + /** + * 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量. + */ + public void setApplicationContext(ApplicationContext applicationContext) { + LOG.info("Version: "+getVersion()); + SpringUtils.applicationContext = applicationContext; + } + + /** + * @return 取得存储在静态变量中的ApplicationContext. + */ + public static ApplicationContext getApplicationContext() { + checkApplicationContext(); + return applicationContext; + } + + /** + * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型. + * + * @param name + * Bean的名称 + * @return 对象 + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) { + checkApplicationContext(); + return (T) applicationContext.getBean(name); + } + + /** + * 清除applicationContext静态变量. + */ + public static void cleanApplicationContext() { + applicationContext = null; + } + + /** + * 检查是否applicaitonContext未注入 + */ + private static void checkApplicationContext() { + if (applicationContext == null) { + throw new IllegalStateException( + "applicaitonContext未注入,请在applicationContext.xml中定义SpringUtils"); + } + } + + /** + * @return 当前的版本 + * @since 3.0.2 + */ + public static String getVersion(){ + return PropUtils.get("setting.version"); + } +} diff --git a/src/main/java/org/svnadmin/common/web/BaseController.java b/src/main/java/org/svnadmin/common/web/BaseController.java new file mode 100644 index 0000000..ec6e2f4 --- /dev/null +++ b/src/main/java/org/svnadmin/common/web/BaseController.java @@ -0,0 +1,111 @@ +package org.svnadmin.common.web; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.svnadmin.common.entity.PushMsg; +import org.svnadmin.common.util.HttpUtils; +import org.svnadmin.common.util.PrintUtils; + +/** + * 基础控制器 + * @author Zoro + * @datetime 2016/2/24 20:53 + * @since 1.0.0 + */ +public class BaseController { + + protected Logger logger = Logger.getLogger(BaseController.class); + + /** + * 全局异常控制,记录日志 + * @param ex + * @param request + * @return + */ + @ExceptionHandler(Throwable.class) + public String operateException(RuntimeException ex,HttpServletRequest request,HttpServletResponse rp) throws Exception{ + PrintUtils.print(request); + logger.error(ex.getMessage(),ex); + logger.info("************* ------ 异常信息已记录 ------- ***********"); + if(HttpUtils.isAjaxRequest(request)){ + rp.getWriter().print("{\"info\":\"抱歉,操作失败,请稍后重试!\",\"status\":false}"); + return ""; + }else{ + request.setAttribute("errorTips", ex.getMessage()); + return "common/exception";//需各端添加此文件 + } + } + + /** + * 推送消息到客户端 + * @param status + * @return + */ + public static PushMsg pushMsg(Boolean status){ + PushMsg pushMsg = new PushMsg(); + pushMsg.setArg1(0);//默认值 + pushMsg.setInfo(status? "恭喜,操作成功":"抱歉,操作失败!"); + pushMsg.setStatus(status); + return pushMsg; + } + + /** + * 推送消息到客户端 + * @param info + * @param status + * @return + */ + public static PushMsg pushMsg(Object info,Boolean status){ + PushMsg pushMsg = new PushMsg(); + pushMsg.setArg1(0);//默认值 + pushMsg.setInfo(info); + pushMsg.setStatus(status); + return pushMsg; + } + + /** + * 推送消息到客户端 + * @param info + * @param status + * @param entrys 附加属性值,Key:Value + * @return + */ + public static PushMsg pushMsg(Object info, Boolean status, Object... entrys){ + PushMsg pushMsg = new PushMsg(); + pushMsg.setArg1(0);//默认值 + pushMsg.setInfo(info); + pushMsg.setStatus(status); + for (int i = 0; i < entrys.length; i+=2) { + pushMsg.getAttr().put(String.valueOf(entrys[i]), entrys[i+1]); + } + return pushMsg; + } + + /** + * 推送消息到客户端 + * @param info + * @param status + * @return + */ + public static PushMsg pushMsg(Object info,Boolean status,int arg1){ + PushMsg pushMsg = new PushMsg(); + pushMsg.setArg1(arg1);//自定义值 + pushMsg.setInfo(info); + pushMsg.setStatus(status); + return pushMsg; + } + + /** + * 向指定Url进行重定向 + * @param url + * @return + */ + public String redirect(String url){ + return "redirect:"+url; + } + + +} diff --git a/src/main/java/org/svnadmin/constant/Constants.java b/src/main/java/org/svnadmin/constant/Constants.java new file mode 100644 index 0000000..46d2b30 --- /dev/null +++ b/src/main/java/org/svnadmin/constant/Constants.java @@ -0,0 +1,53 @@ +package org.svnadmin.constant; + +/** + * 常量 + * + * @author Huiwu Yuan + * @since 1.0 + */ +public class Constants { + /** + * lang 保存在session中得key + */ + public static final String SESSION_KEY_LANG = "_session_key_lang_"; + /** + * 用户在session中key + */ + public static final String SESSION_KEY_USER = "_session_key_user_"; + + /** + * + */ + public static final String ERROR = "error"; + + /** + * svn协议 + */ + public static final String SVN = "svn"; + /** + * http单库 + */ + public static final String HTTP = "http"; + /** + * http多库 + */ + public static final String HTTP_MUTIL = "http-mutil"; + + /** + * 管理组 + */ + public static final String GROUP_MANAGER = "manager"; + + /** + * 项目默认的组 + */ + public static final String[] GROUPS = { GROUP_MANAGER, "developer", + "tester" }; + + /** + * 管理员角色代码 + */ + public static final String USR_ROLE_ADMIN = "admin"; + +} diff --git a/src/main/java/org/svnadmin/constant/SessionConstant.java b/src/main/java/org/svnadmin/constant/SessionConstant.java new file mode 100644 index 0000000..d7d87d4 --- /dev/null +++ b/src/main/java/org/svnadmin/constant/SessionConstant.java @@ -0,0 +1,32 @@ +package org.svnadmin.constant; + + +/** + * 会话键常量类. + * @author Zoro + * @datetime 2016/4/6 13:27 + * @since 1.0.0 + */ +public class SessionConstant { + + /** + * 后台登录用户的session键名. + */ + public static final String USER_SESSION_KEY = "adminUser"; + + /** + * 商户主帐号ID的session键名. + */ + public static final String MAIN_USER_ID_SESSION_KEY = "pmsMainUserId"; + + /** + * 登录用户拥有的权限集合的session键名. + */ + public static final String ACTIONS_SESSION_KEY = "actions"; + + /** + * 用户密码连续输错次数限制(默认5). + */ + public static int WEB_PWD_INPUT_ERROR_LIMIT = 5; + +} diff --git a/src/main/java/org/svnadmin/controller/basic/ConsoleController.java b/src/main/java/org/svnadmin/controller/basic/ConsoleController.java new file mode 100644 index 0000000..089da32 --- /dev/null +++ b/src/main/java/org/svnadmin/controller/basic/ConsoleController.java @@ -0,0 +1,47 @@ +package org.svnadmin.controller.basic; + +import javax.servlet.http.HttpSession; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.svnadmin.common.web.BaseController; +import org.svnadmin.service.PjService; +import org.svnadmin.service.UsrService; +import org.svnadmin.util.SessionUtils; + +/** + * 控制台控制器 + * @author Zoro + * @datetime 2016/1/20 19:48 + * @since 1.0.0 + */ +@Controller +@RequestMapping("/") +public class ConsoleController extends BaseController { + + @Autowired + private UsrService usrService; + @Autowired + private PjService pjService; + + /** + * 控制台主页 + * @param session + * @return + */ + @RequestMapping(value = "console", method = RequestMethod.GET) + public String console(HttpSession session, ModelMap map) { + boolean hasAdminRight = SessionUtils.hasAdminRight(session); + if(hasAdminRight){ + //管理员登录可查看 + return redirect("pjList"); + }else{ + //普通登录可查看 + return redirect("usrRightListView"); + } + } + +} diff --git a/src/main/java/org/svnadmin/controller/basic/LoginController.java b/src/main/java/org/svnadmin/controller/basic/LoginController.java new file mode 100644 index 0000000..b7d80a3 --- /dev/null +++ b/src/main/java/org/svnadmin/controller/basic/LoginController.java @@ -0,0 +1,78 @@ +package org.svnadmin.controller.basic; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.svnadmin.common.annotation.AuthPassport; +import org.svnadmin.common.web.BaseController; +import org.svnadmin.constant.SessionConstant; +import org.svnadmin.entity.Usr; +import org.svnadmin.service.UsrService; +import org.svnadmin.util.I18N; + +/** + * @描述: 登录登出控制器. + * @作者: Zoro. + * @创建时间: 2016-05-08 12:52. + * @版本: 1.0.0. + */ +@Controller +@RequestMapping("/") +public class LoginController extends BaseController{ + + @Autowired + private UsrService usrService; + + /** + * SVN后台管理员登录页面 + */ + @AuthPassport + @RequestMapping(value = "login", method = RequestMethod.GET) + public String login(HttpServletRequest request, ModelMap map){ + map.put("lbe_usr_txt", I18N.getLbl(request, "usr.usr", "帐号")); + map.put("lbe_psw_txt", I18N.getLbl(request,"usr.psw","密码")); + map.put("btn_login_txt", I18N.getLbl(request,"login.btn.login","登录")); + return "basic/login"; + } + + /** + * 登录处理 + */ + @AuthPassport + @RequestMapping(value = "loginHandler", method = RequestMethod.POST) + @ResponseBody + public Object loginHandler(HttpServletRequest request, + @RequestParam("usr")String usr, + @RequestParam("psw")String psw){ + Usr loginUser = null; + //登录 + try { + loginUser = usrService.login(usr, psw); + if (null == loginUser) { + return pushMsg("用户名或密码错误!", false); + } + }catch (Exception ex){ + return pushMsg(ex.getMessage(), false); + } + request.getSession().setAttribute(SessionConstant.USER_SESSION_KEY, loginUser); + return pushMsg("认证通过", true , "url" , "console"); + } + + /** + * 登录退出处理 + */ + @RequestMapping(value = "logout", method = RequestMethod.GET) + public String logout(HttpServletRequest request, ModelMap map){ + request.getSession().removeAttribute(SessionConstant.USER_SESSION_KEY); + return redirect("login"); + } + + + +} diff --git a/src/main/java/org/svnadmin/controller/rep/RepController.java b/src/main/java/org/svnadmin/controller/rep/RepController.java new file mode 100644 index 0000000..cfd4572 --- /dev/null +++ b/src/main/java/org/svnadmin/controller/rep/RepController.java @@ -0,0 +1,162 @@ +package org.svnadmin.controller.rep; + +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.svnadmin.common.entity.PageBean; +import org.svnadmin.common.util.HttpUtils; +import org.svnadmin.common.web.BaseController; +import org.svnadmin.entity.Ajax; +import org.svnadmin.entity.Pj; +import org.svnadmin.entity.PjAuth; +import org.svnadmin.service.DefaultTreeService; +import org.svnadmin.service.PjAuthService; +import org.svnadmin.service.PjGrService; +import org.svnadmin.service.PjService; +import org.svnadmin.service.RepositoryService; +import org.svnadmin.service.UsrService; +import org.svnadmin.util.SessionUtils; +import org.svnadmin.util.UsrProvider; + +/** + * SVN项目资源权限控制器 + * @author Zoro + * @datetime 2016/5/20 19:48 + * @since 1.0.0 + */ +@Controller +@RequestMapping("/") +public class RepController extends BaseController { + + @Autowired + private UsrService usrService; + @Autowired + private PjService pjService; + @Autowired + private PjGrService pjGrService; + @Autowired + private PjAuthService pjAuthService; + /** + * 仓库服务层 + */ + @Autowired + private RepositoryService repositoryService; + @Autowired + private DefaultTreeService treeService; + + /** + * 资源 + * @param session + * @return + */ + @RequestMapping(value = "repository", method = RequestMethod.GET) + public String repository(HttpSession session, + @RequestParam("pj")String _pj,ModelMap map) { + Pj pj = pjService.get(_pj); + map.put("pj",pj); + map.put("usrList", usrService.list()); + map.put("pjgrlist", pjGrService.list(_pj)); + map.put("pjreslist", pjAuthService.getResList(_pj)); + return "rep/repository"; + } + + /** + * 项目资源树数据 + * @param request + * @return + */ + @RequestMapping(value = "repTree", method = RequestMethod.POST ,params = "action=data") + @ResponseBody + public Object repTree(HttpServletRequest request) { + //treeId treeParentId pj path + UsrProvider.setUsr(SessionUtils.getLogedUser(request.getSession())); + Map params = HttpUtils.getParamters(request); + Ajax ajax = treeService.execute(params); + return ajax.getResult(); + } + + /** + * 项目列表 + * @param request + * @return + */ + @RequestMapping(value = "repPathAuth", method = RequestMethod.GET ,params = "action=data") + @ResponseBody + public Object repPathAuth(HttpServletRequest request) { + Map params = HttpUtils.getParams(request); + String pj = params.get("pj"); + String res = params.get("res"); + if(StringUtils.isBlank(res)){ + String path = params.get("path");//从rep 树点击进来,传递的是path + if(StringUtils.isNotBlank(path)){ + res = this.pjAuthService.formatRes(pj, path); + } + }else{ +// res = entity.getRes(); + } +// entity.setRes(res); + List list = pjAuthService.list(pj,res); + PageBean pageBean = new PageBean<>(); + pageBean.setDataList(list); + pageBean.setRecordCount(list.size()); + return pageBean; + } + + /** + * 处理资源权限(添加) + * @param request + * @return + */ + @RequestMapping(value = "repPathAuthAddHandler", method = RequestMethod.POST) + @ResponseBody + public Object pjCreateHandler(HttpServletRequest request) { + Map params = HttpUtils.getParams(request); + String pj = params.get("pj"); + String res = params.get("res"); + + String[] grs = StringUtils.isEmpty(params.get("grs"))? null:params.get("grs").split(","); + String[] usrs = StringUtils.isEmpty(params.get("usrs"))? null:params.get("usrs").split(","); + + String rw = params.get("rw"); + PjAuth entity = new PjAuth(); + entity.setPj(pj); + entity.setRes(res); + request.setAttribute("entity", entity); + pjAuthService.save(pj, res, rw, grs, usrs); + return pushMsg("操作资源权限成功", true); + } + + /** + * 处理资源权限(移除) + * @param request + * @return + */ + @RequestMapping(value = "repPathAuthRemoveHandler", method = RequestMethod.POST) + @ResponseBody + public Object repPathAuthRemoveHandler(HttpServletRequest request) { + Map params = HttpUtils.getParams(request); + String pj = params.get("pj"); + String gr = params.get("gr"); + String usr = params.get("usr"); + String res = params.get("res"); + + if (StringUtils.isNotBlank(gr)) { + pjAuthService.deleteByGr(pj, gr, res); + } else if (StringUtils.isNotBlank(usr)) { + pjAuthService.deleteByUsr(pj, usr, res); + } + return pushMsg("操作资源权限成功", true); + } + +} diff --git a/src/main/java/org/svnadmin/controller/svn/ProjectController.java b/src/main/java/org/svnadmin/controller/svn/ProjectController.java new file mode 100644 index 0000000..5c17377 --- /dev/null +++ b/src/main/java/org/svnadmin/controller/svn/ProjectController.java @@ -0,0 +1,115 @@ +package org.svnadmin.controller.svn; + +import java.util.List; + +import javax.servlet.http.HttpSession; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.svnadmin.common.annotation.AdminAuthPassport; +import org.svnadmin.common.entity.PageBean; +import org.svnadmin.common.web.BaseController; +import org.svnadmin.entity.Pj; +import org.svnadmin.entity.Usr; +import org.svnadmin.service.PjService; +import org.svnadmin.service.UsrService; +import org.svnadmin.util.SessionUtils; + +/** + * SVN项目管理控制器 + * @author Zoro + * @datetime 2016/1/20 19:48 + * @since 1.0.0 + */ +@Controller +@RequestMapping("/") +public class ProjectController extends BaseController { + + @Autowired + private UsrService usrService; + @Autowired + private PjService pjService; + + /** + * 项目列表 + * @param session + * @return + */ + @RequestMapping(value = "pjList", method = RequestMethod.GET) + public String pjList(HttpSession session, ModelMap map) { + boolean hasAdminRight = SessionUtils.hasAdminRight(session); + List list = null; + if (hasAdminRight) { + list = pjService.list();// 所有项目 + } + else { + list = pjService.list(SessionUtils.getLogedUser(session).getUsr());// 登录用户可以看到的项目 + } + PageBean pageBean = new PageBean(); + pageBean.setRecordCount(list.size()); + pageBean.setDataList(list); + map.put("pageBean", pageBean); + return "svn/pj_list"; + } + + /** + * 项目列表数据 + * @param session + * @return + */ + @RequestMapping(value = "pjList", method = RequestMethod.GET ,params = "action=data") + @ResponseBody + public Object pjListDataSet(HttpSession session,@RequestParam("pageNumber")int pageNumber) { + PageBean pageBean = new PageBean(pageNumber,10); +// usrService.queryForPageBean(pageBean); + return pageBean; + } + + /** + * 创建项目 + * @param session + * @return + */ + @AdminAuthPassport + @RequestMapping(value = "pjCreate", method = RequestMethod.GET) + public String pjCreate(HttpSession session, ModelMap map) { + return "svn/pj_create"; + } + + /** + * 创建项目处理 + * @param session + * @return + */ + @AdminAuthPassport + @RequestMapping(value = "pjCreateHandler", method = RequestMethod.POST) + @ResponseBody + public Object pjCreateHandler(HttpSession session,Pj entity) { + try { + pjService.save(entity); + return pushMsg("创建项目成功", true , "url" , "pjList"); + }catch (Exception e){ + logger.error("创建项目提交失败",e); + return pushMsg("创建项目失败,"+e.getMessage(), true); + } + } + + @AdminAuthPassport + @RequestMapping(value = "pjDelete", method = RequestMethod.POST) + @ResponseBody + public Object pjDelete(HttpSession session, @RequestParam("pj")String pj, ModelMap map) { + try { + pjService.delete(pj); + return pushMsg("项目删除成功", true , "url" , "pjList"); + }catch (Exception e){ + logger.error("项目删除失败",e); + return pushMsg("项目删除失败," + e.getMessage(), true); + } + } + +} diff --git a/src/main/java/org/svnadmin/controller/svn/ProjectGrController.java b/src/main/java/org/svnadmin/controller/svn/ProjectGrController.java new file mode 100644 index 0000000..fb3a6ca --- /dev/null +++ b/src/main/java/org/svnadmin/controller/svn/ProjectGrController.java @@ -0,0 +1,92 @@ +package org.svnadmin.controller.svn; + +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.svnadmin.common.annotation.AdminAuthPassport; +import org.svnadmin.common.entity.PageBean; +import org.svnadmin.common.web.BaseController; +import org.svnadmin.entity.PjGr; +import org.svnadmin.service.PjGrService; +import org.svnadmin.service.PjService; +import org.svnadmin.service.UsrService; + +/** + * SVN项目用户组管理控制器 + * @author Zoro + * @datetime 2016/1/20 19:48 + * @since 1.0.0 + */ +@Controller +@RequestMapping("/") +public class ProjectGrController extends BaseController { + + @Autowired + private UsrService usrService; + @Autowired + private PjService pjService; + @Autowired + private PjGrService pjGrService; + + /** + * 项目用户组列表 + * @param session + * @return + */ + @RequestMapping(value = "pjGrList", method = RequestMethod.GET) + public String pjGrList(HttpSession session,@RequestParam("pj")String pj, ModelMap map) { + map.put("pj", pjService.get(pj)); + return "svn/pj_gr_list"; + } + + /** + * 项目用户组列表(数据集) + * @param session + * @return + */ + @RequestMapping(value = "pjGrList", method = RequestMethod.GET, params = "action=data") + @ResponseBody + public Object pjGrList(HttpSession session,@RequestParam("pj")String pj) { + // 项目账户 + List list = pjGrService.list(pj); + PageBean pageBean = new PageBean(); + pageBean.setRecordCount(list.size()); + pageBean.setDataList(list); + return pageBean; + } + + /** + * 添加项目用户组处理 + * @param request + * @return + */ + @AdminAuthPassport + @RequestMapping(value = "pjGrAddHandler", method = RequestMethod.POST) + @ResponseBody + public Object pjGrAddHandler(HttpServletRequest request,PjGr entity) { + pjGrService.save(entity); + return pushMsg("添加项目用户组成功", true); + } + + /** + * 删除项目用户组处理 + * @param request + * @return + */ + @AdminAuthPassport + @RequestMapping(value = "pjGrRemoveHandler", method = RequestMethod.POST) + @ResponseBody + public Object pjGrRemoveHandler(HttpServletRequest request,PjGr entity) { + pjGrService.delete(entity.getPj(), entity.getGr()); + return pushMsg("删除项目用户组成功", true); + } +} diff --git a/src/main/java/org/svnadmin/controller/svn/ProjectGrUsrController.java b/src/main/java/org/svnadmin/controller/svn/ProjectGrUsrController.java new file mode 100644 index 0000000..c42d324 --- /dev/null +++ b/src/main/java/org/svnadmin/controller/svn/ProjectGrUsrController.java @@ -0,0 +1,113 @@ +package org.svnadmin.controller.svn; + +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.svnadmin.common.annotation.AdminAuthPassport; +import org.svnadmin.common.entity.PageBean; +import org.svnadmin.common.util.HttpUtils; +import org.svnadmin.common.web.BaseController; +import org.svnadmin.entity.PjGrUsr; +import org.svnadmin.service.PjGrUsrService; +import org.svnadmin.service.PjService; +import org.svnadmin.service.PjUsrService; +import org.svnadmin.service.UsrService; + +/** + * SVN项目用户组管理控制器 + * @author Zoro + * @datetime 2016/1/20 19:48 + * @since 1.0.0 + */ +@Controller +@RequestMapping("/") +public class ProjectGrUsrController extends BaseController { + + @Autowired + private UsrService usrService; + @Autowired + private PjService pjService; + @Autowired + private PjUsrService pjUsrService; + @Autowired + private PjGrUsrService pjGrUsrService; + + /** + * 项目组用户列表 + * @param session + * @return + */ + @RequestMapping(value = "pjGrUsrList", method = RequestMethod.GET) + public String pjGrUsrList(HttpSession session, + @RequestParam("pj")String pj, + @RequestParam("gr")String gr,ModelMap map) { + // 账户 + map.put("pj", pj); + map.put("gr", gr); + map.put("usrList", usrService.listUnSelected(pj, gr)); + return "svn/pj_gr_usr_list"; + } + + /** + * 项目组用户列表(数据集) + * @param session + * @return + */ + @RequestMapping(value = "pjGrUsrList", method = RequestMethod.GET, params = "action=data") + @ResponseBody + public Object pjGrUsrList(HttpSession session, + @RequestParam("pj")String pj, + @RequestParam("gr")String gr) { + //组用户账户 + List list = pjGrUsrService.list(pj, gr); + PageBean pageBean = new PageBean(); + pageBean.setRecordCount(list.size()); + pageBean.setDataList(list); + return pageBean; + } + + /** + * 添加项目组用户处理 + * @param request + * @return + */ + @AdminAuthPassport + @RequestMapping(value = "pjGrUsrAddHandler", method = RequestMethod.POST) + @ResponseBody + public Object pjGrUsrAddHandler(HttpServletRequest request) { + Map params = HttpUtils.getParams(request); + String pj = params.get("pj"); + String gr = params.get("gr"); + String[] usrs = StringUtils.isEmpty(params.get("usrs"))? null:params.get("usrs").split(","); + this.pjGrUsrService.save(pj, gr, usrs); + return pushMsg("添加项目组用户成功", true); + } + + /** + * 删除项目组用户处理 + * @param request + * @return + */ + @AdminAuthPassport + @RequestMapping(value = "pjGrUsrRemoveHandler", method = RequestMethod.POST) + @ResponseBody + public Object pjGrUsrRemoveHandler(HttpServletRequest request) { + Map params = HttpUtils.getParams(request); + String pj = params.get("pj"); + String gr = params.get("gr"); + String usr = params.get("usr"); + this.pjGrUsrService.delete(pj, gr, usr); + return pushMsg("删除项目组用户成功", true); + } +} diff --git a/src/main/java/org/svnadmin/controller/svn/ProjectUsrController.java b/src/main/java/org/svnadmin/controller/svn/ProjectUsrController.java new file mode 100644 index 0000000..d85fe9c --- /dev/null +++ b/src/main/java/org/svnadmin/controller/svn/ProjectUsrController.java @@ -0,0 +1,111 @@ +package org.svnadmin.controller.svn; + +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.svnadmin.common.annotation.AdminAuthPassport; +import org.svnadmin.common.entity.PageBean; +import org.svnadmin.common.util.HttpUtils; +import org.svnadmin.common.web.BaseController; +import org.svnadmin.entity.PjUsr; +import org.svnadmin.entity.Usr; +import org.svnadmin.service.PjService; +import org.svnadmin.service.PjUsrService; +import org.svnadmin.service.UsrService; +import org.svnadmin.util.EncryptUtil; + +/** + * SVN项目用户管理控制器 + * @author Zoro + * @datetime 2016/1/20 19:48 + * @since 1.0.0 + */ +@Controller +@RequestMapping("/") +public class ProjectUsrController extends BaseController { + + @Autowired + private UsrService usrService; + @Autowired + private PjService pjService; + @Autowired + private PjUsrService pjUsrService; + + /** + * 项目用户列表 + * @param session + * @return + */ + @RequestMapping(value = "pjUsrList", method = RequestMethod.GET) + public String pjUsrList(HttpSession session,@RequestParam("pj")String pj, ModelMap map) { + // 账户 + List usrList = usrService.list(pj); + map.put("pj", pjService.get(pj)); + map.put("usrList", usrList); + return "svn/pj_usr_list"; + } + + /** + * 项目用户列表 + * @param session + * @return + */ + @RequestMapping(value = "pjUsrList", method = RequestMethod.GET, params = "action=data") + @ResponseBody + public Object pjUsrList(HttpSession session,@RequestParam("pj")String pj) { + // 项目账户 + List list = pjUsrService.list(pj); + PageBean pageBean = new PageBean(); + pageBean.setRecordCount(list.size()); + pageBean.setDataList(list); + return pageBean; + } + + /** + * 添加项目用户处理 + * @param request + * @return + */ + @AdminAuthPassport + @RequestMapping(value = "pjUsrAddHandler", method = RequestMethod.POST) + @ResponseBody + public Object pjUsrAddHandler(HttpServletRequest request,PjUsr entity) { + Map params = HttpUtils.getParams(request); + if ("1".equals(params.get("defaultPswd"))) { + entity.setPsw(usrService.get(entity.getUsr()).getPsw()); + } else { + entity.setPsw(EncryptUtil.encrypt(entity.getPsw())); + } + pjUsrService.save(entity); + return pushMsg("添加项目用户成功", true); + } + + /** + * 删除项目用户处理 + * @param request + * @return + */ + @AdminAuthPassport + @RequestMapping(value = "pjUsrRemoveHandler", method = RequestMethod.POST) + @ResponseBody + public Object pjUsrRemoveHandler(HttpServletRequest request,PjUsr entity) { + Map params = HttpUtils.getParams(request); + if ("1".equals(params.get("defaultPswd"))) { + entity.setPsw(usrService.get(entity.getUsr()).getPsw()); + } else { + entity.setPsw(EncryptUtil.encrypt(entity.getPsw())); + } + pjUsrService.save(entity); + return pushMsg("添加项目用户成功", true); + } +} diff --git a/src/main/java/org/svnadmin/controller/usr/UsrController.java b/src/main/java/org/svnadmin/controller/usr/UsrController.java new file mode 100644 index 0000000..74a1e5e --- /dev/null +++ b/src/main/java/org/svnadmin/controller/usr/UsrController.java @@ -0,0 +1,188 @@ +package org.svnadmin.controller.usr; + +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.svnadmin.common.annotation.AdminAuthPassport; +import org.svnadmin.common.entity.PageBean; +import org.svnadmin.common.util.HttpUtils; +import org.svnadmin.common.web.BaseController; +import org.svnadmin.entity.Pj; +import org.svnadmin.entity.PjAuth; +import org.svnadmin.entity.PjUsr; +import org.svnadmin.entity.Usr; +import org.svnadmin.service.PjService; +import org.svnadmin.service.PjUsrService; +import org.svnadmin.service.UsrService; +import org.svnadmin.util.EncryptUtil; +import org.svnadmin.util.SessionUtils; + +/** + * SVN用户管理控制器 + * @author Zoro + * @datetime 2016/1/20 19:48 + * @since 1.0.0 + */ +@Controller +@RequestMapping("/") +public class UsrController extends BaseController { + + @Autowired + private UsrService usrService; + @Autowired + private PjService pjService; + @Autowired + private PjUsrService pjUsrService; + + /** + * 用户列表 + * @param session + * @return + */ + @RequestMapping(value = "usrList", method = RequestMethod.GET) + public String usrList(HttpSession session, ModelMap map) { + return "usr/usr_list"; + } + + /** + * 用户列表数据 + * @param session + * @return + */ + @RequestMapping(value = "usrList", method = RequestMethod.GET ,params = "action=data") + @ResponseBody + public Object usrListDataSet(HttpSession session) { + List list = usrService.list(); + PageBean pageBean = new PageBean(); + pageBean.setRecordCount(list.size()); + pageBean.setDataList(list); + return pageBean; + } + + /** + * 创建用户处理 + * @param session + * @return + */ + @AdminAuthPassport + @RequestMapping(value = "usrCreateHandler", method = RequestMethod.POST) + @ResponseBody + public Object usrCreateHandler(HttpSession session,Usr entity) { + try { + entity.setPsw(EncryptUtil.encrypt(entity.getPsw())); + usrService.save(entity); + return pushMsg("创建用户成功", true , "url" , "usrList"); + }catch (Exception e){ + logger.error("创建用户提交失败",e); + return pushMsg("创建用户失败,"+e.getMessage(), true); + } + } + + /** + * 删除用户处理 + * @param session + * @return + */ + @AdminAuthPassport + @RequestMapping(value = "usrRemoveHandler", method = RequestMethod.POST) + @ResponseBody + public Object usrRemoveHandler(HttpSession session,String usr) { + if(!SessionUtils.hasAdminRight(session)){ + return pushMsg("你没有权限删除用户!", false); + } + if (SessionUtils.getLogedUser(session).getUsr().equals(usr)) {// 当前用户 + return pushMsg("不能删除自己!", false); + } + usrService.delete(usr); + return pushMsg(true); + } + + /** + * 查看用户权限 + * @param session + * @return + */ + @RequestMapping(value = "usrRightList", method = RequestMethod.GET, params = "action=data") + @ResponseBody + public Object usrRightListDataSet(HttpSession session,String usr) { + //查看用户权限 + if(StringUtils.isBlank(usr)){ + usr = SessionUtils.getLogedUser(session).getUsr(); + } + List auths = this.usrService.getAuths(usr); + PageBean pageBean = new PageBean(); + pageBean.setRecordCount(auths.size()); + pageBean.setDataList(auths); + return pageBean; + } + + + /** + * 查看用户权限 + * @param session + * @return + */ + @RequestMapping(value = "usrRightListView", method = RequestMethod.GET) + public String usrRightListDataSet(HttpSession session) { + //查看用户权限 + return "usr/usr_auth"; + } + + /** + * 用户更改密码 + * @param session + * @return + */ + @RequestMapping(value = "updatePswd", method = RequestMethod.GET) + public String updatePswd(HttpSession session, ModelMap map) { + return "usr/usr_update_pswd"; + } + + /** + * 用户更改密码处理 + * @param request + * @return + */ + @RequestMapping(value = "usrUpdatePswdHandler", method = RequestMethod.POST) + @ResponseBody + public Object pjUsrAddHandler(HttpServletRequest request) { + Usr usr = SessionUtils.getLogedUser(request.getSession()); + Map params = HttpUtils.getParams(request); + //验证老密码和新密码 + String oldPsw = params.get("oldPsw"); + if(usr.getPsw().equals(EncryptUtil.encrypt(oldPsw))){ + //验证老密码通过 + //验证老密码和新密码是否一致 + String newPsw = params.get("newPsw"); + if(usr.getPsw().equals(EncryptUtil.encrypt(newPsw))){ + return pushMsg("新密码不能和老密码保持一致", false); + } + //更新用户登录密码 + usr.setPsw(EncryptUtil.encrypt(newPsw)); + usrService.save(usr); + //更新用户项目认证密码 + List pjList = usrService.getPjList(usr.getUsr()); + for (Pj pj : pjList) { + PjUsr pjUsr = new PjUsr(); + pjUsr.setUsr(usr.getUsr()); + pjUsr.setPj(pj.getPj()); + pjUsr.setPsw(EncryptUtil.encrypt(newPsw)); + pjUsrService.save(pjUsr); + } + return pushMsg("用户项目认证密码修改成功", true); + }else{ + return pushMsg("您输入的老密码有误", false); + } + } + +} diff --git a/src/main/java/org/svnadmin/dao/Dao.java b/src/main/java/org/svnadmin/dao/Dao.java new file mode 100644 index 0000000..02dc650 --- /dev/null +++ b/src/main/java/org/svnadmin/dao/Dao.java @@ -0,0 +1,99 @@ +package org.svnadmin.dao; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import javax.annotation.Resource; +import javax.sql.DataSource; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.jdbc.datasource.DataSourceUtils; + +/** + * 所有DAO的父类 + * + * @author Huiwu Yuan + * @since 1.0 + * + */ +public class Dao { + + /** + * 日志 + */ + private final Log LOG = LogFactory.getLog(Dao.class); + + /** + * 数据源 + */ + @Resource(name = "dataSource") + DataSource dataSource; + + /** + * @return 数据源 + */ + protected DataSource getDataSource() { + return this.dataSource; + } + + /** + * @return 数据库连接 + */ + protected Connection getConnection() { + return DataSourceUtils.getConnection(getDataSource()); + } + /** + * 验证是否可以连接上数据库 see Issue 12 + * + * @throws SQLException jdbc异常 + */ + public void validatConnection() throws SQLException { + Connection conn = null; + try { + conn = this.getConnection(); + } finally { + this.close(null, null, conn); + } + } + /** + * 关闭资源 + * + * @param rs + * ResultSet + * @param s + * Statement + * @param conn + * 数据库连接 + */ + protected void close(ResultSet rs, Statement s, Connection conn) { + // rs + if (rs != null) { + try { + rs.close(); + } catch (SQLException e) { + LOG.error(e.getMessage()); + } + } + // s + if (s != null) { + try { + s.close(); + } catch (SQLException e) { + LOG.error(e.getMessage()); + } + } + // conn + if (conn != null) { + try { + // conn.close(); + DataSourceUtils.releaseConnection(conn, getDataSource()); + } catch (Exception e) { + LOG.error(e.getMessage()); + } + } + + } +} \ No newline at end of file diff --git a/src/main/java/org/svnadmin/dao/I18nDao.java b/src/main/java/org/svnadmin/dao/I18nDao.java new file mode 100644 index 0000000..0dffee2 --- /dev/null +++ b/src/main/java/org/svnadmin/dao/I18nDao.java @@ -0,0 +1,268 @@ +/** + * + */ +package org.svnadmin.dao; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Repository; +import org.svnadmin.entity.I18n; + +/** + * 语言DAO + * + * @author Huiwu Yuan + * @since 3.0.2 + */ +@Repository(I18nDao.BEAN_NAME) +public class I18nDao extends Dao { + /** + * Bean名称 + */ + public static final String BEAN_NAME="i18nDao"; + + /** + * + * @param lang 语言 + * @param id 键值 + * @return 多语言 + */ + public I18n get(String lang,String id) { + String sql = "select lang,id,lbl from i18n where lang=? and id=?"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, lang); + pstmt.setString(index++, id); + + rs = pstmt.executeQuery(); + if (rs.next()) { + return readI18n(rs); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + return null; + } + + /** + * + * @return 多语言列表 + */ + public List getList() { + String sql = "select lang,id,lbl from i18n order by lang,id"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + List results = new ArrayList(); + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + + rs = pstmt.executeQuery(); + while (rs.next()) { + results.add(readI18n(rs)); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + return results; + } + /** + * @param id 键值 + * @return 相同键值的语言列表 + */ + public Map getI18ns(String id) { + String sql = "select lang,id,lbl from i18n where id=?"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + Map results = new HashMap(); + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, id); + + rs = pstmt.executeQuery(); + while (rs.next()) { + I18n i18n = readI18n(rs); + results.put(i18n.getLang(),i18n); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + return results; + } + /** + * 从ResultSet中读取i18n对象 + * + * @param rs + * ResultSet + * @return i18n对象 + * @throws SQLException + * JDBC异常 + */ + I18n readI18n(ResultSet rs) throws SQLException { + I18n result = new I18n(); + result.setLang(rs.getString("lang")); + result.setId(rs.getString("id")); + result.setLbl(rs.getString("lbl")); + return result; + } + + /** + * 更新 + * + * @param i18n 多语言 + * + * @return 更新数量 + */ + public int update(I18n i18n) { + String sql = "update i18n set lbl=? where lang=? and id=?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, i18n.getLbl()); + pstmt.setString(index++, i18n.getLang()); + pstmt.setString(index++, i18n.getId()); + + return pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 增加 + * + * @param i18n 多语言 + * + * @return 更新数量 + */ + public int insert(I18n i18n) { + String sql = "insert into i18n (lang,id,lbl) values (?,?,?)"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, i18n.getLang()); + pstmt.setString(index++, i18n.getId()); + pstmt.setString(index++, i18n.getLbl()); + + return pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + /** + * 是否存在这种语言 + * @param lang 语言 + * @return true表示数据库存在这个语言,否则返回false + */ + public boolean existsLang(String lang) { + String sql = "select count(1) from i18n where lang=?"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + pstmt.setString(1, lang); + rs = pstmt.executeQuery(); + if (rs.next()) { + return rs.getInt(1)>0; + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + return false; + } + /** + * @return 获取系统现有的语言 + */ + public List getLangs() { + String sql = "select distinct lang from i18n order by lang"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + List results = new ArrayList(); + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + + rs = pstmt.executeQuery(); + while (rs.next()) { + results.add(rs.getString("lang")); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + return results; + } + /** + * @return 键值列表 + */ + public List getIds() { + String sql = "select id,count(id) total from i18n group by id order by id"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + List results = new ArrayList(); + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + + rs = pstmt.executeQuery(); + while (rs.next()) { + I18n i18n = new I18n(); + i18n.setId(rs.getString("id")); + i18n.setTotal(rs.getInt("total")); + results.add(i18n); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + return results; + } +} diff --git a/src/main/java/org/svnadmin/dao/PjAuthDao.java b/src/main/java/org/svnadmin/dao/PjAuthDao.java new file mode 100644 index 0000000..41d40a0 --- /dev/null +++ b/src/main/java/org/svnadmin/dao/PjAuthDao.java @@ -0,0 +1,585 @@ +package org.svnadmin.dao; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang.StringUtils; +import org.springframework.stereotype.Repository; +import org.svnadmin.constant.Constants; +import org.svnadmin.entity.PjAuth; + +/** + * 项目资源的权限DAO + * + * @author Huiwu Yuan + * @since 1.0 + * + */ +@Repository(PjAuthDao.BEAN_NAME) +public class PjAuthDao extends Dao { + /** + * Bean名称 + */ + public static final String BEAN_NAME = "pjAuthDao"; + + /** + * @param pj + * 项目 + * @param gr + * 组 + * @param res + * 资源 + * @return 项目组资源的权限 + */ + public PjAuth getByGr(String pj, String gr, String res) { + String sql = "select pj,res,rw,gr,' ' usr,' ' usrname from pj_gr_auth where pj = ? and gr=? and res=? "; + + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, gr); + pstmt.setString(index++, res); + + rs = pstmt.executeQuery(); + if (rs.next()) { + return readPjAuth(rs); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + return null; + } + + /** + * @param pj + * 项目 + * @param usr + * 用户 + * @param res + * 资源 + * @return 项目用户资源的权限 + */ + public PjAuth getByUsr(String pj, String usr, String res) { + String sql = "select a.pj,a.res,a.rw,b.usr,b.name as usrname,' ' gr from pj_usr_auth a left join usr b on (a.usr=b.usr) where a.pj = ? and a.usr=? and a.res=? "; + + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, usr); + pstmt.setString(index++, res); + + rs = pstmt.executeQuery(); + if (rs.next()) { + return readPjAuth(rs); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + return null; + } + /** + * @param usr + * 用户 + * @return 用户的权限 + */ + public List getByUsr(String usr) { + String sql = "select b.pj,p.des,b.usr,b.res,b.rw from usr a"; + sql+=" join pj_usr_auth b on (a.usr = b.usr)"; + sql+=" join pj p on (b.pj=p.pj)"; + sql+=" where a.usr=?"; + + sql+=" union all"; + + sql+=" select c.pj,p.des,a.usr,c.res,c.rw from usr a"; + sql+=" join pj_gr_usr b on (a.usr = b.usr)"; + sql+=" join pj_gr_auth c on (b.pj = c.pj and b.gr = c.gr)"; + sql+=" join pj p on (b.pj=p.pj)"; + sql+=" where a.usr=?"; + + sql+=" order by 1,4";//TODO 为了兼容sqlserver + + List list = new ArrayList(); + + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, usr); + pstmt.setString(index++, usr); + + rs = pstmt.executeQuery(); + while (rs.next()) { + + PjAuth result = new PjAuth(); + result.setPj(rs.getString("pj")); + result.setDes(rs.getString("des")); + result.setUsr(rs.getString("usr")); + result.setRes(rs.getString("res")); + String rw = rs.getString("rw"); + if (StringUtils.isBlank(rw)) { + rw = ""; + } + result.setRw(rw); + + list.add(result); + } + return list; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + } + + /** + * @param pj + * 项目 + * @param res 资源 + * @return 项目资源的权限列表 + */ + public List getList(String pj,String res) { + String sql = "select pj,res,rw,gr,' ' usr,' ' usrname from pj_gr_auth where pj=? and res = ? " + + " UNION " + + " select a.pj,a.res,a.rw,' ' gr,a.usr,b.name as usrname from pj_usr_auth a left join usr b on (a.usr=b.usr) where a.pj=? and a.res = ? " + + " order by res,gr,usr"; + List list = new ArrayList(); + + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, res); + pstmt.setString(index++, pj); + pstmt.setString(index++, res); + + rs = pstmt.executeQuery(); + while (rs.next()) { + list.add(readPjAuth(rs)); + } + return list; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + } + /** + * @param pj + * 项目 + * @return 项目资源的权限列表 + */ + public List getList(String pj) { + String sql = "select pj,res,rw,gr,' ' usr,' ' usrname from pj_gr_auth where pj=? " + + " UNION " + + " select a.pj,a.res,a.rw,' ' gr,a.usr,b.name as usrname from pj_usr_auth a left join usr b on (a.usr = b.usr) where a.pj=? " + + " order by res,gr,usr"; + List list = new ArrayList(); + + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, pj); + + rs = pstmt.executeQuery(); + while (rs.next()) { + list.add(readPjAuth(rs)); + } + return list; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + } + + /** + * @param rootPath + * svn root path + * @return 具有相同svn root的项目资源的权限列表 + */ + public List getListByRootPath(String rootPath) { + String sql = "select pj,res,rw,gr,' ' usr,' ' usrname from pj_gr_auth where pj in (select distinct pj from pj where type=? and path like ?) " + + " UNION " + + " select a.pj,a.res,a.rw,' ' gr,a.usr,b.name usrname from pj_usr_auth a left join usr b on (a.usr=b.usr) where a.pj in (select distinct pj from pj where type=? and path like ?) " + + " order by res,gr,usr"; + List list = new ArrayList(); + + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, Constants.HTTP_MUTIL); + pstmt.setString(index++, rootPath + "%");//TODO 大小写敏感? + pstmt.setString(index++, Constants.HTTP_MUTIL); + pstmt.setString(index++, rootPath + "%");//TODO 大小写敏感? + + rs = pstmt.executeQuery(); + while (rs.next()) { + list.add(readPjAuth(rs)); + } + return list; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + } + + /** + * @param rs + * ResultSet + * @return 项目资源的权限 + * @throws SQLException + * jdbc异常 + */ + PjAuth readPjAuth(ResultSet rs) throws SQLException { + PjAuth result = new PjAuth(); + result.setPj(rs.getString("pj")); + result.setGr(rs.getString("gr")); + result.setUsr(rs.getString("usr")); + result.setUsrName(rs.getString("usrname")); + result.setRes(rs.getString("res")); + String rw = rs.getString("rw"); + if (StringUtils.isBlank(rw)) { + rw = ""; + } + result.setRw(rw); + + return result; + } + + /** + * 删除项目 组资源的权限 + * + * @param pj + * 项目 + * @param gr + * 组 + * @param res + * 资源 + */ + public void deleteByGr(String pj, String gr, String res) { + String sql = "delete from pj_gr_auth where pj = ? and gr=? and res=? "; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, gr); + pstmt.setString(index++, res); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 删除项目用户资源的权限 + * + * @param pj + * 项目 + * @param usr + * 用户 + * @param res + * 资源 + */ + public void deleteByUsr(String pj, String usr, String res) { + String sql = "delete from pj_usr_auth where pj = ? and usr=? and res=? "; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, usr); + pstmt.setString(index++, res); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 删除项目 资源的权限 + * + * @param pj + * 项目 + */ + public void deletePj(String pj) { + // pj_gr_auth + String sql = "delete from pj_gr_auth where pj = ?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + // pj_usr_auth + sql = "delete from pj_usr_auth where pj = ?"; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 删除项目 组资源的权限 + * + * @param pj + * 项目 + * @param gr + * 组 + */ + public void deletePjGr(String pj, String gr) { + String sql = "delete from pj_gr_auth where pj = ? and gr=?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, gr); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 删除用户的项目资源的权限 + * + * @param usr + * 用户 + */ + public void deleteUsr(String usr) { + String sql = "delete from pj_usr_auth where usr=?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, usr); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 保存项目组权限 + * + * @param pjAuth + * 项目组权限 + */ + public void saveByGr(PjAuth pjAuth) { + if (this.getByGr(pjAuth.getPj(), pjAuth.getGr(), pjAuth.getRes()) == null) { + String sql = "insert into pj_gr_auth (pj,gr,res,rw) values (?,?,?,?)"; + + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pjAuth.getPj()); + pstmt.setString(index++, pjAuth.getGr()); + pstmt.setString(index++, pjAuth.getRes()); + pstmt.setString(index++, pjAuth.getRw()); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } else { + String sql = "update pj_gr_auth set rw=? where pj=? and gr=? and res=?"; + + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pjAuth.getRw()); + pstmt.setString(index++, pjAuth.getPj()); + pstmt.setString(index++, pjAuth.getGr()); + pstmt.setString(index++, pjAuth.getRes()); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + } + + /** + * 保存项目用户权限 + * + * @param pjAuth + * 项目用户权限 + */ + public void saveByUsr(PjAuth pjAuth) { + if (this.getByUsr(pjAuth.getPj(), pjAuth.getUsr(), pjAuth.getRes()) == null) { + String sql = "insert into pj_usr_auth (pj,usr,res,rw) values (?,?,?,?)"; + + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pjAuth.getPj()); + pstmt.setString(index++, pjAuth.getUsr()); + pstmt.setString(index++, pjAuth.getRes()); + pstmt.setString(index++, pjAuth.getRw()); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } else { + String sql = "update pj_usr_auth set rw=? where pj=? and usr=? and res=?"; + + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pjAuth.getRw()); + pstmt.setString(index++, pjAuth.getPj()); + pstmt.setString(index++, pjAuth.getUsr()); + pstmt.setString(index++, pjAuth.getRes()); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + } + + /** + * @param pj + * 项目 + * @return 项目的资源列表 + */ + public List getResList(String pj) { + String sql = "select distinct res from pj_gr_auth where pj=? " + + " UNION select distinct res from pj_usr_auth where pj=? order by res"; + + List list = new ArrayList(); + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, pj); + + rs = pstmt.executeQuery(); + while (rs.next()) { + list.add(rs.getString("res")); + + } + return list; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + + } + +} \ No newline at end of file diff --git a/src/main/java/org/svnadmin/dao/PjDao.java b/src/main/java/org/svnadmin/dao/PjDao.java new file mode 100644 index 0000000..3a81f68 --- /dev/null +++ b/src/main/java/org/svnadmin/dao/PjDao.java @@ -0,0 +1,267 @@ +package org.svnadmin.dao; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang.StringUtils; +import org.springframework.stereotype.Repository; +import org.svnadmin.constant.Constants; +import org.svnadmin.entity.Pj; + +/** + * 项目DAO + * + * @author Huiwu Yuan + * + */ +@Repository(PjDao.BEAN_NAME) +public class PjDao extends Dao { + /** + * Bean名称 + */ + public static final String BEAN_NAME = "pjDao"; + + /** + * @param pj + * 项目 + * @return 项目 + */ + public Pj get(String pj) { + String sql = "select pj,path,url,des,type from pj where pj = ?"; + + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + + rs = pstmt.executeQuery(); + if (rs.next()) { + return readPj(rs); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + return null; + } + + /** + * @return 项目列表 + */ + public List getList() { + String sql = "select pj,path,url,des,type from pj order by pj"; + List list = new ArrayList(); + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + + rs = pstmt.executeQuery(); + while (rs.next()) { + list.add(readPj(rs)); + } + return list; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + } + + /** + * @param usr + * 用户 + * @return 用户有权限的项目列表(用户是否是这个项目的管理员) + */ + public List getList(String usr) { + String sql = "select p.pj,p.path,p.url,p.des,p.type,pm.pj manager from ( " + + " select distinct a.pj,a.path,a.url,a.des,a.type from pj a where " + + " exists (select b.usr from pj_gr_usr b where a.pj=b.pj and b.usr=?) " + + " or exists(select c.usr from pj_usr_auth c where a.pj=c.pj and c.usr=?) " + + " ) p " + + " left join ( " + + " select distinct a.pj from pj a where " + // TODO like ? 应该是 = ? ,用like主要是兼容3.0版本 see: Issue 4 + + " exists (select b.usr from pj_gr_usr b where a.pj=b.pj and b.usr=? and b.gr like ?)" + + " ) pm on p.pj=pm.pj"; + List list = new ArrayList(); + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, usr); + pstmt.setString(index++, usr); + pstmt.setString(index++, usr); + // TODO 主要是兼容3.0版本 + pstmt.setString(index++, "%" + Constants.GROUP_MANAGER); + + rs = pstmt.executeQuery(); + while (rs.next()) { + Pj pj = readPj(rs); + String manager = rs.getString("manager");// 是否是管理员组的用户 + pj.setManager(StringUtils.isNotBlank(manager)); + list.add(pj); + } + return list; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + } + + /** + * @param rs + * ResultSet + * @return 项目 + * @throws SQLException + * jdbc异常 + */ + public Pj readPj(ResultSet rs) throws SQLException { + Pj result = new Pj(); + result.setPj(rs.getString("pj")); + result.setPath(rs.getString("path")); + result.setUrl(rs.getString("url")); + result.setDes(rs.getString("des")); + result.setType(rs.getString("type")); + return result; + } + + /** + * 删除 + * + * @param pj + * 项目 + */ + public void delete(String pj) { + String sql = "delete from pj where pj = ?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 增加项目 + * + * @param pj + * 项目 + * @return 影响数量 + */ + public int insert(Pj pj) { + String sql = "insert into pj (pj,path,url,des,type) values (?,?,?,?,?)"; + + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj.getPj()); + pstmt.setString(index++, pj.getPath()); + pstmt.setString(index++, pj.getUrl()); + pstmt.setString(index++, pj.getDes()); + pstmt.setString(index++, pj.getType()); + + return pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 保存项目 + * + * @param pj + * 项目 + * @return 影响数量 + */ + public int update(Pj pj) { + String sql = "update pj set path=?,url=?,des=?,type=? where pj = ?"; + + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj.getPath()); + pstmt.setString(index++, pj.getUrl()); + pstmt.setString(index++, pj.getDes()); + pstmt.setString(index++, pj.getType()); + pstmt.setString(index++, pj.getPj()); + + return pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 获取具有相同路径或访问地址的项目数量 + * + * @param path + * 路径 + * @param url + * 访问地址 + * @return 具有相同路径或访问地址的项目数量 + */ + public int getCount(String path, String url) { + String sql = "select count(1) from pj where path=? or url=?";//TODO 大小写敏感? + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, path); + pstmt.setString(index++, url); + + rs = pstmt.executeQuery(); + if (rs.next()) { + return rs.getInt(1); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + return 0; + } +} \ No newline at end of file diff --git a/src/main/java/org/svnadmin/dao/PjGrDao.java b/src/main/java/org/svnadmin/dao/PjGrDao.java new file mode 100644 index 0000000..e35ba4f --- /dev/null +++ b/src/main/java/org/svnadmin/dao/PjGrDao.java @@ -0,0 +1,206 @@ +package org.svnadmin.dao; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Repository; +import org.svnadmin.entity.PjGr; + +/** + * 项目组 + * + * @author Huiwu Yuan + * + */ +@Repository(PjGrDao.BEAN_NAME) +public class PjGrDao extends Dao { + /** + * Bean名称 + */ + public static final String BEAN_NAME = "pjGrDao"; + + /** + * @param pj + * 项目 + * @param gr + * 组 + * @return 项目组 + */ + public PjGr get(String pj, String gr) { + String sql = "select pj,gr,des from pj_gr where pj = ? and gr=?"; + + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, gr); + + rs = pstmt.executeQuery(); + if (rs.next()) { + return readPjGr(rs); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + return null; + } + + /** + * @param pj + * 项目 + * @return 项目组列表 + */ + public List getList(String pj) { + String sql = "select pj,gr,des from pj_gr where pj=? order by pj,gr"; + List list = new ArrayList(); + + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + + rs = pstmt.executeQuery(); + while (rs.next()) { + list.add(readPjGr(rs)); + } + return list; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + } + + /** + * @param rs + * ResultSet + * @return 项目组 + * @throws SQLException + * jdbc异常 + */ + PjGr readPjGr(ResultSet rs) throws SQLException { + PjGr result = new PjGr(); + result.setPj(rs.getString("pj")); + result.setGr(rs.getString("gr")); + result.setDes(rs.getString("des")); + return result; + } + + /** + * 删除 + * + * @param pj + * 项目 + * @param gr + * 组 + */ + public void delete(String pj, String gr) { + String sql = "delete from pj_gr where pj = ? and gr=?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, gr); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 删除 + * + * @param pj + * 项目 + */ + public void deletePj(String pj) { + String sql = "delete from pj_gr where pj = ?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 保存 + * + * @param pjGr + * 项目组 + */ + public void save(PjGr pjGr) { + if (this.get(pjGr.getPj(), pjGr.getGr()) == null) { + String sql = "insert into pj_gr (pj,gr,des) values (?,?,?)"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pjGr.getPj()); + pstmt.setString(index++, pjGr.getGr()); + pstmt.setString(index++, pjGr.getDes()); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } else { + String sql = "update pj_gr set des=? where pj = ? and gr=?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pjGr.getDes()); + pstmt.setString(index++, pjGr.getPj()); + pstmt.setString(index++, pjGr.getGr()); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + } + +} \ No newline at end of file diff --git a/src/main/java/org/svnadmin/dao/PjGrUsrDao.java b/src/main/java/org/svnadmin/dao/PjGrUsrDao.java new file mode 100644 index 0000000..d81acb9 --- /dev/null +++ b/src/main/java/org/svnadmin/dao/PjGrUsrDao.java @@ -0,0 +1,320 @@ +package org.svnadmin.dao; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Repository; +import org.svnadmin.constant.Constants; +import org.svnadmin.entity.PjGrUsr; + +/** + * 项目的组的用户 + * + * @author Huiwu Yuan + * + */ +@Repository(PjGrUsrDao.BEAN_NAME) +public class PjGrUsrDao extends Dao { + /** + * Bean名称 + */ + public static final String BEAN_NAME = "pjGrUsrDao"; + + /** + * @param pj + * 项目 + * @param gr + * 组 + * @param usr + * 用户 + * @return 组用户 + */ + public PjGrUsr get(String pj, String gr, String usr) { + String sql = "select a.pj,a.usr,a.gr,b.name as usrname from pj_gr_usr a left join usr b on (a.usr=b.usr) where a.pj = ? and a.gr=? and a.usr=?"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, gr); + pstmt.setString(index++, usr); + + rs = pstmt.executeQuery(); + if (rs.next()) { + return readPjGrUsr(rs); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + return null; + } + + /** + * @param pj + * 项目 + * @param gr + * 组 + * @return 组用户列表 + */ + public List getList(String pj, String gr) { + String sql = "select a.pj,a.usr,a.gr,b.name as usrname from pj_gr_usr a left join usr b on (a.usr = b.usr) where a.pj=? and a.gr=? order by a.usr"; + List list = new ArrayList(); + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, gr); + + rs = pstmt.executeQuery(); + while (rs.next()) { + list.add(readPjGrUsr(rs)); + } + return list; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + } + + /** + * 项目的组用户列表(用户可能为空),导出authz文件时使用 + * + * @param pj + * 项目 + * @return 项目的组用户列表 + */ + public List getList(String pj) { + // String sql = + // "select pj,usr,gr from pj_gr_usr where pj=? order by gr,usr"; + String sql = "select a.pj,a.gr,b.usr,c.name as usrname from pj_gr a left join pj_gr_usr b on (a.pj=b.pj and a.gr=b.gr) left join usr c on (b.usr = c.usr) where a.pj=? order by a.gr,b.usr"; + List list = new ArrayList(); + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + + rs = pstmt.executeQuery(); + while (rs.next()) { + list.add(readPjGrUsr(rs)); + } + return list; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + } + + /** + * 有相同的svn root的项目的组用户列表(用户可能为空),导出authz文件时使用 + * + * @param rootPath + * svn root + * @return 有相同的svn root的项目组用户 + */ + public List getListByRootPath(String rootPath) { + // String sql = + // "select pj,usr,gr from pj_gr_usr where pj in (select distinct pj from pj where type=? and path like ?) order by pj,gr,usr"; + String sql = "select a.pj,a.gr,b.usr,c.name as usrname from pj_gr a left join pj_gr_usr b on (a.pj=b.pj and a.gr=b.gr) left join usr c on (b.usr=c.usr) " + + " where a.pj in (select distinct pj from pj where type=? and path like ?) order by a.pj,a.gr,b.usr"; + List list = new ArrayList(); + + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, Constants.HTTP_MUTIL); + pstmt.setString(index++, rootPath + "%");//TODO 大小写敏感? + + rs = pstmt.executeQuery(); + while (rs.next()) { + list.add(readPjGrUsr(rs)); + } + return list; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + } + + /** + * @param rs + * ResultSet + * @return 组用户 + * @throws SQLException + * jdbc异常 + */ + PjGrUsr readPjGrUsr(ResultSet rs) throws SQLException { + PjGrUsr result = new PjGrUsr(); + result.setPj(rs.getString("pj")); + result.setUsr(rs.getString("usr")); + result.setGr(rs.getString("gr")); + result.setUsrName(rs.getString("usrname")); + return result; + } + + /** + * 删除 + * + * @param pj + * 项目 + * @param gr + * 组 + * @param usr + * 用户 + */ + public void delete(String pj, String gr, String usr) { + String sql = "delete from pj_gr_usr where pj = ? and gr=? and usr=?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, gr); + pstmt.setString(index++, usr); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 删除 + * + * @param usr + * 用户 + */ + public void deleteUsr(String usr) { + String sql = "delete from pj_gr_usr where usr = ?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, usr); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 删除 + * + * @param pj + * 项目 + * @param gr + * 组 + */ + public void deletePjGr(String pj, String gr) { + String sql = "delete from pj_gr_usr where pj = ? and gr = ?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, gr); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 删除 + * + * @param pj + * 项目 + */ + public void deletePj(String pj) { + String sql = "delete from pj_gr_usr where pj = ?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 保存 + * + * @param pjGrUsr + * 项目用户 + */ + public void save(PjGrUsr pjGrUsr) { + if (this.get(pjGrUsr.getPj(), pjGrUsr.getGr(), pjGrUsr.getUsr()) == null) { + String sql = "insert into pj_gr_usr (pj,usr,gr) values (?,?,?)"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pjGrUsr.getPj()); + pstmt.setString(index++, pjGrUsr.getUsr()); + pstmt.setString(index++, pjGrUsr.getGr()); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + } + +} \ No newline at end of file diff --git a/src/main/java/org/svnadmin/dao/PjUsrDao.java b/src/main/java/org/svnadmin/dao/PjUsrDao.java new file mode 100644 index 0000000..29f60df --- /dev/null +++ b/src/main/java/org/svnadmin/dao/PjUsrDao.java @@ -0,0 +1,240 @@ +package org.svnadmin.dao; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Repository; +import org.svnadmin.entity.PjUsr; + +/** + * + * 项目的用户。 只对单库方式有用,包括svn协议和http协议(单库),可以每个项目设置用户的密码。 + * + * @author Huiwu Yuan + * + */ +@Repository(PjUsrDao.BEAN_NAME) +public class PjUsrDao extends Dao { + /** + * Bean名称 + */ + public static final String BEAN_NAME = "pjUsrDao"; + + /** + * @param pj + * 项目 + * @param usr + * 用户 + * @return 项目用户 + */ + public PjUsr get(String pj, String usr) { + String sql = "select a.pj,a.usr,a.psw,b.name as usrname from pj_usr a left join usr b on (a.usr = b.usr) where a.pj = ? and a.usr=?"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, usr); + + rs = pstmt.executeQuery(); + if (rs.next()) { + return readPjUsr(rs); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + return null; + } + + /** + * @param pj + * 项目 + * @return 项目的用户列表 + */ + public List getList(String pj) { + String sql = "select a.pj,a.usr,a.psw,b.name usrname from pj_usr a left join usr b on (a.usr = b.usr) where a.pj = ?"; + List list = new ArrayList(); + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + + rs = pstmt.executeQuery(); + while (rs.next()) { + list.add(readPjUsr(rs)); + } + return list; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + } + + /** + * @param rs + * ResultSet + * @return PjUsr + * @throws SQLException + * jdbc异常 + */ + PjUsr readPjUsr(ResultSet rs) throws SQLException { + PjUsr result = new PjUsr(); + result.setPj(rs.getString("pj")); + result.setUsr(rs.getString("usr")); + result.setName(rs.getString("usrname")); + result.setPsw(rs.getString("psw")); + return result; + } + + /** + * 删除 + * + * @param pj + * 项目 + * @param usr + * 用户 + */ + public void delete(String pj, String usr) { + String sql = "delete from pj_usr where pj = ? and usr=?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, usr); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 删除这个项目的用户 + * + * @param pj + * 项目 + */ + public void deletePj(String pj) { + String sql = "delete from pj_usr where pj = ?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 删除用户 + * + * @param usr + * 用户 + */ + public void deleteUsr(String usr) { + String sql = "delete from pj_usr where usr = ?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, usr); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 增加一条记录 + * + * @param pjUsr + * 项目用户 + * @return 成功数量 + */ + public int insert(PjUsr pjUsr) { + String sql = "insert into pj_usr (pj,usr,psw) values (?,?,?)"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pjUsr.getPj()); + pstmt.setString(index++, pjUsr.getUsr()); + pstmt.setString(index++, pjUsr.getPsw()); + + return pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + + } + + /** + * 更新用户 + * + * @param pjUsr + * 项目用户 + * @return 更新的数量 + */ + public int update(PjUsr pjUsr) { + String sql = "update pj_usr set psw=? where pj = ? and usr=?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pjUsr.getPsw()); + pstmt.setString(index++, pjUsr.getPj()); + pstmt.setString(index++, pjUsr.getUsr()); + + return pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + +} \ No newline at end of file diff --git a/src/main/java/org/svnadmin/dao/UsrDao.java b/src/main/java/org/svnadmin/dao/UsrDao.java new file mode 100644 index 0000000..e8ec454 --- /dev/null +++ b/src/main/java/org/svnadmin/dao/UsrDao.java @@ -0,0 +1,326 @@ +package org.svnadmin.dao; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Repository; +import org.svnadmin.constant.Constants; +import org.svnadmin.entity.Usr; + +/** + * 用户DAO + * + * @author Huiwu Yuan + * + */ +@Repository(UsrDao.BEAN_NAME) +public class UsrDao extends Dao { + + /** + * Bean名称 + */ + public static final String BEAN_NAME = "usrDao"; + + /** + * 获取一个用户 + * + * @param usr + * 用户 + * @return 用户 + */ + public Usr get(String usr) { + String sql = "select usr,name,psw,role from usr where usr=?"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, usr); + + rs = pstmt.executeQuery(); + if (rs.next()) { + return readUsr(rs); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + return null; + } + + /** + * @return 所有用户列表 + */ + public List getList() { + String sql = "select usr,name,psw,role from usr order by usr"; + List list = new ArrayList(); + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + + rs = pstmt.executeQuery(); + while (rs.next()) { + list.add(readUsr(rs)); + } + return list; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + } + + /** + * 获取这个项目组未选的用户(不包括*) + * + * @param pj + * 项目 + * @param gr + * 组 + * @return 项目组未选的用户(不包括*) + */ + public List listUnSelected(String pj, String gr) { + String sql = "select usr,name,psw,role from usr a where a.usr <> '*' " + + " and not exists (select usr from pj_gr_usr b where a.usr = b.usr and b.pj=? and b.gr=?) order by a.usr"; + List list = new ArrayList(); + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, gr); + rs = pstmt.executeQuery(); + while (rs.next()) { + list.add(readUsr(rs)); + } + return list; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + } + + /** + * @param pj + * 项目 + * @return 所有项目用户列表(不包括*) + */ + public List getList(String pj) { + String sql = "select p.usr,p.name,p.role,CASE WHEN pu.psw IS NOT NULL THEN pu.psw ELSE p.psw END psw from (" + + " select a.usr,a.role,a.psw,a.name from usr a " + + " where " + + " exists (select d.usr from pj_gr_usr d where d.usr=a.usr and d.pj=?) " + + " or exists(select c.usr from pj_usr_auth c where a.usr=c.usr and c.pj=?) " + + " ) p " + + " left join pj_usr pu on (p.usr=pu.usr and pu.pj=?) where p.usr <> '*'" + + " order by p.usr "; + + List list = new ArrayList(); + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, pj); + pstmt.setString(index++, pj); + pstmt.setString(index++, pj); + + rs = pstmt.executeQuery(); + while (rs.next()) { + list.add(readUsr(rs)); + } + return list; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + } + + /** + * @param rootPath + * 项目所在的svn root + * @return 所有相同svn root的项目的用户列表(不包括*) + */ + public List getListByRootPath(String rootPath) { + String sql = "select p.usr,p.name,p.role,CASE WHEN pu.psw IS NOT NULL THEN pu.psw ELSE p.psw END psw from (" + + " select a.usr,a.role,a.psw,a.name from usr a " + + " where " + + " exists (select d.usr from pj_gr_usr d where d.usr=a.usr and d.pj in (select distinct pj from pj where type=? and path like ?)) " + + " or exists(select c.usr from pj_usr_auth c where a.usr=c.usr and c.pj in (select distinct pj from pj where type=? and path like ?)) " + + " ) p " + + " left join pj_usr pu on (p.usr=pu.usr) where p.usr <> '*'" + + " order by p.usr "; + + List list = new ArrayList(); + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, Constants.HTTP_MUTIL); + pstmt.setString(index++, rootPath + "%");//TODO 大小写敏感? + pstmt.setString(index++, Constants.HTTP_MUTIL); + pstmt.setString(index++, rootPath + "%");//TODO 大小写敏感? + + rs = pstmt.executeQuery(); + while (rs.next()) { + list.add(readUsr(rs)); + } + return list; + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + } + + /** + * 从ResultSet中读取Usr对象 + * + * @param rs + * ResultSet + * @return Usr对象 + * @throws SQLException + * JDBC异常 + */ + Usr readUsr(ResultSet rs) throws SQLException { + Usr result = new Usr(); + result.setUsr(rs.getString("usr")); + result.setName(rs.getString("name")); + result.setPsw(rs.getString("psw")); + result.setRole(rs.getString("role")); + return result; + } + + /** + * 删除用户 + * + * @param usr + * 用户 + */ + public void delete(String usr) { + String sql = "delete from usr where usr=?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, usr); + + pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 更新用户 + * + * @param usr + * 用户 + * @return 更新数量 + */ + public int update(Usr usr) { + String sql = "update usr set psw=?,name=?,role=? where usr=?"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, usr.getPsw()); + pstmt.setString(index++, usr.getName()); + pstmt.setString(index++, usr.getRole()); + pstmt.setString(index++, usr.getUsr()); + + return pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * 增加一个用户 + * + * @param usr + * 用户 + * @return 更新数量 + */ + public int insert(Usr usr) { + String sql = "insert into usr (usr,psw,name,role) values (?,?,?,?)"; + Connection conn = null; + PreparedStatement pstmt = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + int index = 1; + pstmt.setString(index++, usr.getUsr()); + pstmt.setString(index++, usr.getPsw()); + pstmt.setString(index++, usr.getName()); + pstmt.setString(index++, usr.getRole()); + + return pstmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(null, pstmt, conn); + } + } + + /** + * @return 总数(不包括*) + */ + public int getCount() { + String sql = "select count(1) from usr where usr <> '*'"; + Connection conn = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + pstmt = conn.prepareStatement(sql); + + rs = pstmt.executeQuery(); + if (rs.next()) { + return rs.getInt(1); + } + } catch (SQLException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } finally { + this.close(rs, pstmt, conn); + } + return 0; + } +} \ No newline at end of file diff --git a/src/main/java/org/svnadmin/entity/Ajax.java b/src/main/java/org/svnadmin/entity/Ajax.java new file mode 100644 index 0000000..c11497f --- /dev/null +++ b/src/main/java/org/svnadmin/entity/Ajax.java @@ -0,0 +1,66 @@ +package org.svnadmin.entity; + +import java.io.Serializable; + +/** + * ajax服务层返回的结果 + * + * @author Huiwu Yuan + * @since 3.0.2 + */ +public class Ajax implements Serializable{ + /** + * 序列化ID + */ + private static final long serialVersionUID = -545103916156321718L; + /** + * content type + */ + private String contentType; + /** + * 结果 + */ + private String result; + + /** + * 默认构造函数 + */ + public Ajax() { + } + + + /** + * 构造函数 + * @param contentType content type + * @param result 结果 + */ + public Ajax(String contentType,String result){ + this.contentType=contentType; + this.result=result; + } + + /** + * @return content type + */ + public String getContentType() { + return contentType; + } + /** + * @param contentType content type + */ + public void setContentType(String contentType) { + this.contentType = contentType; + } + /** + * @return 结果 + */ + public String getResult() { + return result; + } + /** + * @param result 结果 + */ + public void setResult(String result) { + this.result = result; + } +} diff --git a/src/main/java/org/svnadmin/entity/I18n.java b/src/main/java/org/svnadmin/entity/I18n.java new file mode 100644 index 0000000..4760d4c --- /dev/null +++ b/src/main/java/org/svnadmin/entity/I18n.java @@ -0,0 +1,84 @@ +/** + * + */ +package org.svnadmin.entity; + +import java.io.Serializable; + +/** + * @author Harvey + * @since 3.0.2 + * + */ +public class I18n implements Serializable { + /** + * + */ + private static final long serialVersionUID = -8731707774048772734L; + /** + * 语言 + */ + private String lang; + /** + * + */ + private String id; + /** + * + */ + private String lbl; + + /** + * ID对应的语言总数 + */ + private int total; + /** + * @return 语言 + */ + public String getLang() { + return lang; + } + /** + * @param lang 语言 + */ + public void setLang(String lang) { + this.lang = lang; + } + /** + * @return key + */ + public String getId() { + return id; + } + /** + * @param id key + */ + public void setId(String id) { + this.id = id; + } + /** + * @return label + */ + public String getLbl() { + return lbl; + } + /** + * @param lbl label + */ + public void setLbl(String lbl) { + this.lbl = lbl; + } + /** + * @return ID对应的语言总数 + */ + public int getTotal() { + return total; + } + /** + * @param total ID对应的语言总数 + */ + public void setTotal(int total) { + this.total = total; + } + +} diff --git a/src/main/java/org/svnadmin/entity/Pj.java b/src/main/java/org/svnadmin/entity/Pj.java new file mode 100644 index 0000000..e5781c2 --- /dev/null +++ b/src/main/java/org/svnadmin/entity/Pj.java @@ -0,0 +1,132 @@ +package org.svnadmin.entity; + +import java.io.Serializable; + +/** + * 项目 + * + * @author Huiwu Yuan + * + */ +public class Pj implements Serializable{ + /** + * + */ + private static final long serialVersionUID = 3570692240378418844L; + /** + * 项目ID + */ + private String pj; + /** + * 仓库位置 + */ + private String path; + /** + * 访问项目的svn地址 + */ + private String url; + /** + * 描述 + */ + private String des; + /** + * 类型 + */ + private String type; + + /** + * 用户是否是这个项目的管理员 + */ + private boolean manager; + + /** + * @return 项目ID + */ + public String getPj() { + return pj; + } + + /** + * @param pj + * 项目ID + */ + public void setPj(String pj) { + this.pj = pj; + } + + /** + * @return 仓库位置 + */ + public String getPath() { + return path; + } + + /** + * @param path + * 仓库位置 + */ + public void setPath(String path) { + this.path = path; + } + + /** + * @return 描述 + */ + public String getDes() { + return des; + } + + /** + * @param des + * 描述 + */ + public void setDes(String des) { + this.des = des; + } + + /** + * @return 类型 + */ + public String getType() { + return type; + } + + /** + * @param type + * 类型 + */ + public void setType(String type) { + this.type = type; + } + + /** + * @return 访问项目的svn地址 + */ + public String getUrl() { + return url; + } + + /** + * @param url + * 访问项目的svn地址 + */ + public void setUrl(String url) { + this.url = url; + } + + /** + * @return 用户是否是这个项目的管理员 + */ + public boolean isManager() { + return manager; + } + + /** + * @param manager + * 用户是否是这个项目的管理员 + */ + public void setManager(boolean manager) { + this.manager = manager; + } + +} diff --git a/src/main/java/org/svnadmin/entity/PjAuth.java b/src/main/java/org/svnadmin/entity/PjAuth.java new file mode 100644 index 0000000..8817fbc --- /dev/null +++ b/src/main/java/org/svnadmin/entity/PjAuth.java @@ -0,0 +1,152 @@ +package org.svnadmin.entity; + +import java.io.Serializable; + +/** + * 权限 + * + * @author Huiwu Yuan + * + */ +public class PjAuth implements Serializable { + /** + * + */ + private static final long serialVersionUID = -8744287510861451872L; + /** + * 资源 + */ + private String res; + /** + * 项目 + */ + private String pj; + /** + * 组 + */ + private String gr; + /** + * 用户 + */ + private String usr; + /** + * 用户姓名 + */ + private String usrName; + /** + * r : 可读; w : 可写 + */ + private String rw; + /** + * 描述 + */ + private String des; + + /** + * @return 资源 + */ + public String getRes() { + return res; + } + + /** + * @param res + * 资源 + */ + public void setRes(String res) { + this.res = res; + } + + /** + * @return 项目 + */ + public String getPj() { + return pj; + } + + /** + * @param pj + * 项目 + */ + public void setPj(String pj) { + this.pj = pj; + } + + /** + * @return 组 + */ + public String getGr() { + return gr; + } + + /** + * @param gr + * 组 + */ + public void setGr(String gr) { + this.gr = gr; + } + + /** + * @return r : 可读; w : 可写 + */ + public String getRw() { + return rw; + } + + /** + * @param rw + * r : 可读; w : 可写 + */ + public void setRw(String rw) { + this.rw = rw; + } + + /** + * @return 用户 + */ + public String getUsr() { + return usr; + } + + /** + * @param usr + * 用户 + */ + public void setUsr(String usr) { + this.usr = usr; + } + + /** + * + * @return 用户姓名 + */ + public String getUsrName() { + return usrName; + } + + /** + * + * @param usrName + * 用户姓名 + */ + public void setUsrName(String usrName) { + this.usrName = usrName; + } + + /** + * @return 描述 + */ + public String getDes() { + return des; + } + + /** + * @param des + * 描述 + */ + public void setDes(String des) { + this.des = des; + } + +} diff --git a/src/main/java/org/svnadmin/entity/PjGr.java b/src/main/java/org/svnadmin/entity/PjGr.java new file mode 100644 index 0000000..40d1951 --- /dev/null +++ b/src/main/java/org/svnadmin/entity/PjGr.java @@ -0,0 +1,74 @@ +package org.svnadmin.entity; + +import java.io.Serializable; + +/** + * 组 + * + * @author Huiwu Yuan + * + */ +public class PjGr implements Serializable{ + /** + * + */ + private static final long serialVersionUID = 6413099229527347938L; + /** + * 项目 + */ + private String pj; + /** + * 组 + */ + private String gr; + /** + * 描述 + */ + private String des; + + /** + * @return 项目 + */ + public String getPj() { + return pj; + } + + /** + * @param pj + * 项目 + */ + public void setPj(String pj) { + this.pj = pj; + } + + /** + * @return 描述 + */ + public String getDes() { + return des; + } + + /** + * @param des + * 描述 + */ + public void setDes(String des) { + this.des = des; + } + + /** + * @return 组 + */ + public String getGr() { + return gr; + } + + /** + * @param gr + * 组 + */ + public void setGr(String gr) { + this.gr = gr; + } + +} diff --git a/src/main/java/org/svnadmin/entity/PjGrUsr.java b/src/main/java/org/svnadmin/entity/PjGrUsr.java new file mode 100644 index 0000000..cdd89dc --- /dev/null +++ b/src/main/java/org/svnadmin/entity/PjGrUsr.java @@ -0,0 +1,93 @@ +package org.svnadmin.entity; + +import java.io.Serializable; + +/** + * 项目组用户 + * + * @author Huiwu Yuan + * + */ +public class PjGrUsr implements Serializable { + /** + * + */ + private static final long serialVersionUID = -2031955995574649327L; + /** + * 项目 + */ + private String pj; + /** + * 用户 + */ + private String usr; + /** + * 用户姓名 + */ + private String usrName; + /** + * 组 + */ + private String gr; + + /** + * @return 项目 + */ + public String getPj() { + return pj; + } + + /** + * @param pj + * 项目 + */ + public void setPj(String pj) { + this.pj = pj; + } + + /** + * @return 用户 + */ + public String getUsr() { + return usr; + } + + /** + * @return 用户姓名 + */ + public String getUsrName() { + return usrName; + } + + /** + * @param usrName + * 用户姓名 + */ + public void setUsrName(String usrName) { + this.usrName = usrName; + } + + /** + * @param usr + * 用户 + */ + public void setUsr(String usr) { + this.usr = usr; + } + + /** + * @return 组 + */ + public String getGr() { + return gr; + } + + /** + * @param gr + * 组 + */ + public void setGr(String gr) { + this.gr = gr; + } + +} diff --git a/src/main/java/org/svnadmin/entity/PjUsr.java b/src/main/java/org/svnadmin/entity/PjUsr.java new file mode 100644 index 0000000..1c0ad5f --- /dev/null +++ b/src/main/java/org/svnadmin/entity/PjUsr.java @@ -0,0 +1,34 @@ +package org.svnadmin.entity; + +/** + * 项目用户 。只对单库方式有用,包括svn协议和http协议(单库),可以每个项目设置用户的密码 + * + * @author Huiwu Yuan + * + */ +public class PjUsr extends Usr { + /** + * + */ + private static final long serialVersionUID = 5863709168694149752L; + /** + * 项目ID + */ + private String pj; + + /** + * @return 项目ID + */ + public String getPj() { + return pj; + } + + /** + * @param pj + * 项目ID + */ + public void setPj(String pj) { + this.pj = pj; + } + +} diff --git a/src/main/java/org/svnadmin/entity/Usr.java b/src/main/java/org/svnadmin/entity/Usr.java new file mode 100644 index 0000000..a6c7a76 --- /dev/null +++ b/src/main/java/org/svnadmin/entity/Usr.java @@ -0,0 +1,94 @@ +package org.svnadmin.entity; + +import java.io.Serializable; + +/** + * 用户 + * + * @author Huiwu Yuan + * + */ +public class Usr implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 8251147689572549482L; + /** + * 用户ID + */ + private String usr; + /** + * 用户姓名 + */ + private String name; + /** + * 密码(加密) + */ + private String psw; + /** + * 角色 + */ + private String role; + + /** + * @return 用户ID + */ + public String getUsr() { + return usr; + } + + /** + * @param usr + * 用户ID + */ + public void setUsr(String usr) { + this.usr = usr; + } + + /** + * @return 用户姓名 + */ + public String getName() { + return name; + } + + /** + * @param name + * 用户姓名 + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return 密码(加密) + */ + public String getPsw() { + return psw; + } + + /** + * @param psw + * 密码(加密) + */ + public void setPsw(String psw) { + this.psw = psw; + } + + /** + * @return 角色 + */ + public String getRole() { + return role; + } + + /** + * @param role + * 角色 + */ + public void setRole(String role) { + this.role = role; + } + +} diff --git a/src/main/java/org/svnadmin/exceptions/TimeoutException.java b/src/main/java/org/svnadmin/exceptions/TimeoutException.java new file mode 100644 index 0000000..29db02c --- /dev/null +++ b/src/main/java/org/svnadmin/exceptions/TimeoutException.java @@ -0,0 +1,24 @@ +package org.svnadmin.exceptions; + +/** + * 超时异常 + * + * @author Huiwu Yuan + * + */ +public class TimeoutException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * @param string + * 消息 + */ + public TimeoutException(String string) { + super(string); + } + +} diff --git a/src/main/java/org/svnadmin/service/AjaxService.java b/src/main/java/org/svnadmin/service/AjaxService.java new file mode 100644 index 0000000..72eaf75 --- /dev/null +++ b/src/main/java/org/svnadmin/service/AjaxService.java @@ -0,0 +1,41 @@ +package org.svnadmin.service; + +import java.util.Map; + +import org.svnadmin.entity.Ajax; + +/** + * ajax服务层接口 + * + * @author Huiwu Yuan + * @since 3.0.2 + */ +public interface AjaxService { + /** + * html + */ + public static final String CONTENTTYPE_HTML="text/html; charset=UTF-8"; + /** + * xml + */ + public static final String CONTENTTYPE_XML="text/xml; charset=UTF-8"; + /** + * json + */ + public static final String CONTENTTYPE_JSON="application/json; charset=UTF-8"; + /** + * javascript + */ + public static final String CONTENTTYPE_JAVASCRIPT="text/javascript; charset=UTF-8"; + /** + * text + */ + public static final String CONTENTTYPE_TEXT="text/plain; charset=UTF-8"; + + /** + * 执行逻辑 + * @param parameters 参数 + * @return 结果 + */ + Ajax execute(Map parameters); +} diff --git a/src/main/java/org/svnadmin/service/DefaultTreeFactory.java b/src/main/java/org/svnadmin/service/DefaultTreeFactory.java new file mode 100644 index 0000000..89dff22 --- /dev/null +++ b/src/main/java/org/svnadmin/service/DefaultTreeFactory.java @@ -0,0 +1,115 @@ +/** + * + */ +package org.svnadmin.service; + +import java.util.ArrayList; +import java.util.List; + +import org.svnadmin.common.util.SpringUtils; +import org.tree.entity.Tree; +import org.tree.service.TreeFactory; +import org.tree.service.TreeNodeService; + +//TODO 提供JdbcTreeFactory,把树配置数据保存在数据库。 + +/** + * 默认的树工厂类 + * @author Huiwu Yuan + * @since 3.0.2 + * + */ +public class DefaultTreeFactory implements TreeFactory { + + /** + * 单例 + */ + private static DefaultTreeFactory instance = new DefaultTreeFactory(); + + /** + * + */ + private DefaultTreeFactory(){ + + } + + /** + * @return the instance + */ + public static DefaultTreeFactory getInstance() { + return instance; + } + + public TreeNodeService findTreeNodeService(Tree tree) { + return SpringUtils.getBean(tree.getTreeNodeService()); + } + + public Tree find(String id) { + for(Tree tree:datas){ + if(tree.getId().equals(id)){ + //要给leaf设值 + if(tree.getId().equals(tree.getParentId())){ + tree.setLeaf(false); + }else{ + tree.setLeaf(findChildren(tree.getId()).size()==0); + } + return tree; + } + } + return null; + } + + public List findChildren(String parentId) { + List results = new ArrayList(); + for(Tree tree:datas){ + if(parentId.equals(tree.getParentId())){ + //要给leaf设值 + if(tree.getId().equals(tree.getParentId())){ + tree.setLeaf(false); + results.add(tree); + return results; + }else{ + tree.setLeaf(findChildren(tree.getId()).size()==0); + results.add(tree); + } + } + } + return results; + } + + + /** + * + */ + private static List datas = new ArrayList(); + static{ + /* + * rep + * |rep + * | |rep + * | |rep + * |rep + * | + * rep + * | + */ + datas.add(new Tree("rep","rep",RepTreeNodeService.BEAN_NAME)); + /* + * com + * |_dept + * | |_dept user + * | |_dept user + * |_dept + * |_com user + * |_com user + * + */ +// datas.add(new Tree("com",null)); + +// datas.add(new Tree("dept","com")); +// datas.add(new Tree("user","com")); + +// datas.add(new Tree("user","dept")); + } + +} diff --git a/src/main/java/org/svnadmin/service/DefaultTreeService.java b/src/main/java/org/svnadmin/service/DefaultTreeService.java new file mode 100644 index 0000000..000a90e --- /dev/null +++ b/src/main/java/org/svnadmin/service/DefaultTreeService.java @@ -0,0 +1,38 @@ +/** + * + */ +package org.svnadmin.service; + +import java.util.Map; + +import org.springframework.stereotype.Service; +import org.svnadmin.entity.Ajax; +import org.tree.service.AbstractTreeService; +import org.tree.service.TreeFactory; + +/** + * 默认的树服务层 + * @author Huiwu Yuan + * @since 3.0.2 + * + */ +@Service(DefaultTreeService.BEAN_NAME) +public class DefaultTreeService extends AbstractTreeService implements AjaxService{ + + /** + * Bean名称s + */ + public static final String BEAN_NAME="ajaxTreeService"; + + public TreeFactory getTreeFactory() { + return DefaultTreeFactory.getInstance(); + } + + public Ajax execute(Map parameters) { + Ajax result = new Ajax(); + result.setContentType(CONTENTTYPE_HTML); + result.setResult(this.getHTML(parameters)); + return result; + } + +} diff --git a/src/main/java/org/svnadmin/service/I18nService.java b/src/main/java/org/svnadmin/service/I18nService.java new file mode 100644 index 0000000..119d5d1 --- /dev/null +++ b/src/main/java/org/svnadmin/service/I18nService.java @@ -0,0 +1,131 @@ +/** + * + */ +package org.svnadmin.service; + +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; + +import org.apache.commons.lang.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.svnadmin.dao.I18nDao; +import org.svnadmin.entity.I18n; + +/** + * 多语言 + * + * @author Huiwu Yuan + * @since 3.0.2 + * + */ +@Service(I18nService.BEAN_NAME) +public class I18nService { + /** + * Bean名称 + */ + public static final String BEAN_NAME="i18nService"; + + /** + * DAO + */ + @Resource(name=I18nDao.BEAN_NAME) + protected I18nDao i18nDao; + + + /** + * @param lang 语言 + * @param id 键值 + * @return I18n + */ + public I18n getI18n(String lang, String id) { + return i18nDao.get(lang, id); + } + /** + * @param i18n 多语言 + */ + @Transactional(propagation=Propagation.REQUIRES_NEW) + public void insert(I18n i18n) { + i18nDao.insert(i18n); + } + /** + * 更新 + * @param i18n 多语言 + */ + @Transactional + public void update(I18n i18n){ + i18nDao.update(i18n); + } + /** + * 是否存在这种语言 + * @param lang 语言 + * @return true表示数据库存在这个语言,否则返回false + */ + public boolean existsLang(String lang) { + return i18nDao.existsLang(lang); + } + + /** + * @return 获取系统现有的语言 + */ + public List getLangs(){ + return this.i18nDao.getLangs(); + } + /** + * @param id 键值 + * @return 相同键值的语言列表 + */ + public Map getI18ns(String id) { + return i18nDao.getI18ns(id); + } + /** + * @return 键值列表 + */ + public List getIds() { + return this.i18nDao.getIds(); + } + /** + * 获取导出的脚步语句 + * @return 多语言列表 + */ + public String getInsertInto() { + List i18nList = this.i18nDao.getList(); + if(i18nList!=null && !i18nList.isEmpty()){ + StringBuffer content = new StringBuffer(); + for (I18n i18n : i18nList) { + content.append("insert into i18n (lang,id,lbl) values ("); + content.append("'").append(StringUtils.replace(i18n.getLang(), "'", "''")).append("',"); + content.append("'").append(StringUtils.replace(i18n.getId(), "'", "''")).append("',"); + content.append("'").append(StringUtils.replace(i18n.getLbl(), "'", "''")).append("'"); + content.append(");\n"); + } + return content.toString(); + } + return null; + } + /** + * @param list 保存的列表 + */ + @Transactional + public void save(List list) { + for (I18n i18n : list) { + this.save(i18n); + } + } + + /** + * 保存 + * @param i18n 语言 + */ + @Transactional + public void save(I18n i18n){ + if(this.getI18n(i18n.getLang(), i18n.getId())!=null){//已经存在 + this.update(i18n); + }else{ + this.insert(i18n); + } + } +} diff --git a/src/main/java/org/svnadmin/service/PjAuthService.java b/src/main/java/org/svnadmin/service/PjAuthService.java new file mode 100644 index 0000000..acc71fc --- /dev/null +++ b/src/main/java/org/svnadmin/service/PjAuthService.java @@ -0,0 +1,184 @@ +package org.svnadmin.service; + +import java.util.List; + +import javax.annotation.Resource; + +import org.apache.commons.lang.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.svnadmin.dao.PjAuthDao; +import org.svnadmin.dao.PjDao; +import org.svnadmin.entity.Pj; +import org.svnadmin.entity.PjAuth; + +/** + * 项目权限 + * + * @author Huiwu Yuan + * @since 1.0 + * + */ +@Service(PjAuthService.BEAN_NAME) +public class PjAuthService { + /** + * Bean名称 + */ + public static final String BEAN_NAME = "pjAuthService"; + + /** + * 项目权限DAO + */ + @Resource(name=PjAuthDao.BEAN_NAME) + protected PjAuthDao pjAuthDao; + + /** + * 项目DAO + */ + @Resource(name=PjDao.BEAN_NAME) + protected PjDao pjDao; + + /** + * SVN服务层 + */ + @Resource(name=SvnService.BEAN_NAME) + protected SvnService svnService; + + + /** + * @param pj + * 项目 + * @return 项目的资源列表 + */ + public List getResList(String pj) { + return pjAuthDao.getResList(pj); + } + + /** + * @param pj + * 项目 + * @param res 资源 + * @return 项目资源的权限列表 + */ + public List list(String pj,String res) { + if(StringUtils.isBlank(res)){ + return pjAuthDao.getList(pj); + } + return pjAuthDao.getList(pj,res); + } + + /** + * 删除项目 组资源的权限 + * + * @param pj + * 项目 + * @param gr + * 组 + * @param res + * 资源 + */ + @Transactional + public void deleteByGr(String pj, String gr,String res) { + pjAuthDao.deleteByGr(pj, gr, res); + svnService.exportConfig(pj); + } + + /** + * 删除项目用户资源的权限 + * + * @param pj + * 项目 + * @param usr + * 用户 + * @param res + * 资源 + */ + @Transactional + public void deleteByUsr(String pj, String usr,String res) { + pjAuthDao.deleteByUsr(pj, usr, res); + svnService.exportConfig(pj); + } + + /** + * 保存 + * @param pj 项目 + * @param res 资源 + * @param rw 可读可写 + * @param grs 组 + * @param usrs 用户 + */ + @Transactional + public void save(String pj,String res,String rw, String[] grs, String[] usrs) { + res = this.formatRes(pj, res);//如果资源没有[],自动加上 + //gr + if(grs!=null){ + for (String gr : grs) { + if(StringUtils.isBlank(gr)){ + continue; + } + PjAuth pjAuth = new PjAuth(); + pjAuth.setPj(pj); + pjAuth.setRes(res); + pjAuth.setRw(rw); + pjAuth.setGr(gr); + pjAuthDao.saveByGr(pjAuth); + } + } + //usr + if(usrs!=null){ + for (String usr : usrs) { + if(StringUtils.isBlank(usr)){ + continue; + } + PjAuth pjAuth = new PjAuth(); + pjAuth.setPj(pj); + pjAuth.setRes(res); + pjAuth.setRw(rw); + pjAuth.setUsr(usr); + pjAuthDao.saveByUsr(pjAuth); + } + } + //export + svnService.exportConfig(pj); + } + + /** + * 格式化资源.如果资源没有[],自动加上[relateRoot:/] + * @param pj 项目id + * @param res 资源 + * @return 格式化后的资源 + * @since 3.0.3 + */ + public String formatRes(String pj,String res){ + //如果资源没有[],自动加上 +// if(!res.startsWith("[") && !res.endsWith("]")){ + return this.formatRes(this.pjDao.get(pj), res); +// } +// return res; + } + /** + * 格式化资源.如果资源没有[],自动加上[relateRoot:/] + * @param pj 项目 + * @param res 资源 + * @return 格式化后的资源 + * @since 3.0.3 + */ + public String formatRes(Pj pj,String res){ + //去除[xxx:],重新加上[relateRoot:/],防止跨项目授权 + res = StringUtils.replaceEach(res, new String[]{"[","]"}, new String[]{"",""}); + if (res.indexOf(":")!=-1) { + res = StringUtils.substringAfter(res, ":"); + } + + //如果资源没有[],自动加上 + String relateRoot = PjService.getRelateRootPath(pj); + if(!res.startsWith("[") && !res.endsWith("]")){ + if(res.startsWith("/")){ + return "["+relateRoot+":"+res+"]"; + }else{ + return "["+relateRoot+":/"+res+"]"; + } + } + return res; + } +} diff --git a/src/main/java/org/svnadmin/service/PjGrService.java b/src/main/java/org/svnadmin/service/PjGrService.java new file mode 100644 index 0000000..70ab9ec --- /dev/null +++ b/src/main/java/org/svnadmin/service/PjGrService.java @@ -0,0 +1,100 @@ +package org.svnadmin.service; + +import java.util.List; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.svnadmin.dao.PjAuthDao; +import org.svnadmin.dao.PjGrDao; +import org.svnadmin.dao.PjGrUsrDao; +import org.svnadmin.entity.PjGr; + +/** + * 项目组服务层 + * + * @author Huiwu Yuan + * @since 1.0 + * + */ +@Service(PjGrService.BEAN_NAME) +public class PjGrService { + /** + * Bean名称 + */ + public static final String BEAN_NAME = "pjGrService"; + + /** + * 项目组DAO + */ + @Resource(name = PjGrDao.BEAN_NAME) + protected PjGrDao pjGrDao; + + /** + * 项目组用户DAO + */ + @Resource(name = PjGrUsrDao.BEAN_NAME) + protected PjGrUsrDao pjGrUsrDao; + + /** + * 项目权限DAO + */ + @Resource(name = PjAuthDao.BEAN_NAME) + protected PjAuthDao pjAuthDao; + + /** + * SVN服务层 + */ + @Resource(name = SvnService.BEAN_NAME) + protected SvnService svnService; + + /** + * @param pj + * 项目 + * @param gr + * 组 + * @return 项目组 + */ + public PjGr get(String pj, String gr) { + return pjGrDao.get(pj, gr); + } + + /** + * @param pj + * 项目 + * @return 项目组列表 + */ + public List list(String pj) { + return pjGrDao.getList(pj); + } + + /** + * 删除项目组(同时删除项目组的权限,项目组的用户) + * + * @param pj + * 项目 + * @param gr + * 组 + */ + @Transactional + public void delete(String pj, String gr) { + pjAuthDao.deletePjGr(pj, gr); + pjGrUsrDao.deletePjGr(pj, gr); + pjGrDao.delete(pj, gr); + + svnService.exportConfig(pj); + } + + /** + * 保存 + * + * @param pjGr + * 项目组 + */ + @Transactional + public void save(PjGr pjGr) { + pjGrDao.save(pjGr); + svnService.exportConfig(pjGr.getPj()); + } +} diff --git a/src/main/java/org/svnadmin/service/PjGrUsrService.java b/src/main/java/org/svnadmin/service/PjGrUsrService.java new file mode 100644 index 0000000..74d607e --- /dev/null +++ b/src/main/java/org/svnadmin/service/PjGrUsrService.java @@ -0,0 +1,130 @@ +package org.svnadmin.service; + +import java.util.List; + +import javax.annotation.Resource; + +import org.apache.commons.lang.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.svnadmin.constant.Constants; +import org.svnadmin.dao.PjGrUsrDao; +import org.svnadmin.entity.PjGrUsr; +import org.svnadmin.entity.Usr; + +/** + * 项目组用户服务层 + * + * @author Huiwu Yuan + * @since 1.0 + * + */ +@Service(PjGrUsrService.BEAN_NAME) +public class PjGrUsrService { + /** + * Bean名称 + */ + public static final String BEAN_NAME = "pjGrUsrService"; + /** + * 项目组用户DAO + */ + @Resource(name = PjGrUsrDao.BEAN_NAME) + protected PjGrUsrDao pjGrUsrDao; + + /** + * SVN服务层 + */ + @Resource(name = SvnService.BEAN_NAME) + protected SvnService svnService; + + /** + * @param pj + * 项目 + * @param gr + * 组 + * @param usr + * 用户 + * @return 组用户 + */ + public PjGrUsr get(String pj, String gr, String usr) { + return pjGrUsrDao.get(pj, gr, usr); + } + + /** + * @param pj + * 项目 + * @param gr + * 组 + * @return 组用户列表 + */ + public List list(String pj, String gr) { + return pjGrUsrDao.getList(pj, gr); + } + + /** + * 保存 + * + * @param pj + * 项目 + * @param gr + * 组 + * @param usrs + * 用户 + */ + @Transactional + public void save(String pj, String gr, String[] usrs) { + + if (usrs == null || usrs.length == 0) { + return; + } + + for (String usr : usrs) { + if (StringUtils.isBlank(usr)) { + continue; + } + PjGrUsr pjGrUsr = new PjGrUsr(); + pjGrUsr.setPj(pj); + pjGrUsr.setGr(gr); + pjGrUsr.setUsr(usr); + pjGrUsrDao.save(pjGrUsr); + } + // export + svnService.exportConfig(pj); + } + + /** + * 删除 + * + * @param pj + * 项目 + * @param gr + * 组 + * @param usr + * 用户 + */ + @Transactional + public void delete(String pj, String gr, String usr) { + pjGrUsrDao.delete(pj, gr, usr); + svnService.exportConfig(pj); + } + + /** + * 是否有项目管理员的权限 + * @param usr 用户 + * @param pj 项目 + * @return 有权限返回true,否则返回false + */ + public boolean hasManagerRight(Usr usr,String pj){ + if (pj == null) { + return false; + } + // TODO delete me 为了兼容3.0版本 see: Issue 4 + String gr = pj + "_" + Constants.GROUP_MANAGER; + if (this.get(pj, gr, usr.getUsr()) != null) { + return true; + } + // 3.0.1版本以后 + gr = Constants.GROUP_MANAGER; + return this.get(pj, gr, usr.getUsr()) != null; + } +} diff --git a/src/main/java/org/svnadmin/service/PjService.java b/src/main/java/org/svnadmin/service/PjService.java new file mode 100644 index 0000000..b3094a8 --- /dev/null +++ b/src/main/java/org/svnadmin/service/PjService.java @@ -0,0 +1,214 @@ +package org.svnadmin.service; + +import java.io.File; +import java.util.List; + +import javax.annotation.Resource; + +import org.apache.commons.lang.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.svnadmin.constant.Constants; +import org.svnadmin.dao.PjAuthDao; +import org.svnadmin.dao.PjDao; +import org.svnadmin.dao.PjGrDao; +import org.svnadmin.dao.PjGrUsrDao; +import org.svnadmin.dao.PjUsrDao; +import org.svnadmin.entity.Pj; +import org.svnadmin.entity.PjAuth; +import org.svnadmin.entity.PjGr; +import org.svnadmin.util.I18N; + +/** + * 项目服务层 + * + * @author Huiwu Yuan + * @since 1.0 + * + */ +@Service(PjService.BEAN_NAME) +public class PjService { + /** + * Bean名称 + */ + public static final String BEAN_NAME = "pjService"; + + /** + * 项目DAO + */ + @Resource(name = PjDao.BEAN_NAME) + protected PjDao pjDao; + + /** + * 项目用户DAO + */ + @Resource(name = PjUsrDao.BEAN_NAME) + protected PjUsrDao pjUsrDao; + + /** + * 项目组DAO + */ + @Resource(name = PjGrDao.BEAN_NAME) + protected PjGrDao pjGrDao; + + /** + * 项目组用户DAO + */ + @Resource(name = PjGrUsrDao.BEAN_NAME) + protected PjGrUsrDao pjGrUsrDao; + + /** + * 项目权限DAO + */ + @Resource(name = PjAuthDao.BEAN_NAME) + protected PjAuthDao pjAuthDao; + + /** + * SVN服务层 + */ + @Resource(name = SvnService.BEAN_NAME) + protected SvnService svnService; + /** + * 权限服务层 + */ + @Resource(name = PjAuthService.BEAN_NAME) + protected PjAuthService pjAuthService; + + /** + * @param pj + * 项目 + * @return 项目 + */ + public Pj get(String pj) { + return pjDao.get(pj); + } + + /** + * @return 项目列表 + */ + public List list() { + return pjDao.getList(); + } + + /** + * @param usr + * 用户 + * @return 用户有权限的项目列表(用户是否是这个项目的管理员) + */ + public List list(String usr) { + return pjDao.getList(usr); + } + + /** + * 删除(同时删除项目权限,项目组用户,项目组,项目用户) + * + * @param pj + * 项目 + */ + @Transactional + public void delete(String pj) { + pjAuthDao.deletePj(pj); + pjGrUsrDao.deletePj(pj); + pjGrDao.deletePj(pj); + pjUsrDao.deletePj(pj); + + svnService.exportConfig(pj); + + pjDao.delete(pj); + } + + /** + * 保存。
+ * 数据库里已经存在相同的路径或url的项目,不可以保存。
+ * 如果仓库不存在,自动创建。
+ * 如果是增加项目,自动创建默认3个组。 + * + * @param pj + * 项目 + */ + @Transactional + public void save(Pj pj) { + // 路径 把\替换为/ + if (StringUtils.isNotBlank(pj.getPath())) { + pj.setPath(StringUtils.replace(pj.getPath(), "\\", "/")); + } + // url 把\替换为/ + if (StringUtils.isNotBlank(pj.getUrl())) { + pj.setUrl(StringUtils.replace(pj.getUrl(), "\\", "/")); + } + + // 是否可以增加项目 + boolean insert = pjDao.get(pj.getPj()) == null; + if (insert) { + // 数据库里已经存在相同的路径或url的项目 + if (this.pjDao.getCount(pj.getPath(), pj.getUrl()) > 0) { + throw new RuntimeException(I18N.getLbl("pj.save.error.existPathOrUrl", "数据库里已经存在相同的路径或url的仓库项目,请检查路径或url")); + } + } else { + // 数据库里已经存在相同的路径或url的项目 + if (this.pjDao.getCount(pj.getPath(), pj.getUrl()) > 1) { + throw new RuntimeException(I18N.getLbl("pj.save.error.existMutilPathOrUrl","数据库里已经存在多个相同的路径或url的仓库项目,请检查路径或url")); + } + } + // 创建仓库 + File respository = new File(pj.getPath()); + if (!respository.exists() || !respository.isDirectory()) {// 不存在仓库 + RepositoryService.createLocalRepository(respository); + } + if (insert) { + // 增加默认的组 + this.pjDao.insert(pj); + for (String gr : Constants.GROUPS) { + PjGr pjGr = new PjGr(); + pjGr.setPj(pj.getPj()); + pjGr.setGr(gr); + pjGr.setDes(gr); + pjGrDao.save(pjGr); + } + // 增加默认的权限 @see Issue 29 + PjAuth pjAuth = new PjAuth(); + pjAuth.setPj(pj.getPj()); + pjAuth.setRes(this.pjAuthService.formatRes(pj, "/")); + pjAuth.setRw("rw"); + pjAuth.setGr(Constants.GROUP_MANAGER); + pjAuthDao.saveByGr(pjAuth); + + } else { + this.pjDao.update(pj); + } + svnService.exportConfig(pj.getPj()); + } + + /** + * 获取项目的相对根路径.例如项目的path=e:/svn/projar,则返回projar。如果path为空,则返回项目ID + * @param pj 项目id + * @return 项目的相对根路径 + * @since 3.0.3 + */ + public String getRelateRootPath(String pj){ + Pj p = this.get(pj); + if(p == null || StringUtils.isBlank(p.getPath())){ + return pj; + } + return getRelateRootPath(pj); + } + /** + * 获取项目的相对根路径.例如项目的path=e:/svn/projar,则返回projar。如果path为空,则返回项目ID + * @param pj 项目 + * @return 项目的相对根路径 + * @since 3.0.3 + */ + public static String getRelateRootPath(Pj pj){ + String path = pj.getPath(); + if(StringUtils.isBlank(path)){ + return pj.getPj(); + } + path = StringUtils.replace(path, "\\", "/"); + + while(path.endsWith("/")){ + path = path.substring(0, path.length()-1); + } + + return StringUtils.substringAfterLast(path, "/"); + } +} diff --git a/src/main/java/org/svnadmin/service/PjUsrService.java b/src/main/java/org/svnadmin/service/PjUsrService.java new file mode 100644 index 0000000..590d7f7 --- /dev/null +++ b/src/main/java/org/svnadmin/service/PjUsrService.java @@ -0,0 +1,88 @@ +package org.svnadmin.service; + +import java.util.List; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.svnadmin.dao.PjUsrDao; +import org.svnadmin.entity.PjUsr; + +/** + * 项目用户服务层(采用svn或http单库方式是,用户可以对每个项目设置不用的密码) + * + * @author Huiwu Yuan + * @since 1.0 + * + */ +@Service(PjUsrService.BEAN_NAME) +public class PjUsrService { + /** + * Bean名称 + */ + public static final String BEAN_NAME = "pjUsrService"; + + /** + * 项目用户DAO + */ + @Resource(name = PjUsrDao.BEAN_NAME) + protected PjUsrDao pjUsrDao; + + /** + * SVN服务层 + */ + @Resource(name = SvnService.BEAN_NAME) + protected SvnService svnService; + + /** + * @param pj + * 项目 + * @param usr + * 用户 + * @return 项目用户 + */ + public PjUsr get(String pj, String usr) { + return pjUsrDao.get(pj, usr); + } + + /** + * @param pj + * 项目 + * @return 项目的用户列表 + */ + public List list(String pj) { + return pjUsrDao.getList(pj); + } + + /** + * 删除 + * + * @param pj + * 项目 + * @param usr + * 用户 + */ + @Transactional + public void delete(String pj, String usr) { + pjUsrDao.delete(pj, usr); + + svnService.exportConfig(pj); + } + + /** + * 保存 + * + * @param pjUsr + * 项目用户 + */ + @Transactional + public void save(PjUsr pjUsr) { + if (this.pjUsrDao.get(pjUsr.getPj(), pjUsr.getUsr()) == null) { + this.pjUsrDao.insert(pjUsr); + } else { + this.pjUsrDao.update(pjUsr); + } + svnService.exportConfig(pjUsr.getPj()); + } +} diff --git a/src/main/java/org/svnadmin/service/RepTreeNodeService.java b/src/main/java/org/svnadmin/service/RepTreeNodeService.java new file mode 100644 index 0000000..77a111f --- /dev/null +++ b/src/main/java/org/svnadmin/service/RepTreeNodeService.java @@ -0,0 +1,100 @@ +/** + * + */ +package org.svnadmin.service; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Service; +import org.tmatesoft.svn.core.SVNDirEntry; +import org.tmatesoft.svn.core.SVNNodeKind; +import org.tree.entity.Tree; +import org.tree.entity.TreeNode; +import org.tree.service.AbstractTreeNodeService; + +/** + * 仓库目录结构树节点服务层 + * @author Huiwu Yuan + * @since 3.0.2 + * + */ +@Service(RepTreeNodeService.BEAN_NAME) +public class RepTreeNodeService extends AbstractTreeNodeService { + + private static final String AND = "$AND$"; + /** + * Bean名称 + */ + public static final String BEAN_NAME="repTreeNodeService"; + /** + * 日志 + */ + private final Logger LOG = Logger.getLogger(RepTreeNodeService.class); + + + /** + * 仓库服务层 + */ + @Resource(name=RepositoryService.BEAN_NAME) + RepositoryService repositoryService; + + @Override + protected List getTreeNodes(Tree parent, + Map parameters) { + List results = new ArrayList(); + + String pj = (String) parameters.get("pj"); + String path = (String) parameters.get("path"); + path = StringUtils.replace(path, AND, "&"); + if(StringUtils.isBlank(pj)){ + LOG.warn("pj id is blank "); + return null; + } + try{ + Collection entries = this.repositoryService.getDir(pj, path); + if(entries == null){ + return null; + } +// Collection entries = repository.getDir("/trunk", SVNRevision.HEAD.getNumber(), properties, (Collection) null); + for (SVNDirEntry svnDirEntry : entries) { +// System.out.println(svnDirEntry); +// System.out.println(svnDirEntry.getName()//文件夹或文件名 +// +","+svnDirEntry.getKind()//类型,参考SVNNodeKind.FILE,SVNNodeKind.DIR +// +","+svnDirEntry.getRevision()//版本 +// +","+svnDirEntry.getAuthor()//作者 +// +","+svnDirEntry.getSize()//如果kind是SVNNodeKind.FILE时返回文件的大小 +// +","+svnDirEntry.getDate());//日期 + TreeNode treeNode = new TreeNode(svnDirEntry.getName()); + treeNode.setLeaf(SVNNodeKind.FILE.equals(svnDirEntry.getKind()));//叶子? + treeNode.addParamete("pj", pj); + if(path.endsWith("/")){ + treeNode.addParamete("path", path+StringUtils.replace(svnDirEntry.getName(), "&", AND)); + }else{ + treeNode.addParamete("path", path+"/"+StringUtils.replace(svnDirEntry.getName(), "&", AND)); + } + results.add(treeNode); + } + Collections.sort(results);// 排序 + } catch (Exception e) { + LOG.error(e.getMessage()); + e.printStackTrace(); + + results.clear(); + TreeNode errorNode = new TreeNode(e.getMessage()); + errorNode.setLeaf(true); + results.add(errorNode); + return results; + } + + return results; + } + +} diff --git a/src/main/java/org/svnadmin/service/RepositoryService.java b/src/main/java/org/svnadmin/service/RepositoryService.java new file mode 100644 index 0000000..fdc7184 --- /dev/null +++ b/src/main/java/org/svnadmin/service/RepositoryService.java @@ -0,0 +1,233 @@ +/** + * + */ +package org.svnadmin.service; + +import java.io.File; +import java.util.Collection; + +import javax.annotation.Resource; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Service; +import org.svnadmin.constant.Constants; +import org.svnadmin.dao.PjDao; +import org.svnadmin.dao.PjUsrDao; +import org.svnadmin.entity.Pj; +import org.svnadmin.entity.PjUsr; +import org.svnadmin.entity.Usr; +import org.svnadmin.util.EncryptUtil; +import org.svnadmin.util.I18N; +import org.svnadmin.util.UsrProvider; +import org.tmatesoft.svn.core.SVNAuthenticationException; +import org.tmatesoft.svn.core.SVNDirEntry; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNProperties; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; +import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory; +import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory; +import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl; +import org.tmatesoft.svn.core.io.SVNRepository; +import org.tmatesoft.svn.core.io.SVNRepositoryFactory; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc.SVNWCUtil; + +/** + * 仓库服务层 + * @author Huiwu Yuan + * @since 3.0.2 + * + */ +@Service(RepositoryService.BEAN_NAME) +public class RepositoryService{ + + /** + * Bean名称 + */ + public static final String BEAN_NAME="repositoryService"; + /** + * 日志 + */ + private final Logger LOG = Logger.getLogger(RepositoryService.class); + + + /** + * 项目DAO + */ + @Resource(name=PjDao.BEAN_NAME) + PjDao pjDao; + /** + * 项目用户DAO + */ + @Resource(name=PjUsrDao.BEAN_NAME) + PjUsrDao pjUsrDao; + + /** + * 获取svn仓库 + * @param pjId 项目ID + * @return svn仓库 + * @throws SVNException svn异常,例如没有权限等 + */ + public SVNRepository getRepository(String pjId) throws SVNException{ + Pj pj = pjDao.get(pjId); + if(pj == null){ + LOG.warn("Not found project: "+pjId); + return null; + } + return this.getRepository(pj); + } + + /** + * 从项目的url中获取svn的url + * @param url 项目url + * @return svn url + */ + public static String parseURL(String url){ + if(StringUtils.isBlank(url)){ + return null; + } + String result = url.trim();//去空格 + result = StringUtils.replace(result, "\t", " "); + result = StringUtils.replace(result, "\r", " "); + result = StringUtils.replace(result, "\n", " "); + result = StringUtils.replace(result, "\b", " "); + result = StringUtils.replace(result, "<", " ");//eg.
+ result = StringUtils.replace(result, "(", " ");//eg. () + + result = result.trim(); + int blank = result.indexOf(" "); + if(blank != -1){ + result = result.substring(0, blank); + } + + return result; + } + + /** + * 获取svn仓库 + * @param pj 项目 + * @return svn仓库 + * @throws SVNException svn异常,例如没有权限等 + */ + public SVNRepository getRepository(Pj pj) throws SVNException{ + + Usr usr = UsrProvider.getCurrentUsr(); + + String svnUrl = parseURL(pj.getUrl()); + if(StringUtils.isBlank(svnUrl)){ + throw new RuntimeException(I18N.getLbl("pj.error.url", "URL不可以为空")); + } + String svnUserName = usr.getUsr(); + String svnPassword = usr.getPsw(); + if(!Constants.HTTP_MUTIL.equals(pj.getType())){ + //pj_usr覆盖用户的密码 + PjUsr pjUsr = pjUsrDao.get(pj.getPj(), svnUserName); + if(pjUsr != null){ + svnPassword = pjUsr.getPsw(); + } + } + svnPassword = EncryptUtil.decrypt(svnPassword);//解密 + + SVNRepository repository = SVNRepositoryFactory.create(SVNURL.parseURIDecoded(svnUrl)); + ISVNAuthenticationManager authManager = + SVNWCUtil.createDefaultAuthenticationManager(svnUserName, svnPassword); + repository.setAuthenticationManager(authManager); + + return repository; + } + + /** + * 返回项目仓库的根 + * @param pj 项目 + * @return 仓库根 + */ + public String getRepositoryRoot(Pj pj){ + SVNRepository repository = null; + try{ + repository = this.getRepository(pj); + return repository.getRepositoryRoot(true).toString(); + }catch(SVNAuthenticationException e){ + LOG.error(e.getMessage()); + return null; + } catch (SVNException e) { + LOG.error(e.getMessage()); + e.printStackTrace(); + return null; + }finally{ + if(repository != null){ + repository.closeSession(); + } + } + } + + + /** + * 获取项目指定路径的svn仓库文件系统 + * @param pj 项目 + * @param path 相对仓库根目录的路径 + * @return 目录或文件系统 + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Collection getDir(String pj,String path){ + if(StringUtils.isBlank(path)){ + path = "/";//root + } + if(!path.startsWith("/")){ + path = "/"+path; + } + SVNRepository repository = null; + try { + repository = this.getRepository(pj); + SVNProperties properties = new SVNProperties(); + return repository.getDir(path, SVNRevision.HEAD.getNumber(), properties, (Collection) null); + }catch(SVNAuthenticationException e){ + e.printStackTrace(); + throw new RuntimeException(I18N.getLbl("svn.auth.error", "认证失败")); + }catch (SVNException e) { + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + }finally{ + if(repository!=null){ + repository.closeSession(); + } + } + } + + /** + * Creates a local blank FSFS-type repository. + * A call to this routine is equivalent to + * createLocalRepository(path, null, enableRevisionProperties, force). + * + * @param respository a repository root location + * @return a local URL (file:///) of a newly + * created repository + */ + public static SVNURL createLocalRepository(File respository){ + try { + return SVNRepositoryFactory.createLocalRepository(respository, true, + false); + } catch (SVNException e) { + throw new RuntimeException(I18N.getLbl("pj.save.error.createRepository","创建仓库失败.{0}",new Object[]{respository.getAbsolutePath()}) + + " : "+ e.getMessage()); + } + } + + static { + /* + * For using over http:// and https:// + */ + DAVRepositoryFactory.setup(); + /* + * For using over svn:// and svn+xxx:// + */ + SVNRepositoryFactoryImpl.setup(); + + /* + * For using over file:/// + */ + FSRepositoryFactory.setup(); + } + +} diff --git a/src/main/java/org/svnadmin/service/SvnService.java b/src/main/java/org/svnadmin/service/SvnService.java new file mode 100644 index 0000000..98184be --- /dev/null +++ b/src/main/java/org/svnadmin/service/SvnService.java @@ -0,0 +1,620 @@ +package org.svnadmin.service; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Service; +import org.svnadmin.constant.Constants; +import org.svnadmin.dao.PjAuthDao; +import org.svnadmin.dao.PjDao; +import org.svnadmin.dao.PjGrDao; +import org.svnadmin.dao.PjGrUsrDao; +import org.svnadmin.dao.UsrDao; +import org.svnadmin.entity.Pj; +import org.svnadmin.entity.PjAuth; +import org.svnadmin.entity.PjGrUsr; +import org.svnadmin.entity.Usr; +import org.svnadmin.util.EncryptUtil; +import org.svnadmin.util.I18N; + +/** + * 导出svn配置信息服务层 + * + * @author Huiwu Yuan + * @since 1.0 + * + */ +@Service(SvnService.BEAN_NAME) +public class SvnService { + /** + * Bean名称 + */ + public static final String BEAN_NAME = "svnService"; + + /** + * 分隔符 + */ + private static final String SEP = System.getProperty("line.separator"); + /** + * 日志 + */ + private final Logger LOG = Logger.getLogger(this.getClass()); + + /** + * 项目DAO + */ + @Resource(name = PjDao.BEAN_NAME) + protected PjDao pjDao; + + /** + * 用户DAO + */ + @Resource(name = UsrDao.BEAN_NAME) + protected UsrDao usrDao; + + /** + * 项目组DAO + */ + @Resource(name = PjGrDao.BEAN_NAME) + protected PjGrDao pjGrDao; + + /** + * 项目组用户DAO + */ + @Resource(name = PjGrUsrDao.BEAN_NAME) + protected PjGrUsrDao pjGrUsrDao; + + /** + * 项目权限DAO + */ + @Resource(name = PjAuthDao.BEAN_NAME) + protected PjAuthDao pjAuthDao; + + /** + * 导出到配置文件 + * + * @param pj + * 项目id + */ + public synchronized void exportConfig(String pj) { + this.exportConfig(this.pjDao.get(pj)); + } + + /** + * 导出到配置文件 + * + * @param pj + * 项目 + */ + public synchronized void exportConfig(Pj pj) { + if (pj == null) { + return; + } + File parent = new File(pj.getPath()); + if (!parent.exists() || !parent.isDirectory()) { + throw new RuntimeException(I18N.getLbl("svn.notFoundResp", "找不到仓库 路径{0}",new Object[]{pj.getPath()})); + } + + if (Constants.HTTP.equalsIgnoreCase(pj.getType())) {// HTTP(单库) SVNPath + this.exportHTTP(pj); + } else if (Constants.HTTP_MUTIL.equalsIgnoreCase(pj.getType())) {// HTTP(多库) + // SVNParentPath + File root = new File(pj.getPath()).getParentFile(); + this.exportHTTPMutil(root); + } else if (Constants.SVN.equalsIgnoreCase(pj.getType())) {// SVN + this.exportSVN(pj); + } + + } + + /** + * 导出svn协议的配置信息 + * + * @param pj + * 项目 + */ + private void exportSVN(Pj pj) { + // 项目的用户 + List usrList = this.usrDao.getList(pj.getPj()); + // 项目的用户组 + Map> pjGrUsrMap = this.getPjGrUsrs(pj.getPj()); + // 项目的权限 + Map> pjAuthMap = this.getPjAuths(pj.getPj()); + + this.exportSvnConf(pj); + this.exportPasswdSVN(pj, usrList); + this.exportAuthz(pj, pjGrUsrMap, pjAuthMap); + } + + /** + * 导出http(单库)的配置信息 + * + * @param pj + * 项目 + */ + private void exportHTTP(Pj pj) { + // 项目的用户 + List usrList = this.usrDao.getList(pj.getPj()); + // 项目的用户组 + Map> pjGrUsrMap = this.getPjGrUsrs(pj.getPj()); + // 项目的权限 + Map> pjAuthMap = this.getPjAuths(pj.getPj()); + + this.exportSVNPathConf(pj); + this.exportPasswdHTTP(pj, usrList); + this.exportAuthz(pj, pjGrUsrMap, pjAuthMap); + } + + /** + * 导出http(多库)的配置信息 + * + * @param root + * svn root + */ + private void exportHTTPMutil(File root) { + String svnRoot = StringUtils.replace(root.getAbsolutePath(), "\\", "/"); + if (!svnRoot.endsWith("/")) { + svnRoot += "/"; + } + // 和这个项目在同一个父目录的所有项目的用户 + List usrList = this.usrDao.getListByRootPath(svnRoot); + // 和这个项目在同一个父目录的所有项目的用户组 + Map> pjGrUsrMap = this + .getPjGrUsrsByRootPath(svnRoot); + // 和这个项目在同一个父目录的所有项目的权限 + Map> pjAuthMap = this + .getPjAuthsByRootPath(svnRoot); + + this.exportSVNParentPathConf(root); + + this.exportPasswdHTTPMutil(root, usrList); + + this.exportAuthzHTTPMutil(root, pjGrUsrMap, pjAuthMap); + } + + /** + * 获取有相同svn root的项目的权限列表 + * + * @param rootPath + * svn root + * @return 有相同svn root的项目的权限列表 + */ + private Map> getPjAuthsByRootPath(String rootPath) { + Map> results = new LinkedHashMap>();// > + List pjAuthList = this.pjAuthDao.getListByRootPath(rootPath); + // 格式化返回数据 + for (PjAuth pjAuth : pjAuthList) { + List authList = results.get(pjAuth.getRes()); + if (authList == null) { + authList = new ArrayList(); + results.put(pjAuth.getRes(), authList); + } + authList.add(pjAuth); + + } + return results; + } + + /** + * 获取项目的权限列表 + * + * @param pj + * 项目 + * @return 项目的权限列表 + */ + private Map> getPjAuths(String pj) { + Map> results = new LinkedHashMap>();// > + List pjAuthList = this.pjAuthDao.getList(pj); + // 格式化返回数据 + for (PjAuth pjAuth : pjAuthList) { + List authList = results.get(pjAuth.getRes()); + if (authList == null) { + authList = new ArrayList(); + results.put(pjAuth.getRes(), authList); + } + authList.add(pjAuth); + + } + return results; + } + + /** + * 获取项目的组列表 + * + * @param pj + * 项目 + * @return 项目的组列表 + */ + private Map> getPjGrUsrs(String pj) { + Map> results = new LinkedHashMap>();// > + + List pjGrUsrs = this.pjGrUsrDao.getList(pj); + + // 格式化返回数据 + for (PjGrUsr pjGrUsr : pjGrUsrs) { + List grUsrList = results.get(pjGrUsr.getGr()); + if (grUsrList == null) { + grUsrList = new ArrayList(); + results.put(pjGrUsr.getGr(), grUsrList); + } + grUsrList.add(pjGrUsr); + } + + return results; + } + + /** + * 获取有相同svn root的项目的权限列表 + * + * @param rootPath + * svn root + * @return 有相同svn root的项目的权限列表 + */ + private Map> getPjGrUsrsByRootPath(String rootPath) { + + Map> results = new LinkedHashMap>();// > + + List pjGrUsrs = this.pjGrUsrDao.getListByRootPath(rootPath); + + // 格式化返回数据 + for (PjGrUsr pjGrUsr : pjGrUsrs) { + String key = pjGrUsr.getPj() + "_" + pjGrUsr.getGr(); + List grUsrList = results.get(key);// 项目ID_组ID see: Issue 4 + if (grUsrList == null) { + grUsrList = new ArrayList(); + results.put(key, grUsrList); + } + grUsrList.add(pjGrUsr); + } + + return results; + + } + + /** + * 输出http多库方式的密码文件 + * + * @param root + * svn root + * @param usrList + * 所有用户列表 + */ + private void exportPasswdHTTPMutil(File root, List usrList) { + File outFile = new File(root, "passwd.http"); + StringBuffer contents = new StringBuffer(); + + for (Usr usr : usrList) { + // 采用SHA加密 + // http://httpd.apache.org/docs/2.2/misc/password_encryptions.html + String shaPsw = "{SHA}" + + EncryptUtil + .encriptSHA1(EncryptUtil.decrypt(usr.getPsw())); + contents.append(usr.getUsr()).append(":").append(shaPsw) + .append(SEP); + } + this.write(outFile, contents.toString()); + } + + /** + * 输出http单库方式的密码文件 + * + * @param pj + * 项目 + * @param usrList + * 项目用户列表 + */ + private void exportPasswdHTTP(Pj pj, List usrList) { + File outFile = new File(pj.getPath(), "/conf/passwd.http"); + StringBuffer contents = new StringBuffer(); + + for (Usr usr : usrList) { + // 采用SHA加密 + // http://httpd.apache.org/docs/2.2/misc/password_encryptions.html + String shaPsw = "{SHA}" + + EncryptUtil + .encriptSHA1(EncryptUtil.decrypt(usr.getPsw())); + contents.append(usr.getUsr()).append(":").append(shaPsw) + .append(SEP); + } + this.write(outFile, contents.toString()); + } + + /** + * 输出svn方式的密码文件 + * + * @param pj + * 项目 + * @param usrList + * 项目用户列表 + */ + private void exportPasswdSVN(Pj pj, List usrList) { + File outFile = new File(pj.getPath(), "/conf/passwd"); + StringBuffer contents = new StringBuffer(); + contents.append("[users]").append(SEP); + + for (Usr usr : usrList) { + contents.append(usr.getUsr()).append("=") + .append(EncryptUtil.decrypt(usr.getPsw())).append(SEP);// 解密 + } + this.write(outFile, contents.toString()); + } + + /** + * 输出http多库方式的权限文件 + * + * @param root + * svn root + * @param pjGrUsrMap + * 所有的项目组用户列表 + * @param resMap + * 所有的权限列表 + */ + private void exportAuthzHTTPMutil(File root, + Map> pjGrUsrMap, + Map> resMap) { + if (root == null) { + return; + } + File outFile = new File(root, "authz"); + StringBuffer contents = new StringBuffer(); + contents.append("[aliases]").append(SEP); + contents.append("[groups]").append(SEP); + + for (Iterator grIterator = pjGrUsrMap.keySet().iterator(); grIterator + .hasNext();) { + String gr = grIterator.next();// 项目ID_组ID see: Issue 4 + contents.append(gr).append("="); + List pjGrUsrList = pjGrUsrMap.get(gr); + for (int i = 0; i < pjGrUsrList.size(); i++) { + PjGrUsr pjGrUsr = pjGrUsrList.get(i); + if (pjGrUsr.getUsr() == null) { + continue; + } + if (i != 0) { + contents.append(","); + } + contents.append(pjGrUsr.getUsr()); + } + contents.append(SEP); + } + + contents.append(SEP); + + for (Iterator resIterator = resMap.keySet().iterator(); resIterator + .hasNext();) { + String res = resIterator.next(); + contents.append(res).append(SEP); + for (PjAuth pjAuth : resMap.get(res)) { + if (StringUtils.isNotBlank(pjAuth.getGr())) { + // 项目ID_组ID see: Issue 4 + contents.append("@") + .append(pjAuth.getPj() + "_" + pjAuth.getGr()) + .append("=").append(pjAuth.getRw()).append(SEP); + } else if (StringUtils.isNotBlank(pjAuth.getUsr())) { + contents.append(pjAuth.getUsr()).append("=") + .append(pjAuth.getRw()).append(SEP); + } + } + contents.append(SEP); + } + + this.write(outFile, contents.toString()); + } + + /** + * 输出权限配置文件 + * + * @param pj + * 项目 + * @param pjGrUsrMap + * 项目的组列表 + * @param resMap + * 项目的权限列表 + */ + private void exportAuthz(Pj pj, Map> pjGrUsrMap, + Map> resMap) { + if (pj == null || StringUtils.isBlank(pj.getPj())) { + return; + } + /* + * if(pjGrList == null || pjGrList.size() == 0){ return; } if(pjAuthMap + * == null || pjAuthMap.size() == 0){ return; } + */ + File outFile = new File(pj.getPath(), "/conf/authz"); + StringBuffer contents = new StringBuffer(); + contents.append("[aliases]").append(SEP); + contents.append("[groups]").append(SEP); + + for (Iterator grIterator = pjGrUsrMap.keySet().iterator(); grIterator + .hasNext();) { + String gr = grIterator.next(); + contents.append(gr).append("="); + List pjGrUsrList = pjGrUsrMap.get(gr); + for (int i = 0; i < pjGrUsrList.size(); i++) { + PjGrUsr pjGrUsr = pjGrUsrList.get(i); + if (pjGrUsr.getUsr() == null) { + continue; + } + if (i != 0) { + contents.append(","); + } + contents.append(pjGrUsr.getUsr()); + } + contents.append(SEP); + } + + contents.append(SEP); + + for (Iterator resIterator = resMap.keySet().iterator(); resIterator + .hasNext();) { + String res = resIterator.next(); + contents.append(res).append(SEP); + for (PjAuth pjAuth : resMap.get(res)) { + if (StringUtils.isNotBlank(pjAuth.getGr())) { + contents.append("@").append(pjAuth.getGr()).append("=") + .append(pjAuth.getRw()).append(SEP); + } else if (StringUtils.isNotBlank(pjAuth.getUsr())) { + contents.append(pjAuth.getUsr()).append("=") + .append(pjAuth.getRw()).append(SEP); + } + } + contents.append(SEP); + } + + this.write(outFile, contents.toString()); + } + + /** + * 输出svn方式的svnserve.conf + * + * @param pj + * 项目 + */ + private void exportSvnConf(Pj pj) { + if (pj == null || StringUtils.isBlank(pj.getPj())) { + return; + } + File outFile = new File(pj.getPath(), "/conf/svnserve.conf"); + + StringBuffer contents = new StringBuffer(); + contents.append("[general]").append(SEP); + contents.append("anon-access = none").append(SEP); + contents.append("auth-access = write").append(SEP); + contents.append("password-db = passwd").append(SEP); + contents.append("authz-db = authz").append(SEP); + contents.append("[sasl]").append(SEP); + this.write(outFile, contents.toString()); + + } + + /** + * 输出http单库方式的httpd.conf文件 + * + * @param pj + * 项目 + */ + private void exportSVNPathConf(Pj pj) { + if (pj == null || StringUtils.isBlank(pj.getPj())) { + return; + } + File outFile = new File(pj.getPath(), "/conf/httpd.conf"); + StringBuffer contents = new StringBuffer(); + contents.append("#Include ").append(pj.getPath()) + .append("/conf/httpd.conf").append(SEP); + + String location = pj.getPj(); + // 例如 http://192.168.1.100/svn/projar/trunk + if (StringUtils.isNotBlank(pj.getUrl()) + && pj.getUrl().indexOf("//") != -1) { + String svnUrl =RepositoryService.parseURL(pj.getUrl()); + location = StringUtils.substringAfter(svnUrl, "//");// 192.168.1.100/svn/projar/trunk + location = StringUtils.substringAfter(location, "/");// svn/projar/trunk + location = StringUtils.substringBeforeLast(location, "/trunk");// svn/projar + // see: + // Issue + // 5 + } + + contents.append("").append(SEP); + contents.append("DAV svn").append(SEP); + contents.append("SVNPath ").append(pj.getPath()).append(SEP); + contents.append("AuthType Basic").append(SEP); + contents.append("AuthName ").append("\"").append(pj.getPj()) + .append("\"").append(SEP); + contents.append("AuthUserFile ").append(pj.getPath()) + .append("/conf/passwd.http").append(SEP); + contents.append("AuthzSVNAccessFile ").append(pj.getPath()) + .append("/conf/authz").append(SEP); + contents.append("Require valid-user").append(SEP); + contents.append("").append(SEP); + this.write(outFile, contents.toString()); + + } + + /** + * 输出http多库方式的httpd.conf文件 + * + * @param root + * svn root + */ + private void exportSVNParentPathConf(File root) { + String svnRoot = StringUtils.replace(root.getAbsolutePath(), "\\", "/"); + File outFile = new File(root, "httpd.conf"); + StringBuffer contents = new StringBuffer(); + contents.append("#Include ").append(svnRoot).append("/httpd.conf") + .append(SEP); + + String location = root.getName(); + + contents.append("") + .append(SEP); + contents.append("DAV svn").append(SEP); + contents.append("SVNListParentPath on").append(SEP); + contents.append("SVNParentPath ").append(svnRoot).append(SEP); + contents.append("AuthType Basic").append(SEP); + contents.append("AuthName ").append("\"") + .append("Subversion repositories").append("\"").append(SEP); + contents.append("AuthUserFile ").append(svnRoot).append("/passwd.http") + .append(SEP); + contents.append("AuthzSVNAccessFile ").append(svnRoot).append("/authz") + .append(SEP); + contents.append("Require valid-user").append(SEP); + contents.append("").append(SEP); + contents.append("RedirectMatch ^(/").append(location).append(")$ $1/") + .append(SEP); + this.write(outFile, contents.toString()); + } + + /** + * 写文件流 + * + * @param outFile + * 输出文件 + * @param contents + * 内容 + */ + private void write(File outFile, String contents) { + BufferedWriter writer = null; + try { + if (contents == null) { + contents = ""; + } + if (!outFile.getParentFile().exists()) { + outFile.getParentFile().mkdirs(); + } + writer = new BufferedWriter(new OutputStreamWriter( + new FileOutputStream(outFile), "UTF-8"));// UTF-8 without + // BOM + writer.write(contents); + LOG.debug(outFile); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } finally { + if (writer != null) { + try { + writer.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + try { + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } +} diff --git a/src/main/java/org/svnadmin/service/UsrService.java b/src/main/java/org/svnadmin/service/UsrService.java new file mode 100644 index 0000000..d098ff9 --- /dev/null +++ b/src/main/java/org/svnadmin/service/UsrService.java @@ -0,0 +1,268 @@ +package org.svnadmin.service; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.svnadmin.common.entity.PageBean; +import org.svnadmin.constant.Constants; +import org.svnadmin.dao.PjAuthDao; +import org.svnadmin.dao.PjDao; +import org.svnadmin.dao.PjGrUsrDao; +import org.svnadmin.dao.PjUsrDao; +import org.svnadmin.dao.UsrDao; +import org.svnadmin.entity.Pj; +import org.svnadmin.entity.PjAuth; +import org.svnadmin.entity.Usr; +import org.svnadmin.util.EncryptUtil; +import org.svnadmin.util.I18N; + +/** + * 用户 + * + * @author Huiwu Yuan + * @since 3.0 + * + */ +@Service(UsrService.BEAN_NAME) +public class UsrService { + + /** + * Bean名称 + */ + public static final String BEAN_NAME = "usrService"; + + /** + * 用户DAO + */ + @Resource(name = UsrDao.BEAN_NAME) + protected UsrDao usrDao; + + /** + * 项目权限DAO + */ + @Resource(name = PjAuthDao.BEAN_NAME) + protected PjAuthDao pjAuthDao; + + /** + * 项目组用户DAO + */ + @Resource(name = PjGrUsrDao.BEAN_NAME) + protected PjGrUsrDao pjGrUsrDao; + + /** + * 项目用户DAO + */ + @Resource(name = PjUsrDao.BEAN_NAME) + protected PjUsrDao pjUsrDao; + + /** + * 项目DAO + */ + @Resource(name = PjDao.BEAN_NAME) + protected PjDao pjDao; + + /** + * SVN服务层 + */ + @Resource(name = SvnService.BEAN_NAME) + protected SvnService svnService; + + /** + * 获取一个用户 + * + * @param usr + * 用户 + * @return 用户 + */ + public Usr get(String usr) { + return this.usrDao.get(usr); + } + + /** + * @return 所有用户列表 + */ + public List list() { + return this.usrDao.getList(); + } + + /** + * @param pj + * 项目 + * @return 所有项目用户列表(不包括*) + */ + public List list(String pj) { + return this.usrDao.getList(pj); + } + + /** + * 获取这个项目组未选的用户 + * + * @param pj + * 项目 + * @param gr + * 组 + * @return 项目组未选的用户 + */ + public List listUnSelected(String pj, String gr) { + return this.usrDao.listUnSelected(pj, gr); + } + + /** + * 删除用户(同时删除项目用户,项目组用户,项目用户权限) + * + * @param usr + * 用户 + */ + @Transactional + public void delete(String usr) { + + List list = this.getPjList(usr); + + this.pjAuthDao.deleteUsr(usr); + this.pjGrUsrDao.deleteUsr(usr); + this.pjUsrDao.deleteUsr(usr); + this.usrDao.delete(usr); + + // 更新用户所在的项目 + if (list != null) { + for (Pj pj : list) { + this.svnService.exportConfig(pj); + } + } + } + + /** + * 保存用户 + * + * @param usr + * 用户 + */ + @Transactional + public void save(Usr usr) { + if (this.usrDao.get(usr.getUsr()) == null) { + this.usrDao.insert(usr); + } else { + this.usrDao.update(usr); + } + // 更新用户所在的项目 + List list = this.getPjList(usr.getUsr()); + if (list != null) { + for (Pj pj : list) { + this.svnService.exportConfig(pj); + } + } + } + + /** + * @param usr + * 用户 + * @return 用户的项目 + */ + public List getPjList(String usr) { + List list = this.pjDao.getList(usr);// 用户可以看到的所有项目 + // 如果项目使用http(多库),只返回一个项目就可以,SvnService导出时,会导出所有相同svn root的项目 + List results = new ArrayList(); + + Map temp = new HashMap(); + for (Pj pj : list) { + if (Constants.HTTP_MUTIL.equals(pj.getType())) { + File root = new File(pj.getPath()).getParentFile();// svn root + String key = root.getAbsolutePath(); + if (temp.containsKey(key)) { + continue; + } else { + temp.put(key, pj); + results.add(pj);// 第一个 + } + } else { + results.add(pj); + } + } + + return results; + } + + /** + * @return 总数(不包括*) + */ + public int getCount() { + return this.usrDao.getCount(); + } + + /** + * 登录.如果用户表没有数据,表示第一次使用,输入的用户当作是超级管理员。 + * + * @param usr + * 用户 + * @param psw + * 密码 + * @return 成功则返回用户的信息,失败抛出异常 + */ + @Transactional + public Usr login(String usr, String psw) { + int usrCount = this.getCount(); + if (usrCount == 0) {// 第一次使用,设置管理员 + Usr entity = new Usr(); + entity.setUsr(usr); + entity.setPsw(EncryptUtil.encrypt(psw)); + entity.setRole(Constants.USR_ROLE_ADMIN); + this.usrDao.insert(entity); + // * + Usr all = new Usr(); + all.setUsr("*"); + all.setPsw("*"); + this.usrDao.insert(all); + // + return entity; + } + // 正常登录 + Usr entity = this.get(usr); + if (entity == null) { + throw new RuntimeException(I18N.getLbl("login.error.notfoundusr", "系统不存在用户{0} ",new Object[]{usr})); + } + if (!entity.getPsw().equals(EncryptUtil.encrypt(psw))) { + throw new RuntimeException(I18N.getLbl("login.error.wrongpassword", "用户名或密码有误 ")); + } + return entity; + } + + /** + * 验证是否连接数据库成功 Issue 12 + * @throws Exception 验证失败异常 + */ + public void validatConnection() throws Exception{ + this.usrDao.validatConnection(); + } + + /** + * 是否有管理员的权限 + * @param usr 用户 + * @return 有管理员权限返回true,否则返回false + */ + public boolean hasAdminRight(Usr usr){ + if (Constants.USR_ROLE_ADMIN.equals(usr.getRole())) { + return true; + } + return false; + } + /** + * 报表:获取用户所有的权限 + * @param usr 用户 + * @return 用户所有的权限 + */ + public List getAuths(String usr){ + return this.pjAuthDao.getByUsr(usr); + } + + + public void queryForPageBean(PageBean pageBean) { + + } +} diff --git a/src/main/java/org/svnadmin/servlet/StartupLoddingServlet.java b/src/main/java/org/svnadmin/servlet/StartupLoddingServlet.java new file mode 100644 index 0000000..f2659bf --- /dev/null +++ b/src/main/java/org/svnadmin/servlet/StartupLoddingServlet.java @@ -0,0 +1,37 @@ +package org.svnadmin.servlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; + +import org.apache.log4j.Logger; +import org.svnadmin.common.util.HttpUtils; +import org.svnadmin.common.util.PropUtils; + +/** + * @author hpboys + * @version V1.0 + * @ClassName: StartupLoddingServlet + * @Description: 系统启动时加载数据 + * @date 2015年6月8日 下午10:19:30 + */ +@WebServlet(urlPatterns = "/init", loadOnStartup = 2) +public class StartupLoddingServlet extends HttpServlet { + + private Logger logger = Logger.getLogger(StartupLoddingServlet.class); + + private static final long serialVersionUID = 1L; + + @Override + public void init() throws ServletException { + ServletContext context = getServletContext(); + String sysPath = PropUtils.get("setting.sys_path"); + String sysName = HttpUtils.urlDecode(PropUtils.get("setting.sys_name"), "utf-8"); + context.setAttribute("sysName", sysName); + //设置系统应用根目录 + context.setAttribute("assetsPath", "/" + sysPath + "/assets"); + context.setAttribute("framePath", "/" + sysPath + "/assets/hui"); + context.setAttribute("appPath", "/" + sysPath + "/assets/admin"); + logger.info("load setting finish,the servletContextName is " + context.getServletContextName()); + } +} diff --git a/src/main/java/org/svnadmin/util/EncryptUtil.java b/src/main/java/org/svnadmin/util/EncryptUtil.java new file mode 100644 index 0000000..cce4458 --- /dev/null +++ b/src/main/java/org/svnadmin/util/EncryptUtil.java @@ -0,0 +1,120 @@ +package org.svnadmin.util; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * 加密工具 + * + * @author Huiwu Yuan + * @since 1.0 + */ +public class EncryptUtil { + /** + * + */ + private static final String cvt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + "abcdefghijklmnopqrstuvwxyz0123456789#@$"; + + /** + * + */ + private static final int fillchar = '*'; + + /** + * 加密 + * + * @param str + * 明文 + * @return 密文 + */ + public static String encrypt(String str) { + byte[] data = str.getBytes(); + int c; + int len = data.length; + StringBuffer ret = new StringBuffer(((len / 3) + 1) * 4); + for (int i = 0; i < len; ++i) { + c = (data[i] >> 2) & 0x3f; + ret.append(cvt.charAt(c)); + c = (data[i] << 4) & 0x3f; + if (++i < len) { + c |= (data[i] >> 4) & 0x0f; + } + ret.append(cvt.charAt(c)); + if (i < len) { + c = (data[i] << 2) & 0x3f; + if (++i < len) { + c |= (data[i] >> 6) & 0x03; + } + ret.append(cvt.charAt(c)); + } else { + ++i; + ret.append((char) fillchar); + } + if (i < len) { + c = data[i] & 0x3f; + ret.append(cvt.charAt(c)); + } else { + ret.append((char) fillchar); + } + } + return ret.toString(); + } + + /** + * 解密 + * + * @param str + * 密文 + * @return 明文 + */ + public static String decrypt(String str) { + byte[] data = str.getBytes(); + int c, c1; + int len = data.length; + StringBuffer ret = new StringBuffer((len * 3) / 4); + for (int i = 0; i < len; ++i) { + c = cvt.indexOf(data[i]); + ++i; + c1 = cvt.indexOf(data[i]); + c = ((c << 2) | ((c1 >> 4) & 0x3)); + ret.append((char) c); + if (++i < len) { + c = data[i]; + if (fillchar == c) { + break; + } + c = cvt.indexOf((char) c); + c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf); + ret.append((char) c1); + } + if (++i < len) { + c1 = data[i]; + if (fillchar == c1) { + break; + } + c1 = cvt.indexOf((char) c1); + c = ((c << 6) & 0xc0) | c1; + ret.append((char) c); + } + } + return ret.toString(); + } + + /** + * apache SHA1 加密 + * + * @param str + * 明文 + * @return 密文 + */ + public static String encriptSHA1(String str) { + try { + return new sun.misc.BASE64Encoder().encode(MessageDigest + .getInstance("SHA1").digest(str.getBytes())); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/org/svnadmin/util/I18N.java b/src/main/java/org/svnadmin/util/I18N.java new file mode 100644 index 0000000..ddb267f --- /dev/null +++ b/src/main/java/org/svnadmin/util/I18N.java @@ -0,0 +1,171 @@ +/** + * + */ +package org.svnadmin.util; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.svnadmin.common.util.SpringUtils; +import org.svnadmin.constant.Constants; +import org.svnadmin.entity.I18n; +import org.svnadmin.service.I18nService; + +/** + * 多语言工具类 + * + * @author Huiwu Yuan + * @since 3.0.2 + */ +public class I18N { + + /** + * 缓存 + */ + private static Map cache = new HashMap(); + /** + * 多语言服务层 + */ + private static I18nService i18nService = SpringUtils.getBean(I18nService.BEAN_NAME); + + /** + * 获取默认的语言 + * @param request 请求 + * @return 获取默认的语言 + */ + public static final String getDefaultLang(HttpServletRequest request){ + //from session + String result = (String) request.getSession().getAttribute(Constants.SESSION_KEY_LANG); + if(result != null){ + return result; + } + //from request local + Locale locale = request.getLocale(); + String country = locale.getCountry(); + String language = locale.getLanguage(); + + if(country.length() != 0 && i18nService.existsLang(language+"_"+country)){//数据库是否存在这个语言? + result = language+"_"+country; + } + if(result == null && i18nService.existsLang(language)){//数据库是否存在这个语言? + result = language; + } + if(result == null){ + result = Locale.SIMPLIFIED_CHINESE.toString();//default zh_CN + getLbl(result, result, Locale.SIMPLIFIED_CHINESE.getDisplayLanguage());//增加当前语言到数据库i18n + } + + + request.getSession().setAttribute(Constants.SESSION_KEY_LANG, result);//set to session + return result; + } + + /** + * @param request 请求 + * @param id 语言id + * @param defValue 默认值 + * @return 格式化后的多语言 + */ + public static final String getLbl(HttpServletRequest request,String id,String defValue){ + return getLbl(getDefaultLang(request), id, defValue, null); + } + /** + * @param request 请求 + * @param id 语言id + * @param defValue 默认值 + * @param args 参数 + * @return 格式化后的多语言 + */ + public static final String getLbl(HttpServletRequest request,String id,String defValue,Object[] args){ + return getLbl(getDefaultLang(request), id, defValue, args); + } + /** + * @param lang 语言 + * @param id 语言id + * @param defValue 默认值 + * @return 格式化后的多语言 + */ + public static final String getLbl(String lang,String id,String defValue){ + return getLbl(lang, id, defValue, null); + } + /** + * @param lang 语言 + * @param id key + * @param defValue 默认值 + * @param args 参数 + * @return 格式化后的多语言 + */ + public static final String getLbl(String lang,String id,String defValue,Object[] args){ + String key = lang+"$"+id; + //from cache + if(cache.containsKey(key)){ + return format(cache.get(key), args); + } + //from database + I18n i18n = i18nService.getI18n(lang,id); + if(i18n == null){//数据库里不存在 + i18n = new I18n(); + i18n.setLang(lang); + i18n.setId(id); + i18n.setLbl(defValue); + i18nService.insert(i18n); + } + + cache.put(key, i18n.getLbl());//put into cache + + return format(i18n.getLbl(), args); + } + + /** + * 格式化消息 + * @param pattern the pattern for this message format + * @param arguments 参数 + * @return 格式化后的消息 + */ + private static String format(String pattern,Object[] arguments){ +// format = new MessageFormat(pattern); +// format.setLocale(locale); +// format.applyPattern(pattern); +// str = format.format(args) + if(pattern == null){ + return ""; + } + return MessageFormat.format(pattern, arguments); + } + + /** + * 清空缓存 + */ + public static synchronized void clearCache(){ + cache.clear(); + } + + /** + * 提供Service层或DAO使用,会从当前的线程中获取语言 + * @param id 语言id + * @param defValue 默认值 + * @return 格式化后的多语言 + * + * @see LangProvider + */ + public static final String getLbl(String id,String defValue){ + return getLbl(LangProvider.getCurrentLang(), id, defValue, null); + } + /** + * 提供Service层或DAO使用,会从当前的线程中获取语言 + * @param id key + * @param defValue 默认值 + * @param args 参数 + * @return 格式化后的多语言 + * + * @see LangProvider + */ + public static final String getLbl(String id,String defValue,Object[] args){ + return getLbl(LangProvider.getCurrentLang(), id, defValue, args); + } + +} diff --git a/src/main/java/org/svnadmin/util/LangProvider.java b/src/main/java/org/svnadmin/util/LangProvider.java new file mode 100644 index 0000000..95164f6 --- /dev/null +++ b/src/main/java/org/svnadmin/util/LangProvider.java @@ -0,0 +1,48 @@ +/** + * + */ +package org.svnadmin.util; + +import java.util.Locale; + +/** + * 为当前的线程提供lang + * + * @author Huiwu Yuan + * @since 3.0.2 + * + */ +public class LangProvider { + /** + * + */ + private static final ThreadLocal LANG_THREAD_LOCAL = new ThreadLocal(); + + /** + * @return 当前的语言 + */ + public static String getCurrentLang() { + String lang = LANG_THREAD_LOCAL.get(); + if(lang == null){ +// throw new RuntimeException("当前线程没有设置语言!"); + //默认简体中文 + return Locale.SIMPLIFIED_CHINESE.toString(); + } + return lang; + } + + /** + * 设置当前的语言到当前线程中 + * @param lang 语言 + */ + public static void setLang(String lang) { + LANG_THREAD_LOCAL.set(lang); + } + + /** + * 清空线程的语言 + */ + public static void removeLang() { + LANG_THREAD_LOCAL.remove(); + } +} diff --git a/src/main/java/org/svnadmin/util/SessionUtils.java b/src/main/java/org/svnadmin/util/SessionUtils.java new file mode 100644 index 0000000..4b8f5c4 --- /dev/null +++ b/src/main/java/org/svnadmin/util/SessionUtils.java @@ -0,0 +1,52 @@ +package org.svnadmin.util; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.svnadmin.common.util.SpringUtils; +import org.svnadmin.constant.SessionConstant; +import org.svnadmin.entity.Usr; +import org.svnadmin.service.UsrService; + +/** + * @描述: Session操作工具类. + * @作者: Zoro. + * @创建时间: 2016-04-19 17:58. + * @版本: 1.0.0. + */ +public class SessionUtils { + + /** + * 得到当前登录用户 + * @param session + * @return + */ + public static Usr getLogedUser(HttpSession session){ + Object object = session.getAttribute(SessionConstant.USER_SESSION_KEY); + if(object!=null){ + if(object instanceof Usr){ + return (Usr)object; + } + } + return null; + } + + /** + * 是否已登录 + */ + public static boolean isLogin(HttpServletRequest request) { + Usr adminUser = SessionUtils.getLogedUser(request.getSession()); + return null != adminUser; + } + + /** + * @param session 请求 + * @return 当前登录的用户是否有管理员角色 + * @see org.svnadmin.constant.Constants#USR_ROLE_ADMIN + * @see Usr#getRole() + */ + public static boolean hasAdminRight(HttpSession session) { + UsrService usrService = SpringUtils.getBean(UsrService.BEAN_NAME); + return usrService.hasAdminRight(getLogedUser(session)); + } +} diff --git a/src/main/java/org/svnadmin/util/UsrProvider.java b/src/main/java/org/svnadmin/util/UsrProvider.java new file mode 100644 index 0000000..ea25742 --- /dev/null +++ b/src/main/java/org/svnadmin/util/UsrProvider.java @@ -0,0 +1,46 @@ +/** + * + */ +package org.svnadmin.util; + +import org.svnadmin.entity.Usr; + +/** + * 为当前的线程提供登录的用户 + * + * @author Huiwu Yuan + * @since 3.0.2 + * + */ +public class UsrProvider { + /** + * + */ + private static final ThreadLocal USR_THREAD_LOCAL = new ThreadLocal(); + + /** + * @return 当前的用户 + */ + public static Usr getCurrentUsr() { + Usr usr = USR_THREAD_LOCAL.get(); + if(usr == null){ + throw new RuntimeException("当前线程没有设置用户!"); + } + return usr; + } + + /** + * 设置当前的用户到当前线程中 + * @param usr 用户 + */ + public static void setUsr(Usr usr) { + USR_THREAD_LOCAL.set(usr); + } + + /** + * 清空线程的用户 + */ + public static void removeUsr() { + USR_THREAD_LOCAL.remove(); + } +} diff --git a/src/main/java/org/svnadmin/util/filter/ParameterFilter.java b/src/main/java/org/svnadmin/util/filter/ParameterFilter.java new file mode 100644 index 0000000..ed87b9f --- /dev/null +++ b/src/main/java/org/svnadmin/util/filter/ParameterFilter.java @@ -0,0 +1,48 @@ +package org.svnadmin.util.filter; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.svnadmin.common.util.PrintUtils; + +/** + * @ClassName: ParameterFilter + * @Description: 特殊字符拦截过滤器 + * @author + * @date 2015年7月7日 下午8:24:59 + * @version V1.0 + */ +@WebFilter(filterName="ParameterFilter",urlPatterns="/*") +public class ParameterFilter implements Filter { + + private static Logger logger = Logger.getLogger(ParameterFilter.class); + + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest rq = (HttpServletRequest)request; + HttpServletResponse rp = (HttpServletResponse)response; + if(!rq.getRequestURI().contains(".")){ + PrintUtils.print(rq); + if(rq.getRequestURI().endsWith("/")){ + rp.sendRedirect("login"); + return; + } + } + filterChain.doFilter(request, response); + } + + public void init(FilterConfig arg0) throws ServletException {} + + public void destroy() {} +} + diff --git a/src/main/java/org/svnadmin/util/interceptor/AdminInterceptor.java b/src/main/java/org/svnadmin/util/interceptor/AdminInterceptor.java new file mode 100644 index 0000000..84c3658 --- /dev/null +++ b/src/main/java/org/svnadmin/util/interceptor/AdminInterceptor.java @@ -0,0 +1,61 @@ +package org.svnadmin.util.interceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.log4j.Logger; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; +import org.svnadmin.common.annotation.AdminAuthPassport; +import org.svnadmin.common.annotation.AuthPassport; +import org.svnadmin.common.util.PropUtils; +import org.svnadmin.util.SessionUtils; + + +/** + * @author hpboys + * @version V1.0 + * @ClassName: AdminInterceptor + * @Description: 后台拦截器 + * @date 2016年4月17日 下午7:17:56 + */ +public class AdminInterceptor extends HandlerInterceptorAdapter { + + private Logger logger = Logger.getLogger(AdminInterceptor.class); + + private final static String LOGIN_URL = "login";//登录页面 + private final static String CONSOLE_URL = "pjList";//控制台页面 + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + HttpSession session = request.getSession(); + HandlerMethod auth = (HandlerMethod) handler; + AuthPassport authPassport = auth.getMethodAnnotation(AuthPassport.class); + if (null != authPassport) { + if (SessionUtils.isLogin(request)) { + //去控制台页面 + response.sendRedirect("/" + PropUtils.get("setting.sys_path") + "/" + CONSOLE_URL); + return false; + } + }else{ + //是否已经登录 + if (!SessionUtils.isLogin(request)) { + //去登录页面 + response.sendRedirect("/" + PropUtils.get("setting.sys_path") + "/" + LOGIN_URL); + return false; + } + } + //鉴权 + AdminAuthPassport adminAuth = auth.getMethodAnnotation(AdminAuthPassport.class); + if(null != adminAuth){ + if(!SessionUtils.hasAdminRight(session)){ + //无权限页面 + request.getRequestDispatcher("/WEB-INF/views/common/not_auth.jsp").forward(request,response); + return false; + } + } + return true; + } + +} diff --git a/src/main/java/org/svnadmin/util/place/SystemPropertyPlaceholderConfigurer.java b/src/main/java/org/svnadmin/util/place/SystemPropertyPlaceholderConfigurer.java new file mode 100644 index 0000000..c74e5d4 --- /dev/null +++ b/src/main/java/org/svnadmin/util/place/SystemPropertyPlaceholderConfigurer.java @@ -0,0 +1,23 @@ +package org.svnadmin.util.place; + +import java.util.Properties; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; +import org.svnadmin.common.util.PropUtils; + +/** + * @ClassName: SystemPropertyPlaceholderConfigurer + * @Description: 系统配置文件的属性加载 + * @author zyj + * @date 2015年9月17日 下午1:55:39 + * @version V1.0 + */ +public class SystemPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer { + + protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) throws BeansException { + PropUtils.initConfigProperties(props); + } + +} \ No newline at end of file diff --git a/src/main/java/org/tree/entity/Tree.java b/src/main/java/org/tree/entity/Tree.java new file mode 100644 index 0000000..3e8858b --- /dev/null +++ b/src/main/java/org/tree/entity/Tree.java @@ -0,0 +1,109 @@ +package org.tree.entity; + +import java.io.Serializable; + + +/** + * 树 + * @author Huiwu Yuan + * @since 3.0.2 + * + */ +public class Tree implements Serializable{ + /** + * 序列化ID + */ + private static final long serialVersionUID = -785319127620330061L; + /** + * ID + */ + private String id; + /** + * 父节点ID + */ + private String parentId; + /** + * 是否是叶子 + */ + private boolean leaf; + /** + * 节点服务层 + */ + private String treeNodeService; + + /** + * 默认构造函数 + */ + public Tree() { + } + + /** + * 构造函数 + * @param id ID + * @param parentId 父节点ID + * @param treeNodeService 节点服务层 + */ + public Tree(String id,String parentId,String treeNodeService){ + this.id=id; + this.parentId=parentId; + this.treeNodeService = treeNodeService; + } + + /** + * @return ID + */ + public String getId() { + return id; + } + + /** + * @param id ID + */ + public void setId(String id) { + this.id = id; + } + + /** + * @return 父节点ID + */ + public String getParentId() { + return parentId; + } + + /** + * @param parentId 父节点ID + */ + public void setParentId(String parentId) { + this.parentId = parentId; + } + + /** + * @return 是否是叶子 + */ + public boolean isLeaf() { + return leaf; + } + + /** + * @param leaf 是否是叶子 + */ + public void setLeaf(boolean leaf) { + this.leaf = leaf; + } + + /** + * @return 节点服务层 + */ + public String getTreeNodeService() { + return treeNodeService; + } + + /** + * @param treeNodeService 节点服务层 + */ + public void setTreeNodeService(String treeNodeService) { + this.treeNodeService = treeNodeService; + } + + +} diff --git a/src/main/java/org/tree/entity/TreeNode.java b/src/main/java/org/tree/entity/TreeNode.java new file mode 100644 index 0000000..97c64bf --- /dev/null +++ b/src/main/java/org/tree/entity/TreeNode.java @@ -0,0 +1,217 @@ +package org.tree.entity; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +/** + * 树节点 + * @author Huiwu Yuan + * @since 3.0.2 + * + */ +public class TreeNode implements Comparable,Serializable{ + /** + * 序列化ID + */ + private static final long serialVersionUID = -2006855434442859723L; + /** + * 节点显示的文字 + */ + private String text; + /** + * 点击节点时的url链接 + */ + private String url; + /** + * 是否是叶子 + */ + private boolean leaf; + /** + * 父节点 + */ + private TreeNode parent; + + /** + * 叶子 + */ + private List children; + + + /** + * 参数 + */ + private Map parameters; + /** + * 属性 + */ + private Map attributes; + + /** + * 默认构造函数 + */ + public TreeNode() { + } + + /** + * 构造函数 + * @param text 节点显示的文字 + */ + public TreeNode(String text){ + this.text=text; + } + + /** + * @return 父节点 + */ + public TreeNode getParent() { + return parent; + } + + /** + * @param parent 父节点 + */ + public void setParent(TreeNode parent) { + this.parent = parent; + } + + /** + * @return 叶子 + */ + public List getChildren() { + return children; + } + + /** + * @param children 叶子 + */ + public void setChildren(List children) { + if(children !=null){ + for (TreeNode treeNode : children) { + treeNode.setParent(this); + } + } + this.children = children; + } + + /** + * @return 是否是叶子 + */ + public boolean isLeaf() { + return leaf; + } + + /** + * @param leaf 是否是叶子 + */ + public void setLeaf(boolean leaf) { + this.leaf = leaf; + } + + /** + * @return 参数 + */ + public Map getParameters() { + return parameters; + } + + /** + * @param parameters 参数 + */ + public void setParameters(Map parameters) { + this.parameters = parameters; + } + + /** + * @return 属性 + */ + public Map getAttributes() { + return attributes; + } + + /** + * @param attributes 属性 + */ + public void setAttributes(Map attributes) { + this.attributes = attributes; + } + + /** + * 增加一个参数 + * @param key 键 + * @param value 值 + */ + public void addParamete(String key,String value){ + if(parameters == null){ + parameters = new HashMap(); + } + parameters.put(key, value); + } + + /** + * 增加一个属性 + * @param key 键 + * @param value 值 + */ + public void addAttribute(String key,String value){ + if(attributes == null){ + attributes = new HashMap(); + } + attributes.put(key, value); + } + + /** + * @return 节点显示的文字 + */ + public String getText() { + return text; + } + + /** + * @param text 节点显示的文字 + */ + public void setText(String text) { + this.text = text; + } + + /** + * @return 点击节点时的url链接 + */ + public String getUrl() { + return url; + } + + /** + * @param url 点击节点时的url链接 + */ + public void setUrl(String url) { + this.url = url; + } + + public int compareTo(TreeNode o) { + if(this.isLeaf()){ + if(o.isLeaf()){ + if(this.getText() == null){ + return -1; + }else{ + return this.getText().compareToIgnoreCase(o.getText()); + } + }else{ + return 1; + } + }else{ + if(o.isLeaf()){ + return -1; + }else{ + if(this.getText() == null){ + return -1; + }else{ + return this.getText().compareToIgnoreCase(o.getText()); + } + } + } + + } + + +} diff --git a/src/main/java/org/tree/service/AbstractTreeNodeService.java b/src/main/java/org/tree/service/AbstractTreeNodeService.java new file mode 100644 index 0000000..6dfb380 --- /dev/null +++ b/src/main/java/org/tree/service/AbstractTreeNodeService.java @@ -0,0 +1,192 @@ +package org.tree.service; + +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang.StringEscapeUtils; +import org.tree.entity.Tree; +import org.tree.entity.TreeNode; + + +/** + * 抽象树节点服务层 + * @author Huiwu Yuan + * @since 3.0.2 + * + */ +public abstract class AbstractTreeNodeService implements TreeNodeService { + + public StringBuffer getHTML(Tree tree, Map parameters) { + StringBuffer html = new StringBuffer(); + List nodes = getTreeNodes(tree, parameters); + if (nodes == null || nodes.size() == 0) { + return null; + } + html.append("
    "); + for (int i = 0; nodes != null && i < nodes.size(); i++) { + TreeNode treeNode = nodes.get(i); + + // htmlsrc + html.append(" allParam = new HashMap(); + if (parameters != null) { + allParam.putAll(parameters); + } + Map treeNodeParameters = treeNode.getParameters(); + if (treeNodeParameters != null) { + allParam.putAll(treeNodeParameters); + } + allParam.remove(TreeService.TREE_ID_VAR); + allParam.remove(TreeService.TREE_PARENTID_VAR); + prepareParameters(html, allParam); + + // url + if (treeNode.getUrl() != null) { + this.prepareAttribute(html, "url", treeNode.getUrl()); + } + + // otherAttributes + Map attributes = treeNode.getAttributes(); + if (attributes != null) { + Iterator attributeKeys = treeNode.getAttributes() + .keySet().iterator(); + while (attributeKeys.hasNext()) { + String att = attributeKeys.next(); + prepareAttribute(html, att, treeNode.getAttributes().get( + att)); + } + } + // end otherAttributes + + // end
  • + html.append(" >"); + + // span + if (this.isLeaf(tree,treeNode)) { + html.append(""); + }else{ + if(i == nodes.size() -1){//last folder + html.append("
    "); + }else{ + html.append("
    "); + } + html.append(""); + } + // a + html.append(""); + html.append(StringEscapeUtils.escapeHtml(treeNode.getText())); + html.append(""); + html.append(""); + //end
  • + html.append(""); + + } + html.append("
"); + //System.out.println(html); + return html; + } + + /** + * 获取子节点 + * @param parent 树 + * @param parameters 参数 + * @return 子节点 + */ + protected abstract List getTreeNodes(Tree parent,Map parameters); + + /** + * 处理参数 + * @param handlers html + * @param params 参数 + */ + protected void prepareParameters(StringBuffer handlers,Map params) { + if (params == null) + return; + + StringBuffer result = new StringBuffer(); + Iterator iterKeys = params.keySet().iterator(); + int count =0; + while(iterKeys.hasNext()){ + if(count >0)result.append("&"); + count ++; + + String key = iterKeys.next(); + Object value = params.get(key); + try { + value = java.net.URLEncoder.encode((String) value, "UTF-8"); + } catch (UnsupportedEncodingException e) { + value = params.get(key); + e.printStackTrace(); + } + if(value != null){ + if(value instanceof String){ + result.append(key).append("=").append(value.toString()); + }else if(value instanceof String[]){ + String[] arrs = (String[])value; + for (String string : arrs) { + if(string == null){ + result.append(key).append("="); + }else{ + result.append(key).append("=").append(string); + } + } + }else{ + throw new RuntimeException("Not support parameter: "+ key +"="+value);//TODO + } + }else{ + result.append(key).append("="); + } + + } + if(result.length()>0){ + this.prepareAttribute(handlers, "param", result.toString()); + } + } + + /** + * Prepares an attribute if the value is not null, appending it to the the + * given StringBuffer. + * + * @param handlers + * The StringBuffer that output will be appended to. + * @param name 属性名称 + * @param value 属性值 + */ + protected void prepareAttribute(StringBuffer handlers, String name, + Object value) { + if (value != null) { + handlers.append(" "); + handlers.append(name); + handlers.append("=\""); + handlers.append(value); + handlers.append("\""); + } + } + + /** + * @param tree 树 + * @param treeNode 节点 + * @return 是否是叶子节点 + */ + protected boolean isLeaf(Tree tree,TreeNode treeNode){ + return treeNode.isLeaf() || tree.isLeaf(); + } +} diff --git a/src/main/java/org/tree/service/AbstractTreeService.java b/src/main/java/org/tree/service/AbstractTreeService.java new file mode 100644 index 0000000..5964e09 --- /dev/null +++ b/src/main/java/org/tree/service/AbstractTreeService.java @@ -0,0 +1,88 @@ +package org.tree.service; + +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.tree.entity.Tree; + +/** + * 抽象树服务层 + * @author Huiwu Yuan + * @since 3.0.2 + * + */ +public abstract class AbstractTreeService implements TreeService { + + /** + * 日志 + */ + private static final Log LOG = LogFactory.getLog(AbstractTreeService.class); + + public String getHTML(Map parameters) { + try { + String treeId = (String) parameters.get(TREE_ID_VAR); + String parentId = (String) parameters.get(TREE_PARENTID_VAR); + + if (StringUtils.isBlank(treeId) && StringUtils.isBlank(parentId)) { + return null; + } + + StringBuffer html = new StringBuffer(); + + if (StringUtils.isNotBlank(parentId)) { + // 找出所有的子树 + List treeList = getTreeFactory().findChildren(parentId); + for (Tree tree : treeList) { + if (tree == null) { + continue; + } + parseTree(html, tree, parameters); + } + } else if (StringUtils.isNotBlank(treeId)) { + // 说明是第一层 + Tree tree = getTreeFactory().find(treeId); + if (tree == null) { + LOG.info("not found tree. id = " + treeId); + return null; + } + parseTree(html, tree, parameters); + } + return html.toString(); + + // LOG.info(html.toString()); + } catch (Exception e) { + LOG.error(e); + e.printStackTrace(); + return null; + } + } + + /** + * @param treeHtml html + * @param tree 树 + * @param parameters 参数 + */ + protected void parseTree(StringBuffer treeHtml, Tree tree, + Map parameters) { + StringBuffer html; + try { + html = getTreeFactory().findTreeNodeService(tree).getHTML(tree, + parameters); + } catch (Exception e) { + LOG.error(e); + e.printStackTrace(); + html = null; + } finally { + } + + if (html == null) { + LOG.debug("not found tree html data." + tree); + return; + } + treeHtml.append(html); + } + +} diff --git a/src/main/java/org/tree/service/TreeFactory.java b/src/main/java/org/tree/service/TreeFactory.java new file mode 100644 index 0000000..cce40ed --- /dev/null +++ b/src/main/java/org/tree/service/TreeFactory.java @@ -0,0 +1,36 @@ +package org.tree.service; + +import java.util.List; + +import org.tree.entity.Tree; + +/** + * 树工厂类 + * @author Huiwu Yuan + * @since 3.0.2 + * + */ +public interface TreeFactory { + + /** + * @param id 树ID + * @return 查找树 + */ + Tree find(String id); + + /** + * 查找子树 + * + * @param parentId 父树ID + * @return 树的子树 + */ + List findChildren(String parentId); + + /** + * 根据树获取对应的树节点服务层 + * @param tree 树 + * @return 树节点服务层 + */ + TreeNodeService findTreeNodeService(Tree tree); + +} diff --git a/src/main/java/org/tree/service/TreeNodeService.java b/src/main/java/org/tree/service/TreeNodeService.java new file mode 100644 index 0000000..54f65d7 --- /dev/null +++ b/src/main/java/org/tree/service/TreeNodeService.java @@ -0,0 +1,23 @@ +package org.tree.service; + +import java.util.Map; + +import org.tree.entity.Tree; + +/** + * 树节点服务层接口 + * @author Huiwu Yuan + * @since 3.0.2 + * + */ +public interface TreeNodeService { + + /** + * 获取树节点的html + * @param tree 树 + * @param parameters 参数 + * @return 树节点的html + */ + StringBuffer getHTML(Tree tree, Map parameters); + +} diff --git a/src/main/java/org/tree/service/TreeService.java b/src/main/java/org/tree/service/TreeService.java new file mode 100644 index 0000000..4dc7fd5 --- /dev/null +++ b/src/main/java/org/tree/service/TreeService.java @@ -0,0 +1,34 @@ +/** + * + */ +package org.tree.service; + +import java.util.Map; + +/** + * 树服务层接口 + * @author Huiwu Yuan + * @since 3.0.2 + * + */ +public interface TreeService { + /** + * 树ID + */ + public static final String TREE_ID_VAR = "treeId"; + /** + * 树的父的ID + */ + public static final String TREE_PARENTID_VAR = "treeParentId"; + + /** + * @return 树工厂类 + */ + TreeFactory getTreeFactory(); + + /** + * @param parameters 参数 + * @return 树的html + */ + String getHTML(Map parameters); +} diff --git a/src/main/resources/META-INF/zip.xml b/src/main/resources/META-INF/zip.xml new file mode 100644 index 0000000..aa204da --- /dev/null +++ b/src/main/resources/META-INF/zip.xml @@ -0,0 +1,35 @@ + + ${project.version} + + zip + + false + + + ${project.build.directory} + / + + ${project.build.finalName}.war + ${project.build.finalName}-sources.jar + ${project.build.finalName}-javadoc.jar + + + + ${project.basedir}/db + /db + + **/*.sql + + + + ${project.basedir}/doc + / + + *.pdf + + + + \ No newline at end of file diff --git a/src/main/resources/jdbc.properties b/src/main/resources/jdbc.properties new file mode 100644 index 0000000..d1498ce --- /dev/null +++ b/src/main/resources/jdbc.properties @@ -0,0 +1,29 @@ +db=MySQL + +#Dev Local MySQL +#MySQL.jdbc.driver=com.mysql.jdbc.Driver +#MySQL.jdbc.url=jdbc:mysql://127.0.0.1:3306/svnadmin?characterEncoding=utf-8 +#MySQL.jdbc.username=root +#MySQL.jdbc.password=root +#MySQL.jdbc.validationQuery=select now() + +#MySQL +MySQL.jdbc.driver=com.mysql.jdbc.Driver +MySQL.jdbc.url=jdbc:mysql://localhost:3306/svnadmin?characterEncoding=utf-8 +MySQL.jdbc.username=root +MySQL.jdbc.password=duxact +MySQL.jdbc.validationQuery=select now() + +#Oracle +#Oracle.jdbc.driver=oracle.jdbc.driver.OracleDriver +#Oracle.jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:svnadmin +#Oracle.jdbc.username=root +#Oracle.jdbc.password=root +#Oracle.jdbc.validationQuery=select 1 from dual + +#SQLSERVER +#SQLSERVER.jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver +#SQLSERVER.jdbc.url=jdbc:sqlserver://127.0.0.1:1433;databaseName=svnadmin +#SQLSERVER.jdbc.username=sa +#SQLSERVER.jdbc.password=sa +#SQLSERVER.jdbc.validationQuery=select getdate() \ No newline at end of file diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties new file mode 100644 index 0000000..5e3b052 --- /dev/null +++ b/src/main/resources/log4j.properties @@ -0,0 +1,12 @@ +log4j.rootCategory=info,C,F + +log4j.appender.C=org.apache.log4j.ConsoleAppender +log4j.appender.C.layout=org.apache.log4j.PatternLayout +log4j.appender.C.layout.ConversionPattern=[%-p] %d %c:%L %n %m%n + +log4j.appender.F=org.apache.log4j.FileAppender +log4j.appender.F.File=log.log +log4j.appender.F.layout=org.apache.log4j.PatternLayout +log4j.appender.F.layout.ConversionPattern=[%-p] %d %c:%L %n %m%n + +log4j.logger.org.springframework.beans.factory.support.DefaultListableBeanFactory=warn \ No newline at end of file diff --git a/src/main/resources/setting.properties b/src/main/resources/setting.properties new file mode 100644 index 0000000..20d81a5 --- /dev/null +++ b/src/main/resources/setting.properties @@ -0,0 +1,11 @@ +########################################## +### ϵͳ +########################################## +# Ŀ汾 +setting.version=${project.version} +# ĿĿ¼ ,˴˴ҲҪglobal_config.jsļ +setting.sys_path=svnadmin +# Ŀʾ +setting.sys_name=SVN%E8%B5%84%E6%BA%90%E7%AE%A1%E7%90%86%E5%B9%B3%E5%8F%B0 +# Ŀ汾 +version=${project.version} \ No newline at end of file diff --git a/src/main/resources/spring/spring-config.xml b/src/main/resources/spring/spring-config.xml new file mode 100644 index 0000000..1fd367d --- /dev/null +++ b/src/main/resources/spring/spring-config.xml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + classpath*:setting.properties + classpath*:jdbc.properties + + + + + + + + + classpath*:setting.properties + classpath*:jdbc.properties + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.springframework.web.servlet.view.JstlView + + + /WEB-INF/views/ + + + .jsp + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/springMVC.xml b/src/main/resources/springMVC.xml new file mode 100644 index 0000000..3a46958 --- /dev/null +++ b/src/main/resources/springMVC.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/lib/ojdbc-10.2.0.3.0.jar b/src/main/webapp/WEB-INF/lib/ojdbc-10.2.0.3.0.jar new file mode 100644 index 0000000..2bcaa01 Binary files /dev/null and b/src/main/webapp/WEB-INF/lib/ojdbc-10.2.0.3.0.jar differ diff --git a/src/main/webapp/WEB-INF/lib/sqljdbc-2005.jar b/src/main/webapp/WEB-INF/lib/sqljdbc-2005.jar new file mode 100644 index 0000000..7706d39 Binary files /dev/null and b/src/main/webapp/WEB-INF/lib/sqljdbc-2005.jar differ diff --git a/src/main/webapp/WEB-INF/views/basic/console.jsp b/src/main/webapp/WEB-INF/views/basic/console.jsp new file mode 100644 index 0000000..2a4272d --- /dev/null +++ b/src/main/webapp/WEB-INF/views/basic/console.jsp @@ -0,0 +1,81 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + + + + SVN资源管理平台 - 首页 + + + +
+
+ +
+
+
+
+
+
+
SVN 项目列表
+
+
+
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
序号项目路径URL类型描述设置用户设置用户组设置权限删除
未查询到相关数据
${v.index+1}${item.pj}${item.pj}${item.pj}${item.pj}${item.pj}{{userStatus[item.isActive]}}${item.pj}${item.pj}${item.pj}
+
+
+
+
+
+
+
+
+
+ +<%----%> + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/basic/login.jsp b/src/main/webapp/WEB-INF/views/basic/login.jsp new file mode 100644 index 0000000..cead2b6 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/basic/login.jsp @@ -0,0 +1,61 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + + + + + + + + 登录 - ${applicationScope.sysName} + + + + + + + + +
+
+
+ +
+
+
+

登录:

+ +

登录到SVN资源管理平台

+ + + <%--<%–忘记密码了?–%>--%> + <%-- --%> +

+ +
+
+
+ +
+ + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/common/404.jsp b/src/main/webapp/WEB-INF/views/common/404.jsp new file mode 100644 index 0000000..bb0719b --- /dev/null +++ b/src/main/webapp/WEB-INF/views/common/404.jsp @@ -0,0 +1,49 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + + + + + + 请求资源不存在 - ${applicationScope.sysName} + + + + +
+

404 . Not Found

+

沒有找到你要的内容!

+
+

扫码收益,先人一步!

+

+
+ + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/common/exception.jsp b/src/main/webapp/WEB-INF/views/common/exception.jsp new file mode 100644 index 0000000..a18847a --- /dev/null +++ b/src/main/webapp/WEB-INF/views/common/exception.jsp @@ -0,0 +1,111 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + 服务器暂时无法解释您的请求 - ${applicationScope.sysName} + + + + + + +
+ +

500,server not explain your request!

+ +

服务器暂时无法解释您的请求

+
+ +

+ 扫码关注话费宝 +

+ +

+
+ + diff --git a/src/main/webapp/WEB-INF/views/common/footer.jsp b/src/main/webapp/WEB-INF/views/common/footer.jsp new file mode 100644 index 0000000..4cd51f7 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/common/footer.jsp @@ -0,0 +1,11 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + diff --git a/src/main/webapp/WEB-INF/views/common/header.jsp b/src/main/webapp/WEB-INF/views/common/header.jsp new file mode 100644 index 0000000..8191c40 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/common/header.jsp @@ -0,0 +1,46 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +
+ +
diff --git a/src/main/webapp/WEB-INF/views/common/init_script.jsp b/src/main/webapp/WEB-INF/views/common/init_script.jsp new file mode 100644 index 0000000..09584e5 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/common/init_script.jsp @@ -0,0 +1,6 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/common/init_style.jsp b/src/main/webapp/WEB-INF/views/common/init_style.jsp new file mode 100644 index 0000000..2e81356 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/common/init_style.jsp @@ -0,0 +1,12 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/common/not_auth.jsp b/src/main/webapp/WEB-INF/views/common/not_auth.jsp new file mode 100644 index 0000000..e262765 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/common/not_auth.jsp @@ -0,0 +1,111 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + 无权限访问 - ${applicationScope.sysName} + + + + + + +
+ + <%--

500,server not explain your request!

--%> + +

该页面无权限访问,请联系管理员。

+
+ +

+ 扫码关注话费宝 +

+ +

+
+ + diff --git a/src/main/webapp/WEB-INF/views/common/pagination.jsp b/src/main/webapp/WEB-INF/views/common/pagination.jsp new file mode 100644 index 0000000..b590ea4 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/common/pagination.jsp @@ -0,0 +1,36 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/rep/repository.jsp b/src/main/webapp/WEB-INF/views/rep/repository.jsp new file mode 100644 index 0000000..48b6c8f --- /dev/null +++ b/src/main/webapp/WEB-INF/views/rep/repository.jsp @@ -0,0 +1,174 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + + + + 项目资源权限管理 - ${applicationScope.sysName} + + + + + +
+
+ +
+
+
+
+
+
+
+

项目资源树

+ +
+ +
+
+
+
+
+
+
+

项目资源权限管理

+
+
+ + + + + + + + + + + + + + + + + + + + +
资源 + * + +
用户组 + + + + + + +
+ + +
+

+
+

+
+ +
+
用户 + + + + + + +
+ + +
+

+
+

+
+ +
+
权限 + +
+ +
+
+
+ + + + + + + + + + + + +
序号项目资源用户组/帐号权限删除
+
+
+
+
+
+
+
+
+
+
+
+ + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/svn/pj_create.jsp b/src/main/webapp/WEB-INF/views/svn/pj_create.jsp new file mode 100644 index 0000000..a324b40 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/svn/pj_create.jsp @@ -0,0 +1,87 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + + + + 创建项目 - ${applicationScope.sysName} + + + +
+
+ +
+
+
+
+
+
创建项目
+
+
+ +
+
+ +
+ +
+ +  项目名称请使用字母,用作资源目录名 +
+
+ +
+ +
+ +
+
+ + + +
+ +
+ + +  项目 Url 例如:svn://192.168.105.100/项目一 +
+
+ +
+ +
+ +  SVN项目的简单描述信息 +
+
+ +
+ +
+ + +
+
+
+
+
+
+
+
+
+
+
+ + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/svn/pj_gr_list.jsp b/src/main/webapp/WEB-INF/views/svn/pj_gr_list.jsp new file mode 100644 index 0000000..ca20900 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/svn/pj_gr_list.jsp @@ -0,0 +1,105 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + + + + 项目列表 - ${applicationScope.sysName} + + + +
+ +
+
+
+
+
+
+
项目用户组列表
+
+
+
+
+ + +
+
+
+ + + + + + + + + + + + + + +
序号项目用户组描述设置用户删除
+
+
+
+
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/svn/pj_gr_usr_list.jsp b/src/main/webapp/WEB-INF/views/svn/pj_gr_usr_list.jsp new file mode 100644 index 0000000..e4b7238 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/svn/pj_gr_usr_list.jsp @@ -0,0 +1,103 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + + + + 项目用户组管理 - ${applicationScope.sysName} + + + +
+ +
+
+
+
+
+
+
项目组用户列表
+
+
+
+
+
+
+
+

未入组账号

+
    + +
  • + ${item.usr}(${item.name}) + +
  • +
    +
+
+
+
+
+ + + + + +
+
+
+
+

已入组账号

+
+
    +
+
+
+
+
+
+
+
+ + + + + + + + + + + + + +
序号项目用户组账号删除
+
+
+
+
+
+
+
+
+ + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/svn/pj_list.jsp b/src/main/webapp/WEB-INF/views/svn/pj_list.jsp new file mode 100644 index 0000000..362dced --- /dev/null +++ b/src/main/webapp/WEB-INF/views/svn/pj_list.jsp @@ -0,0 +1,104 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + + + + 项目用户管理 - ${applicationScope.sysName} + + + +
+ +
+
+
+
+
+
+
SVN 项目列表
+
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
序号项目路径URL类型描述操作
未查询到相关数据
${v.index+1}${item.pj}${item.path}${item.url}${item.des} +
+ + + + +
+ <%--
+ + +
--%> +
+
+
+
+
+
+
+
+
+ + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/svn/pj_usr_list.jsp b/src/main/webapp/WEB-INF/views/svn/pj_usr_list.jsp new file mode 100644 index 0000000..b2c5931 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/svn/pj_usr_list.jsp @@ -0,0 +1,132 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + + + + 项目列表 - ${applicationScope.sysName} + + + +
+ +
+
+
+
+
+
+
项目用户列表
+
+
+
+
+ + +
+
+
+ + + + + + + + + + + + + + +
序号项目帐号姓名项目密码删除
+
+
+
+
+
+
+
+
+ + + + + + +<%----%> + <%--未查询到相关数据--%> +<%----%> +<%----%> + <%----%> + <%----%> + <%--${v.index+1}--%> + <%--${item.pj}--%> + <%--${item.path}--%> + <%--${item.url}--%> + <%----%> + <%--${item.des}--%> + <%----%> + <%----%> +<%----%> \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/usr/usr_auth.jsp b/src/main/webapp/WEB-INF/views/usr/usr_auth.jsp new file mode 100644 index 0000000..b0491b1 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/usr/usr_auth.jsp @@ -0,0 +1,70 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + + + + SVN资源管理平台 - 首页 + + + +
+
+ +
+
+
+
+
+
+
我的项目权限列表
+
+
+
+ + + + + + + + + + + + + + +
序号项目描述帐号资源权限
+
+
+
+
+
+
+
+
+
+ + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/usr/usr_list.jsp b/src/main/webapp/WEB-INF/views/usr/usr_list.jsp new file mode 100644 index 0000000..a896f31 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/usr/usr_list.jsp @@ -0,0 +1,152 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + + + + 用户列表 - ${applicationScope.sysName} + + + +
+ +
+
+
+
+
+
+
用户列表
+
+
+
+
+ +
+
+
+ + + + + + + + + + + + + + + +
序号用户名姓名密码角色查看操作
+
+
+
+
+
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/usr/usr_update_pswd.jsp b/src/main/webapp/WEB-INF/views/usr/usr_update_pswd.jsp new file mode 100644 index 0000000..17e0b74 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/usr/usr_update_pswd.jsp @@ -0,0 +1,78 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + + + + SVN资源管理平台 - 修改密码 + + + +
+
+ +
+
+
+
+
+
+
修改密码
+
+
+
+
+ +
+ +
+
+
+ +
+ + 新密码不能和老密码保持一致 +
+
+
+ +
+ +
+
+
+ +
+

更改密码后,本系统登录密码和所有SVN项目认证密码都会被更新

+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+ + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..8a10b5e --- /dev/null +++ b/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,56 @@ + + + kjjf-p2p + + + login.html + + + + setCharacterEncoding + org.springframework.web.filter.CharacterEncodingFilter + + encoding + UTF-8 + + + + setCharacterEncoding + /* + + + + springMVC + org.springframework.web.servlet.DispatcherServlet + + contextConfigLocation + classpath*:/springMVC.xml + + 1 + + + springMVC + / + + + + 30 + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/assets/admin/image/action_success.png b/src/main/webapp/assets/admin/image/action_success.png new file mode 100644 index 0000000..c8cf8fb Binary files /dev/null and b/src/main/webapp/assets/admin/image/action_success.png differ diff --git a/src/main/webapp/assets/admin/image/bg/1.jpg b/src/main/webapp/assets/admin/image/bg/1.jpg new file mode 100644 index 0000000..fb6f88e Binary files /dev/null and b/src/main/webapp/assets/admin/image/bg/1.jpg differ diff --git a/src/main/webapp/assets/admin/image/bg/2.jpg b/src/main/webapp/assets/admin/image/bg/2.jpg new file mode 100644 index 0000000..18f431a Binary files /dev/null and b/src/main/webapp/assets/admin/image/bg/2.jpg differ diff --git a/src/main/webapp/assets/admin/image/favicon.ico b/src/main/webapp/assets/admin/image/favicon.ico new file mode 100644 index 0000000..1f99cb0 Binary files /dev/null and b/src/main/webapp/assets/admin/image/favicon.ico differ diff --git a/src/main/webapp/assets/admin/image/login.png b/src/main/webapp/assets/admin/image/login.png new file mode 100644 index 0000000..7b5d506 Binary files /dev/null and b/src/main/webapp/assets/admin/image/login.png differ diff --git a/src/main/webapp/assets/admin/image/not-right.jpg b/src/main/webapp/assets/admin/image/not-right.jpg new file mode 100644 index 0000000..40fddd2 Binary files /dev/null and b/src/main/webapp/assets/admin/image/not-right.jpg differ diff --git a/src/main/webapp/assets/admin/image/validate/form-icon-small.png b/src/main/webapp/assets/admin/image/validate/form-icon-small.png new file mode 100644 index 0000000..0efc65c Binary files /dev/null and b/src/main/webapp/assets/admin/image/validate/form-icon-small.png differ diff --git a/src/main/webapp/assets/admin/image/validate/form-validate-icon.png b/src/main/webapp/assets/admin/image/validate/form-validate-icon.png new file mode 100644 index 0000000..c9c7fad Binary files /dev/null and b/src/main/webapp/assets/admin/image/validate/form-validate-icon.png differ diff --git a/src/main/webapp/assets/admin/image/validate/form-validate-icon22.png b/src/main/webapp/assets/admin/image/validate/form-validate-icon22.png new file mode 100644 index 0000000..a721bae Binary files /dev/null and b/src/main/webapp/assets/admin/image/validate/form-validate-icon22.png differ diff --git a/src/main/webapp/assets/admin/image/validate/infomation_18.png b/src/main/webapp/assets/admin/image/validate/infomation_18.png new file mode 100644 index 0000000..0953798 Binary files /dev/null and b/src/main/webapp/assets/admin/image/validate/infomation_18.png differ diff --git a/src/main/webapp/assets/admin/image/validate/infomation_24.png b/src/main/webapp/assets/admin/image/validate/infomation_24.png new file mode 100644 index 0000000..6a5463f Binary files /dev/null and b/src/main/webapp/assets/admin/image/validate/infomation_24.png differ diff --git a/src/main/webapp/assets/admin/image/validate/lodding.gif b/src/main/webapp/assets/admin/image/validate/lodding.gif new file mode 100644 index 0000000..5bb90fd Binary files /dev/null and b/src/main/webapp/assets/admin/image/validate/lodding.gif differ diff --git a/src/main/webapp/assets/admin/image/validate/success_32.png b/src/main/webapp/assets/admin/image/validate/success_32.png new file mode 100644 index 0000000..c8cf8fb Binary files /dev/null and b/src/main/webapp/assets/admin/image/validate/success_32.png differ diff --git a/src/main/webapp/assets/admin/image/validate/xubox_ico0.png b/src/main/webapp/assets/admin/image/validate/xubox_ico0.png new file mode 100644 index 0000000..7754a47 Binary files /dev/null and b/src/main/webapp/assets/admin/image/validate/xubox_ico0.png differ diff --git a/src/main/webapp/assets/admin/image/validate/xubox_loading2.gif b/src/main/webapp/assets/admin/image/validate/xubox_loading2.gif new file mode 100644 index 0000000..5bb90fd Binary files /dev/null and b/src/main/webapp/assets/admin/image/validate/xubox_loading2.gif differ diff --git a/src/main/webapp/assets/admin/script/modules/basic/add_user.js b/src/main/webapp/assets/admin/script/modules/basic/add_user.js new file mode 100644 index 0000000..bc2eae2 --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/basic/add_user.js @@ -0,0 +1,26 @@ +/** + * 添加用户 + * @author yuliang + * @version 1.0.0 + */ +define(function(require, exports, module){ + //引入模块 + require('$'); + var util = require('util'); + + function formSubmit(){ + var addUserForm = $('#addUserForm'); + $.post('saveUser.do',util.serializeObject(addUserForm),function(data){ + if(data.status){ + util.showMsg(data.info); + addUserForm.get(0).reset() + }else{ + util.showMsg(data.info, 3); + } + }); + return false; + }; + + window.formSubmit = formSubmit; + +}); \ No newline at end of file diff --git a/src/main/webapp/assets/admin/script/modules/basic/edit_password.js b/src/main/webapp/assets/admin/script/modules/basic/edit_password.js new file mode 100644 index 0000000..cc7776b --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/basic/edit_password.js @@ -0,0 +1,29 @@ +/** + * 用户修改密码 + * @author Hpboys + * @version 1.0.0 + */ +define(function(require, exports, module){ + //引入模块 + require('$'); + var util = require('util'); + var layer = require('layer'); + + function formSubmit(){ + var submitForm = $('#submitForm'); + var loadIndex = util.loading(); + $.post('updatePassword.do',util.serializeObject(submitForm),function(data){ + layer.close(loadIndex); + if(data.status){ + util.showMsg(data.info); + submitForm.get(0).reset(); + }else{ + util.showMsg(data.info,3); + } + }); + return false; + }; + + window.formSubmit = formSubmit; + +}); \ No newline at end of file diff --git a/src/main/webapp/assets/admin/script/modules/basic/login.js b/src/main/webapp/assets/admin/script/modules/basic/login.js new file mode 100644 index 0000000..1605aed --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/basic/login.js @@ -0,0 +1,38 @@ +/** + * 登录页面 + * @author Hpboys + * @version 1.0.0 + */ +define(function(require, exports, module){ + //引入模块 + require('$'); + var util = require('util'); + var layer = require('layer'); + + //全登陆不允许iframe嵌入 + if(window.top !== window.self){ window.top.location = window.location;} + + $(document).keydown(function(e) { + if (e.keyCode == 13) { + $('#submit').click(); + } + }); + + function loginSubmit(){ + var layIndex = util.loading(); + $.post('loginHandler',util.serializeObject($('#loginForm')),function(data){ + layer.close(layIndex); + if(data.status){ + $('#error').html('登录成功').slideDown(100); + setTimeout(function(){location.href = data.attr.url;},500); + }else{ + $('#error').html(''+data.info).slideDown(150); + $('#verify').val('').focus(); + } + }); + return false; + }; + + window.loginSubmit = loginSubmit; + +}); \ No newline at end of file diff --git a/src/main/webapp/assets/admin/script/modules/constant/constant.js b/src/main/webapp/assets/admin/script/modules/constant/constant.js new file mode 100644 index 0000000..6a58fc8 --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/constant/constant.js @@ -0,0 +1,11 @@ +/** + * 系统公用常量数据 + * @author Hpboys + * @version 1.0.1 + */ +define(function(require, exports, module){ + //用户状态 + exports.userStatus = {'0':'冻结','1':'正常'}; + //资源读写状态 + exports.resRightStatus = {'r':'可读','rw':'可读可写'}; +}); \ No newline at end of file diff --git a/src/main/webapp/assets/admin/script/modules/global_config.js b/src/main/webapp/assets/admin/script/modules/global_config.js new file mode 100644 index 0000000..0cfa248 --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/global_config.js @@ -0,0 +1,30 @@ +var global = {}; +//全局配置项 +global.config = { + // Sea.js 的基础路径 + base: location.origin+"/svnadmin/assets/admin/script/modules/", + // 变量配置 + vars: { + 'framePath': location.origin+"/svnadmin/assets/hui/js" + }, + // 别名配置 + alias: { + '$': 'libs/jquery/jquery-2.1.1.min.js', + 'util': 'libs/util.js', + 'bootstrap': 'libs/bootstrap/bootstrap.min.js', + 'kindeditor': 'libs/kindeditor/bootstrap.min.js', + 'layer': 'libs/layer/layer.min.js', //layer层综合插件 + 'input_vali_service': 'service/input_vali_service.js', //输入框验证插件 + 'service': 'service/service.js', //输入框验证插件 + 'page_service': 'service/page_service.js', //输入框验证插件 + 'template': 'libs/template/template.js', //模板引擎 + 'template_ext': 'libs/template/template_ext.js', //模板扩展Tag + 'my97date': 'libs/My97DatePicker/WdatePicker.js', //时间选择控件 + 'toastr': '{framePath}/plugins/toastr/toastr.min.js', //时间选择控件 + 'constant': 'constant/constant.js' //系统公用常量 + }, + // 文件编码 + charset: 'utf-8' + }; +// Set configuration +seajs.config(global.config); diff --git a/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/My97DatePicker.htm b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/My97DatePicker.htm new file mode 100644 index 0000000..82c5ca8 --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/My97DatePicker.htm @@ -0,0 +1,49 @@ + + + +My97DatePicker + + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/WdatePicker.js b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/WdatePicker.js new file mode 100644 index 0000000..3baa118 --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/WdatePicker.js @@ -0,0 +1,39 @@ +/* + * My97 DatePicker 4.72 Release + * License: http://www.my97.net/dp/license.asp + */ +var $dp,WdatePicker;(function(){var _={ +$wdate:true, +$dpPath:"", +$crossFrame:true, +doubleCalendar:false, +enableKeyboard:true, +enableInputMask:true, +autoUpdateOnChanged:null, +whichDayIsfirstWeek:4, +position:{}, +lang:"auto", +skin:"default", +dateFmt:"yyyy-MM-dd", +realDateFmt:"yyyy-MM-dd", +realTimeFmt:"HH:mm:ss", +realFullFmt:"%Date %Time", +minDate:"1900-01-01 00:00:00", +maxDate:"2099-12-31 23:59:59", +startDate:"", +alwaysUseStartDate:false, +yearOffset:1911, +firstDayOfWeek:0, +isShowWeek:false, +highLineWeekDay:true, +isShowClear:true, +isShowToday:true, +isShowOK:true, +isShowOthers:true, +readOnly:false, +errDealMode:0, +autoPickDate:null, +qsEnabled:true, +autoShowQS:false, + +specialDates:null,specialDays:null,disabledDates:null,disabledDays:null,opposite:false,onpicking:null,onpicked:null,onclearing:null,oncleared:null,ychanging:null,ychanged:null,Mchanging:null,Mchanged:null,dchanging:null,dchanged:null,Hchanging:null,Hchanged:null,mchanging:null,mchanged:null,schanging:null,schanged:null,eCont:null,vel:null,errMsg:"",quickSel:[],has:{}};WdatePicker=U;var X=window,O="document",J="documentElement",C="getElementsByTagName",V,A,T,I,b;switch(navigator.appName){case"Microsoft Internet Explorer":T=true;break;case"Opera":b=true;break;default:I=true;break}A=L();if(_.$wdate)M(A+"skin/WdatePicker.css");V=X;if(_.$crossFrame){try{while(V.parent&&V.parent[O]!=V[O]&&V.parent[O][C]("frameset").length==0)V=V.parent}catch(P){}}if(!V.$dp)V.$dp={ff:I,ie:T,opera:b,el:null,win:X,status:0,defMinDate:_.minDate,defMaxDate:_.maxDate,flatCfgs:[]};B();if($dp.status==0)Z(X,function(){U(null,true)});if(!X[O].docMD){E(X[O],"onmousedown",D);X[O].docMD=true}if(!V[O].docMD){E(V[O],"onmousedown",D);V[O].docMD=true}E(X,"onunload",function(){if($dp.dd)Q($dp.dd,"none")});function B(){V.$dp=V.$dp||{};obj={$:function($){return(typeof $=="string")?X[O].getElementById($):$},$D:function($,_){return this.$DV(this.$($).value,_)},$DV:function(_,$){if(_!=""){this.dt=$dp.cal.splitDate(_,$dp.cal.dateFmt);if($)for(var B in $)if(this.dt[B]===undefined)this.errMsg="invalid property:"+B;else{this.dt[B]+=$[B];if(B=="M"){var C=$["M"]>0?1:0,A=new Date(this.dt["y"],this.dt["M"],0).getDate();this.dt["d"]=Math.min(A+C,this.dt["d"])}}if(this.dt.refresh())return this.dt}return""},show:function(){var A=V[O].getElementsByTagName("div"),$=100000;for(var B=0;B$)$=_}this.dd.style.zIndex=$+2;Q(this.dd,"block")},hide:function(){Q(this.dd,"none")},attachEvent:E};for(var $ in obj)V.$dp[$]=obj[$];$dp=V.$dp;$dp.dd=V[O].getElementById("_my97DP")}function E(A,$,_){if(T)A.attachEvent($,_);else if(_){var B=$.replace(/on/,"");_._ieEmuEventHandler=function($){return _($)};A.addEventListener(B,_._ieEmuEventHandler,false)}}function L(){var _,A,$=X[O][C]("script");for(var B=0;B<$.length;B++){_=$[B].src.substring(0,$[B].src.toLowerCase().indexOf("wdatepicker.js"));A=_.lastIndexOf("/");if(A>0)_=_.substring(0,A+1);if(_)break}return _}function F(F){var E,C;if(F.substring(0,1)!="/"&&F.indexOf("://")==-1){E=V.location.href;C=location.href;if(E.indexOf("?")>-1)E=E.substring(0,E.indexOf("?"));if(C.indexOf("?")>-1)C=C.substring(0,C.indexOf("?"));var G,I,$="",D="",A="",J,H,B="";for(J=0;J_.scrollTop||A.scrollLeft>_.scrollLeft))?A:_;return{"top":B.scrollTop,"left":B.scrollLeft}}function D($){var _=$?($.srcElement||$.target):null;try{if($dp.cal&&!$dp.eCont&&$dp.dd&&_!=$dp.el&&$dp.dd.style.display=="block")$dp.cal.close()}catch($){}}function Y(){$dp.status=2;H()}function H(){if($dp.flatCfgs.length>0){var $=$dp.flatCfgs.shift();$.el={innerHTML:""};$.autoPickDate=true;$.qsEnabled=false;K($)}}var R,$;function U(J,C){$dp.win=X;B();J=J||{};if(C){if(!G()){$=$||setInterval(function(){if(V[O].readyState=="complete")clearInterval($);U(null,true)},50);return}if($dp.status==0){$dp.status=1;K({el:{innerHTML:""}},true)}else return}else if(J.eCont){J.eCont=$dp.$(J.eCont);$dp.flatCfgs.push(J);if($dp.status==2)H()}else{if($dp.status==0){U(null,true);return}if($dp.status!=2)return;var F=D();if(F){$dp.srcEl=F.srcElement||F.target;F.cancelBubble=true}$dp.el=J.el=$dp.$(J.el||$dp.srcEl);if(!$dp.el||$dp.el["My97Mark"]===true||$dp.el.disabled||($dp.el==$dp.el&&Q($dp.dd)!="none"&&$dp.dd.style.left!="-1970px")){$dp.el["My97Mark"]=false;return}K(J);if(F&&$dp.el.nodeType==1&&$dp.el["My97Mark"]===undefined){$dp.el["My97Mark"]=false;var _,A;if(F.type=="focus"){_="onclick";A="onfocus"}else{_="onfocus";A="onclick"}E($dp.el,_,$dp.el[A])}}function G(){if(T&&V!=X&&V[O].readyState!="complete")return false;return true}function D(){if(I){func=D.caller;while(func!=null){var $=func.arguments[0];if($&&($+"").indexOf("Event")>=0)return $;func=func.caller}return null}return event}}function S(_,$){return _.currentStyle?_.currentStyle[$]:document.defaultView.getComputedStyle(_,false)[$]}function Q(_,$){if(_)if($!=null)_.style.display=$;else return S(_,"display")}function K(H,$){for(var D in _)if(D.substring(0,1)!="$")$dp[D]=_[D];for(D in H)if($dp[D]!==undefined)$dp[D]=H[D];var E=$dp.el?$dp.el.nodeName:"INPUT";if($||$dp.eCont||new RegExp(/input|textarea|div|span|p|a/ig).test(E))$dp.elProp=E=="INPUT"?"value":"innerHTML";else return;if($dp.lang=="auto")$dp.lang=T?navigator.browserLanguage.toLowerCase():navigator.language.toLowerCase();if(!$dp.dd||$dp.eCont||($dp.lang&&$dp.realLang&&$dp.realLang.name!=$dp.lang&&$dp.getLangIndex&&$dp.getLangIndex($dp.lang)>=0)){if($dp.dd&&!$dp.eCont)V[O].body.removeChild($dp.dd);if(_.$dpPath=="")F(A);var B="";if($dp.eCont){$dp.eCont.innerHTML=B;Z($dp.eCont.childNodes[0],Y)}else{$dp.dd=V[O].createElement("DIV");$dp.dd.id="_my97DP";$dp.dd.style.cssText="position:absolute";$dp.dd.innerHTML=B;V[O].body.appendChild($dp.dd);Z($dp.dd.childNodes[0],Y);if($)$dp.dd.style.left=$dp.dd.style.top="-1970px";else{$dp.show();C()}}}else if($dp.cal){$dp.show();$dp.cal.init();if(!$dp.eCont)C()}function C(){var F=$dp.position.left,B=$dp.position.top,C=$dp.el;if(C!=$dp.srcEl&&(Q(C)=="none"||C.type=="hidden"))C=$dp.srcEl;var H=W(C),$=G(X),D=N(V),A=a(V),E=$dp.dd.offsetHeight,_=$dp.dd.offsetWidth;if(isNaN(B)){if(B=="above"||(B!="under"&&(($.topM+H.bottom+E>D.height)&&($.topM+H.top-E>0))))B=A.top+$.topM+H.top-E-2;else B=A.top+$.topM+Math.min(H.bottom,D.height-E)+2}else B+=A.top+$.topM;if(isNaN(F))F=A.left+Math.min($.leftM+H.left,D.width-_-5)-(T?2:0);else F+=A.left+$.leftM;$dp.dd.style.top=B+"px";$dp.dd.style.left=F+"px"}}})() \ No newline at end of file diff --git a/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/calendar.js b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/calendar.js new file mode 100644 index 0000000..46cc248 --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/calendar.js @@ -0,0 +1,5 @@ +/* + * My97 DatePicker 4.72 Release + * License: http://www.my97.net/dp/license.asp + */ +eval(function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1;};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p;}('o $c;k($5u){5Q.2X.7n("6G",l($){k(!$)h.25();t $});5Q.2X.7e("6w",l(){o $=h.6t;3i($.5M!=1)$=$.7g;t $});7f.2X.2I=l($,b){o A=$.1l(/6p/,"");b.5R=l($){6L.1Y=$;t b()};h.7t(A,b.5R,1m)}}l 5H(){$c=h;h.2Y=[];$d=1Q.7q("x");$d.1d="4d";$d.1L="<1v Y=3M><1v Y=3M><1x 2o=0 2m=0 2u=0><1j><18 7J=2><4h 1D=7L>&4B;<1v Y=7o 4b=2><1v 1g=\\":\\" Y=5P 5N><1v Y=5O 4b=2><1v 1g=\\":\\" Y=5P 5N><1v Y=5O 4b=2><18><1O 1D=7I><1j><18><1O 1D=7Q><1v Y=4e 1D=7G 3o=1O><1v Y=4e 1D=7z 3o=1O><1v Y=4e 1D=7E 3o=1O>";6M($d,l(){3t()});A();$f.1W=[1Q,$d.1M,$d.1t,$d.2V,$d.3r,$d.3I,$d.2S,$d.28,$d.1U];1b(o B=0;B<$f.1W.u;B++){o b=$f.1W[B];b.3q=B==$f.1W.u-1?$f.1W[1]:$f.1W[B+1];$f.2I(b,"4c",4R)}h.5F();$();4Q("y,M,H,m,s");$d.5S.1q=l(){4Z(1)};$d.5T.1q=l(){4Z(-1)};$d.4i.1q=l(){k($d.1E.1c.2h!="6K"){$c.4p();3w($d.1E)}q 1n($d.1E)};1Q.6N.4q($d);l A(){o b=$("a");1r=$("x"),1I=$("1v"),4g=$("1O"),5G=$("4h");$d.3y=b[0];$d.3V=b[1];$d.42=b[3];$d.3Y=b[2];$d.3K=1r[9];$d.1M=1I[0];$d.1t=1I[1];$d.4k=1r[0];$d.3T=1r[4];$d.2J=1r[6];$d.1E=1r[10];$d.2T=1r[11];$d.2H=1r[12];$d.6R=1r[13];$d.6Q=1r[14];$d.6O=1r[15];$d.4i=1r[16];$d.3z=1r[17];$d.2V=1I[2];$d.3r=1I[4];$d.3I=1I[6];$d.2S=1I[7];$d.28=1I[8];$d.1U=1I[9];$d.5S=4g[0];$d.5T=4g[1];$d.5L=5G[0];l $($){t $d.4o($)}}l $(){$d.3y.1q=l(){$1P=$1P<=0?$1P-1:-1;k($1P%5==0){$d.1t.2d();t}$d.1t.1g=$n.y-1;$d.1t.2n()};$d.3V.1q=l(){$n.2C("M",-1);$d.1M.2n()};$d.42.1q=l(){$n.2C("M",1);$d.1M.2n()};$d.3Y.1q=l(){$1P=$1P>=0?$1P+1:1;k($1P%5==0){$d.1t.2d();t}$d.1t.1g=$n.y+1;$d.1t.2n()}}}5H.2X={5F:l(){$1P=0;$f.5K=h;k($f.3N&&$f.z.3N!=1i){$f.z.3N=19;$f.z.4w()}$();h.5j();$n=h.6f=1a 1C();$1B=1a 1C();$1w=h.2w=1a 1C();h.1y=h.34($f.1y);h.2P=$f.2P==1i?($f.Z.2a&&$f.Z.2a?1m:19):$f.2P;$f.2z=$f.2z==1i?($f.4j&&$f.Z.d?1m:19):$f.2z;h.49=h.3f("8a");h.68=h.3f("8b");h.64=h.3f("89");h.5C=h.3f("87");h.1X=h.3P($f.1X,$f.1X!=$f.5D?$f.1S:$f.3j,$f.5D);h.1Z=h.3P($f.1Z,$f.1Z!=$f.5E?$f.1S:$f.3j,$f.5E);k(h.1X.2r(h.1Z)>0)$f.4f=$1k.7V;k(h.1R()){h.5J();h.3O=$f.z[$f.1z]}q h.3m(1m,2);4u($n);$d.5L.1L=$1k.7R;$d.2S.1g=$1k.7S;$d.28.1g=$1k.7Z;$d.1U.1g=$1k.80;$d.1U.1N=!$c.1u($1w);h.5c();h.6l();k($f.4f)7Y($f.4f);h.4C();k($f.z.5M==1&&$f.z["4m"]===4Y){$f.2I($f.z,"4c",4R);$f.2I($f.z,"2n",l(){k($f.1K.1c.2h=="2E"){$c.3Q();k($f.5K.3O!=$f.z[$f.1z]&&$f.z.75)4I($f.z,"73")}})}$c.1f=$f.z;3t();l $(){o b,$;1b(b=0;($=1Q.4o("71")[b]);b++)k($["72"].1o("1c")!=-1&&$["5I"]){$.1N=19;k($["5I"]==$f.79)$.1N=1m}}},5J:l(){o b=h.2L();k(b!=0){o $;k(b>0)$=h.1Z;q $=h.1X;k($f.Z.3u){$n.y=$.y;$n.M=$.M;$n.d=$.d}k($f.Z.2a){$n.H=$.H;$n.m=$.m;$n.s=$.s}}},3b:l(J,C,Q,E,B,G,F,K,L){o $;k(J&&J.1R)$=J;q{$=1a 1C();k(J!=""){C=C||$f.1y;o H,P=0,O,A=/3a|2l|36|y|2A|2Z|3U|M|1K|d|%2k|4J|H|4K|m|4G|s|3c|D|4H|W|w/g,b=C.35(A);A.2x=0;k(L)O=J.4O(/\\W+/);q{o D=0,M="^";3i((O=A.3h(C))!==1i){k(D>=0)M+=C.1F(D,O.3x);D=A.2x;2G(O[0]){1e"3a":M+="(\\\\d{4})";1h;1e"2l":M+="(\\\\d{3})";1h;1e"2A":1e"2Z":1e"3c":1e"D":M+="(\\\\D+)";1h;5X:M+="(\\\\d\\\\d?)";1h}}M+=".*$";O=1a 4r(M).3h(J);P=1}k(O){1b(H=0;H=0){A=A.1l(/%2k/g,"0");$.d=0;$.M=2e($.M)+1}$.20()}t $},1R:l(){o b,$;k($f.7b||($f.6b!=""&&$f.z[$f.1z]=="")){b=h.34($f.6b);$=$f.1S}q{b=$f.z[$f.1z];$=h.1y}$n.2c(h.3b(b,$));k(b!=""){o A=1;k($f.Z.3u&&!h.44($n)){$n.y=$1B.y;$n.M=$1B.M;$n.d=$1B.d;A=0}k($f.Z.2a&&!h.4a($n)){$n.H=$1B.H;$n.m=$1B.m;$n.s=$1B.s;A=0}t A&&h.1u($n)}t 1},44:l($){k($.y!=1i)$=3n($.y,4)+"-"+$.M+"-"+$.d;t $.35(/^((\\d{2}(([69][7p])|([6a][26]))[\\-\\/\\s]?((((0?[6h])|(1[6i]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[6g])))|(((0?[6e])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([69][74])|([6a][7u]))[\\-\\/\\s]?((((0?[6h])|(1[6i]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[6g])))|(((0?[6e])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$/)},4a:l($){k($.H!=1i)$=$.H+":"+$.m+":"+$.s;t $.35(/^([0-9]|([0-1][0-9])|([2][0-3])):([0-9]|([0-5][0-9])):([0-9]|([0-5][0-9]))$/)},2L:l($,A){$=$||$n;o b=$.2r(h.1X,A);k(b>0){b=$.2r(h.1Z,A);k(b<0)b=0}t b},1u:l($,A,B){A=A||$f.Z.3A;o b=h.2L($,A);k(b==0){b=1;k(A=="d"&&B==1i)B=2y.5Y((1a 1G($.y,$.M-1,$.d).21()-$f.41)%7);b=!h.67(B)&&!h.5Z($,A)}q b=0;t b},62:l(){o b=$f.z,A=h,$=$f.z[$f.1z];k($!=1i){k($!="")A.2w.2c(A.3b($,A.1y));k($==""||(A.44(A.2w)&&A.4a(A.2w)&&A.1u(A.2w))){k($!=""){A.6f.2c(A.2w);A.2p()}q A.3R("")}q t 1m}t 19},3Q:l($){3t();k(h.62()){h.3m(19);$f.1n()}q{k($){3k($);h.3m(1m,2)}q h.3m(1m);$f.24()}},3F:l(){o E,C,D,K,A,H=1a 2s(),F=$1k.5y,G=$f.41,I="",$="",b=1a 1C($n.y,$n.M,$n.d,0,0,0),J=b.y,B=b.M;A=1-1a 1G(J,B-1,1).21()+G;k(A>1)A-=7;H.a("<1x Y=5g 2U=3p% 2u=0 2o=0 2m=0>");H.a("<1j Y=5f 4A=5h>");k($f.61)H.a("<18>"+F[0]+"");1b(E=0;E<7;E++)H.a("<18>"+F[(G+E)%7+1]+"");H.a("");1b(E=1,C=A;E<7;E++){H.a("<1j>");1b(D=0;D<7;D++){b.1R(J,B,C++);b.20();k(b.M==B){K=19;k(b.2r($1w,"d")==0)I="7s";q k(b.2r($1B,"d")==0)I="7d";q I=($f.63&&(0==(G+D)%7||6==(G+D)%7)?"7k":"7l");$=($f.63&&(0==(G+D)%7||6==(G+D)%7)?"7i":"7j")}q k($f.5s){K=19;I="7c";$="8L"}q K=1m;k($f.61&&D==0&&(E<4||K))H.a("<18 Y=8H>"+4t(b,$f.41==0?1:0)+"");H.a("<18 ");k(K){k(h.1u(b,"d",D)){k(h.65(2y.5Y((1a 1G(b.y,b.M-1,b.d).21()-$f.41)%7))||h.66(b))I="8K";H.a("1q=\\"2O("+b.y+","+b.M+","+b.d+");\\" ");H.a("2t=\\"h.1d=\'"+$+"\'\\" ");H.a("2q=\\"h.1d=\'"+I+"\'\\" ")}q I="8M";H.a("Y="+I);H.a(">"+b.d+"")}q H.a(">")}H.a("")}H.a("");t H.j()},5Z:l(b,A){o $=h.47(b,h.49,A);t(h.49&&$f.5e)?!$:$},67:l($){t h.4x($,h.68)},66:l($){t h.47($,h.64)},65:l($){t h.4x($,h.5C)},47:l($,B,A){o b=A=="d"?$f.4l:$f.1S;t B?B.4P(h.3S(b,$)):0},4x:l(b,$){t $?$.4P(b):0},2R:l(p,c,r,e,2j){o s=1a 2s(),4y=2j?"r"+p:p;5b=$n[p];s.a("<1x 2o=0 2m=3 2u=0");1b(o i=0;i");1b(o j=0;j"+(p=="M"?$1k.29[$n[p]-1]:$n[p])+"")}s.a("")}s.a("");$n[p]=5b;t s.j()},4E:l($,b){k($){o A=$.8Q;k($6m)A=$.8V().2v;b.1c.2v=A}},8E:l($){h.4E($,$d.3T);$d.3T.1L=h.2R("M",2,6,"i+j*6+1",$==$d.2i)},4v:l(b,A){o $=1a 2s();A=2K(A,$n.y-5);$.a(h.2R("y",2,5,A+"+i+j*5",b==$d.2D));$.a("<1x 2o=0 2m=3 2u=0 4A=5h><1j><18 ");$.a(h.1X.y\\8l<18 Y=\'1A\' 2t=\\"h.1d=\'3e\'\\" 2q=\\"h.1d=\'1A\'\\" 3Z=\\"1n($d.2J);$d.1t.4w();\\">\\5l<18 ");$.a(h.1Z.y>A+10?"Y=\'1A\' 2t=\\"h.1d=\'3e\'\\" 2q=\\"h.1d=\'1A\'\\" 3Z=\'k(1Y.25)1Y.25();1Y.4S=19;$c.4v(0,"+(A+10)+")\'":"Y=\'4z\'");$.a(">\\8p");h.4E(b,$d.2J);$d.2J.1L=$.j()},3C:l(A,b,$){$d[A+"D"].1L=h.2R(A,6,b,$)},8n:l(){h.3C("H",4,"i * 6 + j")},8e:l(){h.3C("m",2,"i * 30 + j * 5")},8c:l(){h.3C("s",1,"j * 10")},4p:l(A){h.6F();o b=h.2Y,C=b.1c,$=1a 2s();$.a("<1x Y=5g 2U=3p% 2f=3p% 2u=0 2o=0 2m=0>");$.a("<1j Y=5f><18>"+$1k.8g+"");k(!A)$.a("\\5l");$.a("");1b(o B=0;B<18 1c=\'55-4A:2v\' 3d=\'3d\' Y=\'1A\' 2t=\\"h.1d=\'3e\'\\" 2q=\\"h.1d=\'1A\'\\" 1q=\\"");$.a("2O("+b[B].y+", "+b[B].M+", "+b[B].d+","+b[B].H+","+b[B].m+","+b[B].s+");\\">");$.a("&4B;"+h.3S(1i,b[B]));$.a("")}q $.a("<1j><18 Y=\'1A\'>&4B;");$.a("");$d.1E.1L=$.j()},5j:l(){$(/w/);$(/4H|W/);$(/3c|D/);$(/3a|2l|36|y/);$(/2A|2Z|3U|M/);$(/1K|d/);$(/4J|H/);$(/4K|m/);$(/4G|s/);$f.Z.3u=($f.Z.y||$f.Z.M||$f.Z.d)?19:1m;$f.Z.2a=($f.Z.H||$f.Z.m||$f.Z.s)?19:1m;$f.3j=$f.3j.1l(/%1G/,$f.4l).1l(/%8w/,$f.5d);k($f.Z.3u){k($f.Z.2a)$f.1S=$f.3j;q $f.1S=$f.4l}q $f.1S=$f.5d;l $(b){o $=(b+"").4T(1,2);$f.Z[$]=b.3h($f.1y)?($f.Z.3A=$,19):1m}},5c:l(){o $=0;$f.Z.y?($=1,24($d.1t,$d.3y,$d.3Y)):1n($d.1t,$d.3y,$d.3Y);$f.Z.M?($=1,24($d.1M,$d.3V,$d.42)):1n($d.1M,$d.3V,$d.42);$?24($d.4k):1n($d.4k);k($f.Z.2a){24($d.2H);3G($d.2V,$f.Z.H);3G($d.3r,$f.Z.m);3G($d.3I,$f.Z.s)}q 1n($d.2H);2M($d.2S,$f.5w);2M($d.28,$f.5x);2M($d.1U,$f.4j);2M($d.4i,!$f.5n&&$f.Z.d&&$f.8t);k($f.6v||!($f.5w||$f.5x||$f.4j))1n($d.3z);q 24($d.3z)},3m:l(B,D){o A=$f.z,b=$5u?"Y":"1d";k(B)C(A);q{k(D==1i)D=$f.8s;2G(D){1e 0:k(8B($1k.8C)){A[$f.1z]=h.3O;C(A)}q $(A);1h;1e 1:A[$f.1z]=h.3O;C(A);1h;1e 2:$(A);1h}}l C(A){o B=A.1d;k(B){o $=B.1l(/5B/g,"");k(B!=$)A.5A(b,$)}}l $($){$.5A(b,$.1d+" 5B")}},1V:l(D,b,$){$=$||$1w;o H,C=[D+D,D],E,A=$[D],F=l($){t 3n(A,$.u)};2G(D){1e"w":A=21($);1h;1e"D":o G=21($)+1;F=l($){t $.u==2?$1k.8A[G]:$1k.5y[G]};1h;1e"W":A=4t($);1h;1e"y":C=["3a","2l","36","y"];b=b||C[0];F=l(b){t 3n((b.u<4)?(b.u<3?$.y%3p:($.y+5z-$f.5p)%8x):A,b.u)};1h;1e"M":C=["2A","2Z","3U","M"];F=l($){t($.u==4)?$1k.5m[A-1]:($.u==3)?$1k.29[A-1]:3n(A,$.u)};1h}b=b||D+D;k("2N".1o(D)>-1&&D!="y"&&!$f.Z[D])k("8h".1o(D)>-1)A=0;q A=1;o B=[];1b(H=0;H=0){B[H]=F(E);b=b.1l(E,"{"+H+"}")}}1b(H=0;H=0){o A=1a 1C();A.2c($);A.d=0;A.M=2e(A.M)+1;A.20();b=b.1l(/%2k/g,A.d)}o B="8d";1b(o D=0;D<1j><18 5q=5r>");$.a(h.3F());$.a("<18 5q=5r>");$n.2C("M",1);$.a(h.3F());$d.2i=$d.1M.5o(19);$d.2D=$d.1t.5o(19);$d.3K.4q($d.2i);$d.3K.4q($d.2D);$d.2i.1g=$1k.29[$n.M-1];$d.2i["3v"]=$n.M;$d.2D.1g=$n.y;4Q("6H,6E");$d.2i.1d=$d.2D.1d="3M";$n.2C("M",-1);$.a("");$d.2T.1L=$.j()}q{$d.1d="4d";$d.2T.1L=h.3F()}k(!$f.Z.d||$f.8J){h.4p(19);3w($d.1E)}q 1n($d.1E);h.6P()},6P:l(){o b=8W.1Q.4o("8k");1b(o C=0;C=B){A+=B;$d.1c.2f=A}q $d.1c.2f=$;b[C].1c.2f=2y.5v(A,$d.3l)+"6s"}}$d.1E.1c.2U=$d.2T.6q;$d.1E.1c.2f=$d.2T.3l},4W:l(){$n.d=2y.8D(1a 1G($n.y,$n.M,0).2F(),$n.d);$1w.2c($n);h.2p();k(!$f.6v)k(h.1u($n)){4n();1n($f.1K)}k($f.6u)2g("6u")},6l:l(){$d.2S.1q=l(){k(!2g("8q")){$f.z[$f.1z]="";$c.3R("");4n();1n($f.1K);k($f.6n)2g("6n")}};$d.1U.1q=l(){2O()};k(h.1u($1B)){$d.28.1N=1m;$d.28.1q=l(){$n.2c($1B);2O()}}q $d.28.1N=19},6F:l(){o H,G,A,F,C=[],$=5,E=$f.6I.u,b=$f.Z.3A;k(E>$)E=$;q k(b=="m"||b=="s")C=[-60,-30,0,30,60,-15,15,-45,45];q 1b(H=0;H<$;H++)C[H]=$n[b]-2+H;1b(H=G=0;H=0)1H=43(1H,0,59);k($1w[p]!=1H&&!2g(p+"7U")){o 6o="1T(\\""+p+"\\","+1H+")",3B=$c.2L();k(3B==0)2W(6o);q k(3B<0)4D($c.1X);q k(3B>0)4D($c.1Z);$d.1U.1N=!$c.1u($1w);k("7C".1o(p)>=0)$c.4C();2g(p+"7D")}l 4D($){4u($c.1u($)?$:$1w)}}l 4u($){1T("y",$.y);1T("M",$.M);1T("d",$.d);1T("H",$.H);1T("m",$.m);1T("s",$.s)}l 2O(F,B,b,D,C,A){o $=1a 1C($n.y,$n.M,$n.d,$n.H,$n.m,$n.s);$n.1R(F,B,b,D,C,A);k(!2g("7H")){o E=$.y==F&&$.M==B&&$.d==b;k(!E&&2Q.u!=0){c("y",F);c("M",B);c("d",b);$c.1f=$f.z;k($f.2z)$c.2p()}k($c.2P||E||2Q.u==0)$c.4W()}q $n=$}l 2g($){o b;k($f[$])b=$f[$].4V($f.z,$f);t b}l 1T(b,$){k($==1i)$=$n[b];$1w[b]=$n[b]=$;k("7K".1o(b)>=0)$d[b+"I"].1g=$;k(b=="M"){$d.1M["3v"]=$;$d.1M.1g=$1k.29[$-1]}}l 43(b,$,A){k(b<$)b=$;q k(b>A)b=A;t b}l 6M($,b){$.2I("4c",l(){o $=1Y,A=($.4M==4Y)?$.4F:$.4M;k(A==9)b()})}l 3n($,b){$=$+"";3i($.u=0?C:5;1b(o D=0;D<=C;D++){B=A.1J(D);b=h[B]-$[B];k(b>0)t 1;q k(b<0)t-1}t 0},20:l(){o $=1a 1G(h.y,h.M-1,h.d,h.H,h.m,h.s);h.y=$.52();h.M=$.5a()+1;h.d=$.2F();h.H=$.54();h.m=$.53();h.s=$.56();t!6j(h.y)},2C:l(b,$){k("2N".1o(b)>=0){o A=h.d;k(b=="M")h.d=1;h[b]+=$;h.20();h.d=A}}};l 2e($){t 7F($,10)}l 3E($,b){t 2K(2e($),b)}l 1p($,A,b){t 3E($,2K(A,b))}l 2K($,b){t $==1i||6j($)?b:$}l 4I(A,$){k($6m)A.4I("6p"+$);q{o b=1Q.82("88");b.7W($,19,19);A.7X(b)}}l 3J($){o A,B,b="y,M,H,m,s,6E,6H".4O(",");1b(B=0;B=0?6B(v):$n[p];k(p=="y"){2j=h==$d.2D;k(2j&&$n.M==12)$n.y-=1}q k(p=="M"){2j=h==$d.2i;k(2j){51=$1k.29[$n[p]-1];k(6C==12)$n.y+=1;$n.2C("M",-1)}k($1w.M==$n.M)h.1g=51||$1k.29[$n[p]-1];k(($1w.y!=$n.y))c("y",$n.y)}2W("c(\\""+p+"\\","+$n[p]+")");k(6y!==19){k(p=="y"||p=="M")h.1d="3M";1n($d[p+"D"])}k($f.2z)$c.2p()}l 3k($){k($.25){$.25();$.8i()}q{$.4S=19;$.6G=1m}k($5t)$.4F=0}l 4Q($){o A=$.4O(",");1b(o B=0;B=8m&&Q<=8U)Q-=48;k($f.8I&&58){k(!H.3q){H.3q=$f.1W[1];$c.1f=$f.z}k(H==$f.z)$c.1f=$f.z;k(Q==27)k(H==$f.z){$c.3Q();t}q $f.z.2d();k(Q>=37&&Q<=40){o U;k($c.1f==$f.z||$c.1f==$d.1U)k($f.Z.d){U="d";k(Q==38)$n[U]-=7;q k(Q==39)$n[U]+=1;q k(Q==37)$n[U]-=1;q $n[U]+=7;$n.20();c("y",$n["y"]);c("M",$n["M"]);c("d",$n[U]);3k(M);t}q{U=$f.Z.3A;$d[U+"I"].2d()}U=U||3J($c.1f);k(U){k(Q==38||Q==39)$n[U]+=1;q $n[U]-=1;$n.20();$c.1f.1g=$n[U];3L.4V($c.1f,19);$c.1f.4U()}}q k(Q==9){o D=H.3q;1b(o R=0;R<$f.1W.u;R++)k(D.1N==19||D.3l==0)D=D.3q;q 1h;k($c.1f!=D){$c.1f=D;D.2d()}}q k(Q==13){3L.4V($c.1f);k($c.1f.3o=="1O")$c.1f.8P();q $c.4W();$c.1f=$f.z}}q k(Q==9&&H==$f.z)$c.3Q();k($f.8S&&!$5t&&!$f.3N&&$c.1f==$f.z&&(Q>=48&&Q<=57)){o T=$f.z,S=T.1g,F=E(T),I={22:"",1s:[]},R=0,K,N=0,X=0,O=0,J,b=/3a|2l|36|y|3U|M|1K|d|%2k|4J|H|4K|m|4G|s|4H|W|w/g,L=$f.1y.35(b),B,A,$,V,W,G,J=0;k(S!=""){O=S.35(/[0-9]/g);O=O==1i?0:O.u;1b(R=0;R=0?1:0;k(O==1&&F>=S.u)F=S.u-1}S=S.1F(0,F)+8r.8v(Q)+S.1F(F+O);F++;1b(R=0;R=0){S+=$f.1y.1F(N,X);k(F>=N+J&&F<=X+J)F+=X-N}N=b.2x;G=N-X;B=I.22.1F(0,G);A=K[0].1J(0);$=2e(B.1J(0));k(I.22.u>1){V=I.22.1J(1);W=$*10+2e(V)}q{V="";W=$}k(I.1s[X+1]||A=="M"&&W>12||A=="d"&&W>31||A=="H"&&W>23||"5k".1o(A)>=0&&W>59){k(K[0].u==2)B="0"+$;q B=$;F++}q k(G==1){B=W;G++;J++}S+=B;I.22=I.22.1F(G);k(I.22=="")1h}T.1g=S;P(T,F);3k(M)}k(58&&$c.1f!=$f.z&&!((Q>=48&&Q<=57)||Q==8||Q==46))3k(M);l E(A){o b=0;k($f.4N.1Q.6d){o B=$f.4N.1Q.6d.6U(),$=B.55.u;B.5V("4X",-A.1g.u);b=B.55.u-$}q k(A.4L||A.4L=="0")b=A.4L;t b}l P(b,A){k(b.5U){b.2d();b.5U(A,A)}q k(b.5W){o $=b.5W();$.7w(19);$.7y("4X",A);$.5V("4X",A);$.4U()}}}',62,555,'|||||||||||_||||dp||this|||if|function||dt|var||else|||return|length|||div||el|||||||||||||||||||||||||class|has|||||||||td|true|new|for|style|className|case|currFocus|value|break|null|tr|lang|replace|false|hide|indexOf|pInt3|onclick|divs|arr|yI|checkValid|input|sdt|table|dateFmt|elProp|menu|tdt|DPDate|id|qsDivSel|substring|Date|pv|ipts|charAt|dd|innerHTML|MI|disabled|button|ny|document|loadDate|realFmt|sv|okI|getP|focusArr|minDate|event|maxDate|refresh|getDay|str||show|preventDefault|||todayI|aMonStr|st|9700|loadFromDate|focus|pInt|height|callFunc|display|rMI|isR|ld|yyy|cellpadding|onblur|cellspacing|update|onmouseout|compareWith|sb|onmouseover|border|left|date|lastIndex|Math|autoUpdateOnChanged|MMMM|tmpEval|attr|ryI|none|getDate|switch|tDiv|attachEvent|yD|rtn|checkRange|shorH|yMdHms|day_Click|autoPickDate|arguments|_f|clearI|dDiv|width|HI|eval|prototype|QS|MMM||||menuSel|doExp|match|yy||||yyyy|splitDate|DD|nowrap|menuOn|_initRe|float|exec|while|realFullFmt|_cancelKey|offsetHeight|mark|doStr|type|100|nextCtrl|mI|setDisp|hideSel|sd|realValue|showB|index|navLeftImg|bDiv|minUnit|rv|_fHMS|ps|pInt2|_fd|disHMS|navImg|sI|_foundInput|rMD|_blur|yminput|readOnly|oldValue|doCustomDate|close|setRealValue|getDateStr|MD|MM|leftImg|href|toLowerCase|navRightImg|onmousedown||firstDayOfWeek|rightImg|makeInRange|isDate|||testDate||ddateRe|isTime|maxlength|onkeydown|WdateDiv|dpButton|errMsg|btns|span|qsDiv|isShowOK|titleDiv|realDateFmt|My97Mark|elFocus|getElementsByTagName|_fillQS|appendChild|RegExp|getNewDateStr|getWeek|_setAll|_fy|blur|testDay|fp|invalidMenu|align|nbsp|draw|_setFrom|_fMyPos|keyCode|ss|WW|fireEvent|HH|mm|selectionStart|which|win|split|test|_inputBindEvent|_tab|cancelBubble|slice|select|call|pickDate|character|undefined|updownEvent||mStr|getFullYear|getMinutes|getHours|text|getSeconds||isShow||getMonth|bak|initShowAndHide|realTimeFmt|opposite|MTitle|WdayTable|center|right|_dealFmt|ms|xd7|aLongMonStr|doubleCalendar|cloneNode|yearOffset|valign|top|isShowOthers|OPERA|FF|max|isShowClear|isShowToday|aWeekStr|2000|setAttribute|WdateFmtErr|sdayRe|defMinDate|defMaxDate|init|spans|My97DP|title|_makeDateInRange|cal|timeSpan|nodeType|readonly|tE|tm|Event|_ieEmuEventHandler|upButton|downButton|setSelectionRange|moveStart|createTextRange|default|abs|testDisDate||isShowWeek|checkAndUpdate|highLineWeekDay|sdateRe|testSpeDay|testSpeDate|testDisDay|ddayRe|02468|13579|startDate|re|selection|469|newdate|01|13578|02|isNaN|_focus|initBtn|IE|oncleared|func|on|offsetWidth|coverDate|px|target|onpicked|eCont|srcElement|yminputfocus|showDiv|setDate|hidden|Number|oldv|nodeName|ry|initQS|returnValue|rM|quickSel|valueOf|block|window|attachTabEvent|body|sD|autoSize|mD|HD|Function|86400000|createRange|vel|NavImgll|round|dpTitle|typeof|object|link|rel|change|1235679|onchange|NavImgl|substr|1900|skin|MMenu|alwaysUseStartDate|WotherDay|Wtoday|__defineGetter__|HTMLElement|parentNode|Array|WwdayOn|WdayOn|Wwday|Wday|setMonth|__defineSetter__|tB|048|createElement|join|Wselday|addEventListener|01345789|whichDayIsfirstWeek|collapse|dpTime|moveEnd|dpTodayInput|hhMenu|overflow|yMd|changed|dpOkInput|parseInt|dpClearInput|onpicking|dpTimeUp|rowspan|yHms|dpTimeStr|mmMenu|dpControl|dpQS|ssMenu|dpTimeDown|timeStr|clearStr|00|changing|err_1|initEvent|dispatchEvent|alert|todayStr|okStr|YMenu|createEvent|NavImgrr|NavImgr|absolute|position|specialDays|HTMLEvents|specialDates|disabledDates|disabledDays|_fs|ydHmswW|_fm|scrollHeight|quickStr|Hms|stopPropagation|contentWindow|iframe|u2190|96|_fH|getNewP|u2192|onclearing|String|errDealMode|qsEnabled|onfocus|fromCharCode|Time|1000|pointer|cursor|aLongWeekStr|confirm|errAlertMsg|min|_fM|try|textarea|Wweek|enableKeyboard|autoShowQS|WspecialDay|WotherDayOn|WinvalidDay|srcEl|catch|click|offsetLeft|WdayTable2|enableInputMask|WdateDiv2|105|getBoundingClientRect|parent'.split('|'),0,{})) \ No newline at end of file diff --git a/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/config.js b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/config.js new file mode 100644 index 0000000..20db8dd --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/config.js @@ -0,0 +1,12 @@ +var langList = +[ + {name:'en', charset:'UTF-8'}, + {name:'zh-cn', charset:'UTF-8'}, + {name:'zh-tw', charset:'UTF-8'} +]; + +var skinList = +[ + {name:'default', charset:'UTF-8'}, + {name:'whyGreen', charset:'UTF-8'} +]; \ No newline at end of file diff --git a/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/lang/en.js b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/lang/en.js new file mode 100644 index 0000000..3159885 --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/lang/en.js @@ -0,0 +1,14 @@ +var $lang={ +errAlertMsg: "Invalid date or the date out of range,redo or not?", +aWeekStr: ["wk", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], +aLongWeekStr:["wk","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"], +aMonStr: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], +aLongMonStr: ["January","February","March","April","May","June","July","August","September","October","November","December"], +clearStr: "Clear", +todayStr: "Today", +okStr: "OK", +updateStr: "OK", +timeStr: "Time", +quickStr: "Quick Selection", +err_1: 'MinDate Cannot be bigger than MaxDate!' +} \ No newline at end of file diff --git a/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/lang/zh-cn.js b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/lang/zh-cn.js new file mode 100644 index 0000000..70e5e4f --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/lang/zh-cn.js @@ -0,0 +1,14 @@ +var $lang={ +errAlertMsg: "\u4E0D\u5408\u6CD5\u7684\u65E5\u671F\u683C\u5F0F\u6216\u8005\u65E5\u671F\u8D85\u51FA\u9650\u5B9A\u8303\u56F4,\u9700\u8981\u64A4\u9500\u5417?", +aWeekStr: ["\u5468","\u65E5","\u4E00","\u4E8C","\u4E09","\u56DB","\u4E94","\u516D"], +aLongWeekStr:["\u5468","\u661F\u671F\u65E5","\u661F\u671F\u4E00","\u661F\u671F\u4E8C","\u661F\u671F\u4E09","\u661F\u671F\u56DB","\u661F\u671F\u4E94","\u661F\u671F\u516D"], +aMonStr: ["\u4E00\u6708","\u4E8C\u6708","\u4E09\u6708","\u56DB\u6708","\u4E94\u6708","\u516D\u6708","\u4E03\u6708","\u516B\u6708","\u4E5D\u6708","\u5341\u6708","\u5341\u4E00","\u5341\u4E8C"], +aLongMonStr: ["\u4E00\u6708","\u4E8C\u6708","\u4E09\u6708","\u56DB\u6708","\u4E94\u6708","\u516D\u6708","\u4E03\u6708","\u516B\u6708","\u4E5D\u6708","\u5341\u6708","\u5341\u4E00\u6708","\u5341\u4E8C\u6708"], +clearStr: "\u6E05\u7A7A", +todayStr: "\u4ECA\u5929", +okStr: "\u786E\u5B9A", +updateStr: "\u786E\u5B9A", +timeStr: "\u65F6\u95F4", +quickStr: "\u5FEB\u901F\u9009\u62E9", +err_1: '\u6700\u5C0F\u65E5\u671F\u4E0D\u80FD\u5927\u4E8E\u6700\u5927\u65E5\u671F!' +} \ No newline at end of file diff --git a/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/lang/zh-tw.js b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/lang/zh-tw.js new file mode 100644 index 0000000..b92e0ee --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/lang/zh-tw.js @@ -0,0 +1,14 @@ +var $lang={ +errAlertMsg: "\u4E0D\u5408\u6CD5\u7684\u65E5\u671F\u683C\u5F0F\u6216\u8005\u65E5\u671F\u8D85\u51FA\u9650\u5B9A\u7BC4\u570D,\u9700\u8981\u64A4\u92B7\u55CE?", +aWeekStr: ["\u5468","\u65E5","\u4E00","\u4E8C","\u4E09","\u56DB","\u4E94","\u516D"], +aLongWeekStr:["\u5468","\u661F\u671F\u65E5","\u661F\u671F\u4E00","\u661F\u671F\u4E8C","\u661F\u671F\u4E09","\u661F\u671F\u56DB","\u661F\u671F\u4E94","\u661F\u671F\u516D"], +aMonStr: ["\u4E00\u6708","\u4E8C\u6708","\u4E09\u6708","\u56DB\u6708","\u4E94\u6708","\u516D\u6708","\u4E03\u6708","\u516B\u6708","\u4E5D\u6708","\u5341\u6708","\u5341\u4E00","\u5341\u4E8C"], +aLongMonStr: ["\u4E00\u6708","\u4E8C\u6708","\u4E09\u6708","\u56DB\u6708","\u4E94\u6708","\u516D\u6708","\u4E03\u6708","\u516B\u6708","\u4E5D\u6708","\u5341\u6708","\u5341\u4E00\u6708","\u5341\u4E8C\u6708"], +clearStr: "\u6E05\u7A7A", +todayStr: "\u4ECA\u5929", +okStr: "\u78BA\u5B9A", +updateStr: "\u78BA\u5B9A", +timeStr: "\u6642\u9593", +quickStr: "\u5FEB\u901F\u9078\u64C7", +err_1: '\u6700\u5C0F\u65E5\u671F\u4E0D\u80FD\u5927\u65BC\u6700\u5927\u65E5\u671F!' +} \ No newline at end of file diff --git a/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/WdatePicker.css b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/WdatePicker.css new file mode 100644 index 0000000..9c8fd2c --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/WdatePicker.css @@ -0,0 +1,10 @@ +.Wdate { +/* border: #999 1px solid; */ +/* height: 20px; */ + background: #fff url(datePicker.gif) no-repeat right; +} + +.WdateFmtErr { + font-weight: bold; + color: red; +} \ No newline at end of file diff --git a/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/datePicker.gif b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/datePicker.gif new file mode 100644 index 0000000..d6bf40c Binary files /dev/null and b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/datePicker.gif differ diff --git a/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/default/datepicker.css b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/default/datepicker.css new file mode 100644 index 0000000..17dff17 --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/default/datepicker.css @@ -0,0 +1,258 @@ +/* + * My97 DatePicker 4.7 + */ +.WdateDiv { + width: 180px; + background-color: #FFFFFF; + border: #bbb 1px solid; + padding: 2px; +} + +.WdateDiv2 { + width: 360px; +} + +.WdateDiv * { + font-size: 9pt; +} + +.WdateDiv .NavImg a { + display: block; + cursor: pointer; + height: 16px; + width: 16px; +} + +.WdateDiv .NavImgll a { + float: left; + background: transparent url(img.gif) no-repeat scroll 0 0; +} + +.WdateDiv .NavImgl a { + float: left; + background: transparent url(img.gif) no-repeat scroll -16px 0; +} + +.WdateDiv .NavImgr a { + float: right; + background: transparent url(img.gif) no-repeat scroll -32px 0; +} + +.WdateDiv .NavImgrr a { + float: right; + background: transparent url(img.gif) no-repeat scroll -48px 0; +} + +.WdateDiv #dpTitle { + height: 24px; + margin-bottom: 2px; + padding: 1px; +} + +.WdateDiv .yminput { + margin-top: 2px; + text-align: center; + height: 20px; + border: 0px; + width: 50px; + cursor: pointer; +} + +.WdateDiv .yminputfocus { + margin-top: 2px; + text-align: center; + font-weight: bold; + height: 20px; + color: blue; + border: #ccc 1px solid; + width: 50px; +} + +.WdateDiv .menuSel { + z-index: 1; + position: absolute; + background-color: #FFFFFF; + border: #ccc 1px solid; + display: none; +} + +.WdateDiv .menu { + cursor: pointer; + background-color: #fff; +} + +.WdateDiv .menuOn { + cursor: pointer; + background-color: #BEEBEE; +} + +.WdateDiv .invalidMenu { + color: #aaa; +} + +.WdateDiv .YMenu { + margin-top: 20px; +} + +.WdateDiv .MMenu { + margin-top: 20px; + *width: 62px; +} + +.WdateDiv .hhMenu { + margin-top: -90px; + margin-left: 26px; +} + +.WdateDiv .mmMenu { + margin-top: -46px; + margin-left: 26px; +} + +.WdateDiv .ssMenu { + margin-top: -24px; + margin-left: 26px; +} + +.WdateDiv .Wweek { + text-align: center; + background: #DAF3F5; + border-right: #BDEBEE 1px solid; +} + +.WdateDiv .MTitle { + background-color: #BDEBEE; +} + +.WdateDiv .WdayTable2 { + border-collapse: collapse; + border: #c5d9e8 1px solid; +} + +.WdateDiv .WdayTable2 table { + border: 0; +} + +.WdateDiv .WdayTable { + line-height: 20px; + border: #c5d9e8 1px solid; +} + +.WdateDiv .WdayTable td { + text-align: center; +} + +.WdateDiv .Wday { + cursor: pointer; +} + +.WdateDiv .WdayOn { + cursor: pointer; + background-color: #C0EBEF; +} + +.WdateDiv .Wwday { + cursor: pointer; + color: #FF2F2F; +} + +.WdateDiv .WwdayOn { + cursor: pointer; + color: #000; + background-color: #C0EBEF; +} + +.WdateDiv .Wtoday { + cursor: pointer; + color: blue; +} + +.WdateDiv .Wselday { + background-color: #A9E4E9; +} + +.WdateDiv .WspecialDay { + background-color: #66F4DF; +} + +.WdateDiv .WotherDay { + cursor: pointer; + color: #6A6AFF; +} + +.WdateDiv .WotherDayOn { + cursor: pointer; + background-color: #C0EBEF; +} + +.WdateDiv .WinvalidDay { + color: #aaa; +} + +.WdateDiv #dpTime { + float: left; + margin-top: 3px; + margin-right: 30px; +} + +.WdateDiv #dpTime #dpTimeStr { + margin-left: 1px; +} + +.WdateDiv #dpTime input { + width: 18px; + height: 20px; + text-align: center; + border: #ccc 1px solid; +} + +.WdateDiv #dpTime .tB { + border-right: 0px; +} + +.WdateDiv #dpTime .tE { + border-left: 0; + border-right: 0; +} + +.WdateDiv #dpTime .tm { + width: 7px; + border-left: 0; + border-right: 0; +} + +.WdateDiv #dpTime #dpTimeUp { + height: 10px; + width: 13px; + border: 0px; + background: url(img.gif) no-repeat -32px -16px; +} + +.WdateDiv #dpTime #dpTimeDown { + height: 10px; + width: 13px; + border: 0px; + background: url(img.gif) no-repeat -48px -16px; +} + +.WdateDiv #dpQS { + float: left; + margin-right: 3px; + margin-top: 3px; + background: url(img.gif) no-repeat 0px -16px; + width: 20px; + height: 20px; + cursor: pointer; +} + +.WdateDiv #dpControl { + text-align: right; +} + +.WdateDiv .dpButton { + height: 20px; + width: 45px; + border: #ccc 1px solid; + margin-top: 2px; + margin-right: 1px; +} \ No newline at end of file diff --git a/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/default/img.gif b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/default/img.gif new file mode 100644 index 0000000..053205d Binary files /dev/null and b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/default/img.gif differ diff --git a/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/whyGreen/bg.jpg b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/whyGreen/bg.jpg new file mode 100644 index 0000000..75516a6 Binary files /dev/null and b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/whyGreen/bg.jpg differ diff --git a/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/whyGreen/datepicker.css b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/whyGreen/datepicker.css new file mode 100644 index 0000000..c50fd7c --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/whyGreen/datepicker.css @@ -0,0 +1,270 @@ +/* + * My97 DatePicker 4.7 Skin:whyGreen + */ +.WdateDiv { + width: 180px; + background-color: #fff; + border: #C5E1E4 1px solid; + padding: 2px; +} + +.WdateDiv2 { + width: 360px; +} + +.WdateDiv * { + font-size: 9pt; +} + +.WdateDiv .NavImg a { + cursor: pointer; + display: block; + width: 16px; + height: 16px; + margin-top: 1px; +} + +.WdateDiv .NavImgll a { + float: left; + background: url(img.gif) no-repeat; +} + +.WdateDiv .NavImgl a { + float: left; + background: url(img.gif) no-repeat -16px 0px; +} + +.WdateDiv .NavImgr a { + float: right; + background: url(img.gif) no-repeat -32px 0px; +} + +.WdateDiv .NavImgrr a { + float: right; + background: url(img.gif) no-repeat -48px 0px; +} + +.WdateDiv #dpTitle { + height: 24px; + padding: 1px; + border: #c5d9e8 1px solid; + background: url(bg.jpg); + margin-bottom: 2px; +} + +.WdateDiv .yminput { + margin-top: 2px; + text-align: center; + border: 0px; + height: 20px; + width: 50px; + color: #034c50; + background-color: transparent; + cursor: pointer; +} + +.WdateDiv .yminputfocus { + margin-top: 2px; + text-align: center; + border: #939393 1px solid; + font-weight: bold; + color: #034c50; + height: 20px; + width: 50px; +} + +.WdateDiv .menuSel { + z-index: 1; + position: absolute; + background-color: #FFFFFF; + border: #A3C6C8 1px solid; + display: none; +} + +.WdateDiv .menu { + cursor: pointer; + background-color: #fff; + color: #11777C; +} + +.WdateDiv .menuOn { + cursor: pointer; + background-color: #BEEBEE; +} + +.WdateDiv .invalidMenu { + color: #aaa; +} + +.WdateDiv .YMenu { + margin-top: 20px; +} + +.WdateDiv .MMenu { + margin-top: 20px; + *width: 62px; +} + +.WdateDiv .hhMenu { + margin-top: -90px; + margin-left: 26px; +} + +.WdateDiv .mmMenu { + margin-top: -46px; + margin-left: 26px; +} + +.WdateDiv .ssMenu { + margin-top: -24px; + margin-left: 26px; +} + +.WdateDiv .Wweek { + text-align: center; + background: #DAF3F5; + border-right: #BDEBEE 1px solid; +} + +.WdateDiv .MTitle { + color: #13777e; + background-color: #bdebee; +} + +.WdateDiv .WdayTable2 { + border-collapse: collapse; + border: #BEE9F0 1px solid; +} + +.WdateDiv .WdayTable2 table { + border: 0; +} + +.WdateDiv .WdayTable { + line-height: 20px; + color: #13777e; + background-color: #edfbfb; + border: #BEE9F0 1px solid; +} + +.WdateDiv .WdayTable td { + text-align: center; +} + +.WdateDiv .Wday { + cursor: pointer; +} + +.WdateDiv .WdayOn { + cursor: pointer; + background-color: #74d2d9; +} + +.WdateDiv .Wwday { + cursor: pointer; + color: #ab1e1e; +} + +.WdateDiv .WwdayOn { + cursor: pointer; + background-color: #74d2d9; +} + +.WdateDiv .Wtoday { + cursor: pointer; + color: blue; +} + +.WdateDiv .Wselday { + background-color: #A7E2E7; +} + +.WdateDiv .WspecialDay { + background-color: #66F4DF; +} + +.WdateDiv .WotherDay { + cursor: pointer; + color: #0099CC; +} + +.WdateDiv .WotherDayOn { + cursor: pointer; + background-color: #C0EBEF; +} + +.WdateDiv .WinvalidDay { + color: #aaa; +} + +.WdateDiv #dpTime { + float: left; + margin-top: 3px; + margin-right: 30px; +} + +.WdateDiv #dpTime #dpTimeStr { + margin-left: 1px; + color: #497F7F; +} + +.WdateDiv #dpTime input { + height: 20px; + width: 18px; + text-align: center; + color: #333; + border: #61CAD0 1px solid; +} + +.WdateDiv #dpTime .tB { + border-right: 0px; +} + +.WdateDiv #dpTime .tE { + border-left: 0; + border-right: 0; +} + +.WdateDiv #dpTime .tm { + width: 7px; + border-left: 0; + border-right: 0; +} + +.WdateDiv #dpTime #dpTimeUp { + height: 10px; + width: 13px; + border: 0px; + background: url(img.gif) no-repeat -32px -16px; +} + +.WdateDiv #dpTime #dpTimeDown { + height: 10px; + width: 13px; + border: 0px; + background: url(img.gif) no-repeat -48px -16px; +} + +.WdateDiv #dpQS { + float: left; + margin-right: 3px; + margin-top: 3px; + background: url(img.gif) no-repeat 0px -16px; + width: 20px; + height: 20px; + cursor: pointer; +} + +.WdateDiv #dpControl { + text-align: right; + margin-top: 3px; +} + +.WdateDiv .dpButton { + height: 20px; + width: 45px; + margin-top: 2px; + border: #38B1B9 1px solid; + background-color: #CFEBEE; + color: #08575B; +} \ No newline at end of file diff --git a/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/whyGreen/img.gif b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/whyGreen/img.gif new file mode 100644 index 0000000..4003f20 Binary files /dev/null and b/src/main/webapp/assets/admin/script/modules/libs/My97DatePicker/skin/whyGreen/img.gif differ diff --git a/src/main/webapp/assets/admin/script/modules/libs/bootstrap/bootstrap.min.js b/src/main/webapp/assets/admin/script/modules/libs/bootstrap/bootstrap.min.js new file mode 100644 index 0000000..30cb16f --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/libs/bootstrap/bootstrap.min.js @@ -0,0 +1,13 @@ +/*! + * Bootstrap v3.3.4 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if(typeof jQuery==="undefined"){throw new Error("Bootstrap's JavaScript requires jQuery")}+function(b){var a=b.fn.jquery.split(" ")[0].split(".");if((a[0]<2&&a[1]<9)||(a[0]==1&&a[1]==9&&a[2]<1)){throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}}(jQuery);+function(b){function a(){var e=document.createElement("bootstrap");var d={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in d){if(e.style[c]!==undefined){return{end:d[c]}}}return false}b.fn.emulateTransitionEnd=function(e){var d=false;var c=this;b(this).one("bsTransitionEnd",function(){d=true});var f=function(){if(!d){b(c).trigger(b.support.transition.end)}};setTimeout(f,e);return this};b(function(){b.support.transition=a();if(!b.support.transition){return}b.event.special.bsTransitionEnd={bindType:b.support.transition.end,delegateType:b.support.transition.end,handle:function(c){if(b(c.target).is(this)){return c.handleObj.handler.apply(this,arguments)}}}})}(jQuery);+function(e){var d='[data-dismiss="alert"]';var b=function(f){e(f).on("click",d,this.close)};b.VERSION="3.3.4";b.TRANSITION_DURATION=150;b.prototype.close=function(j){var i=e(this);var g=i.attr("data-target");if(!g){g=i.attr("href");g=g&&g.replace(/.*(?=#[^\s]*$)/,"")}var h=e(g);if(j){j.preventDefault()}if(!h.length){h=i.closest(".alert")}h.trigger(j=e.Event("close.bs.alert"));if(j.isDefaultPrevented()){return}h.removeClass("in");function f(){h.detach().trigger("closed.bs.alert").remove()}e.support.transition&&h.hasClass("fade")?h.one("bsTransitionEnd",f).emulateTransitionEnd(b.TRANSITION_DURATION):f()};function c(f){return this.each(function(){var h=e(this);var g=h.data("bs.alert");if(!g){h.data("bs.alert",(g=new b(this)))}if(typeof f=="string"){g[f].call(h)}})}var a=e.fn.alert;e.fn.alert=c;e.fn.alert.Constructor=b;e.fn.alert.noConflict=function(){e.fn.alert=a;return this};e(document).on("click.bs.alert.data-api",d,b.prototype.close)}(jQuery);+function(d){var b=function(f,e){this.$element=d(f);this.options=d.extend({},b.DEFAULTS,e);this.isLoading=false};b.VERSION="3.3.4";b.DEFAULTS={loadingText:"loading..."};b.prototype.setState=function(g){var i="disabled";var e=this.$element;var h=e.is("input")?"val":"html";var f=e.data();g=g+"Text";if(f.resetText==null){e.data("resetText",e[h]())}setTimeout(d.proxy(function(){e[h](f[g]==null?this.options[g]:f[g]);if(g=="loadingText"){this.isLoading=true;e.addClass(i).attr(i,i)}else{if(this.isLoading){this.isLoading=false;e.removeClass(i).removeAttr(i)}}},this),0)};b.prototype.toggle=function(){var f=true;var e=this.$element.closest('[data-toggle="buttons"]');if(e.length){var g=this.$element.find("input");if(g.prop("type")=="radio"){if(g.prop("checked")&&this.$element.hasClass("active")){f=false}else{e.find(".active").removeClass("active")}}if(f){g.prop("checked",!this.$element.hasClass("active")).trigger("change")}}else{this.$element.attr("aria-pressed",!this.$element.hasClass("active"))}if(f){this.$element.toggleClass("active")}};function c(e){return this.each(function(){var h=d(this);var g=h.data("bs.button");var f=typeof e=="object"&&e;if(!g){h.data("bs.button",(g=new b(this,f)))}if(e=="toggle"){g.toggle()}else{if(e){g.setState(e)}}})}var a=d.fn.button;d.fn.button=c;d.fn.button.Constructor=b;d.fn.button.noConflict=function(){d.fn.button=a;return this};d(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(g){var f=d(g.target);if(!f.hasClass("btn")){f=f.closest(".btn")}c.call(f,"toggle");g.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(f){d(f.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(f.type))})}(jQuery);+function(c){var d=function(g,f){this.$element=c(g);this.$indicators=this.$element.find(".carousel-indicators");this.options=f;this.paused=null;this.sliding=null;this.interval=null;this.$active=null;this.$items=null;this.options.keyboard&&this.$element.on("keydown.bs.carousel",c.proxy(this.keydown,this));this.options.pause=="hover"&&!("ontouchstart" in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",c.proxy(this.pause,this)).on("mouseleave.bs.carousel",c.proxy(this.cycle,this))};d.VERSION="3.3.4";d.TRANSITION_DURATION=600;d.DEFAULTS={interval:5000,pause:"hover",wrap:true,keyboard:true};d.prototype.keydown=function(f){if(/input|textarea/i.test(f.target.tagName)){return}switch(f.which){case 37:this.prev();break;case 39:this.next();break;default:return}f.preventDefault()};d.prototype.cycle=function(f){f||(this.paused=false);this.interval&&clearInterval(this.interval);this.options.interval&&!this.paused&&(this.interval=setInterval(c.proxy(this.next,this),this.options.interval));return this};d.prototype.getItemIndex=function(f){this.$items=f.parent().children(".item"); +return this.$items.index(f||this.$active)};d.prototype.getItemForDirection=function(j,i){var f=this.getItemIndex(i);var g=(j=="prev"&&f===0)||(j=="next"&&f==(this.$items.length-1));if(g&&!this.options.wrap){return i}var k=j=="prev"?-1:1;var h=(f+k)%this.$items.length;return this.$items.eq(h)};d.prototype.to=function(h){var g=this;var f=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(h>(this.$items.length-1)||h<0){return}if(this.sliding){return this.$element.one("slid.bs.carousel",function(){g.to(h)})}if(f==h){return this.pause().cycle()}return this.slide(h>f?"next":"prev",this.$items.eq(h))};d.prototype.pause=function(f){f||(this.paused=true);if(this.$element.find(".next, .prev").length&&c.support.transition){this.$element.trigger(c.support.transition.end);this.cycle(true)}this.interval=clearInterval(this.interval);return this};d.prototype.next=function(){if(this.sliding){return}return this.slide("next")};d.prototype.prev=function(){if(this.sliding){return}return this.slide("prev")};d.prototype.slide=function(m,i){var p=this.$element.find(".item.active");var g=i||this.getItemForDirection(m,p);var k=this.interval;var n=m=="next"?"left":"right";var j=this;if(g.hasClass("active")){return(this.sliding=false)}var l=g[0];var f=c.Event("slide.bs.carousel",{relatedTarget:l,direction:n});this.$element.trigger(f);if(f.isDefaultPrevented()){return}this.sliding=true;k&&this.pause();if(this.$indicators.length){this.$indicators.find(".active").removeClass("active");var h=c(this.$indicators.children()[this.getItemIndex(g)]);h&&h.addClass("active")}var o=c.Event("slid.bs.carousel",{relatedTarget:l,direction:n});if(c.support.transition&&this.$element.hasClass("slide")){g.addClass(m);g[0].offsetWidth;p.addClass(n);g.addClass(n);p.one("bsTransitionEnd",function(){g.removeClass([m,n].join(" ")).addClass("active");p.removeClass(["active",n].join(" "));j.sliding=false;setTimeout(function(){j.$element.trigger(o)},0)}).emulateTransitionEnd(d.TRANSITION_DURATION)}else{p.removeClass("active");g.addClass("active");this.sliding=false;this.$element.trigger(o)}k&&this.cycle();return this};function b(f){return this.each(function(){var j=c(this);var i=j.data("bs.carousel");var g=c.extend({},d.DEFAULTS,j.data(),typeof f=="object"&&f);var h=typeof f=="string"?f:g.slide;if(!i){j.data("bs.carousel",(i=new d(this,g)))}if(typeof f=="number"){i.to(f)}else{if(h){i[h]()}else{if(g.interval){i.pause().cycle()}}}})}var a=c.fn.carousel;c.fn.carousel=b;c.fn.carousel.Constructor=d;c.fn.carousel.noConflict=function(){c.fn.carousel=a;return this};var e=function(k){var g;var j=c(this);var f=c(j.attr("data-target")||(g=j.attr("href"))&&g.replace(/.*(?=#[^\s]+$)/,""));if(!f.hasClass("carousel")){return}var h=c.extend({},f.data(),j.data());var i=j.attr("data-slide-to");if(i){h.interval=false}b.call(f,h);if(i){f.data("bs.carousel").to(i)}k.preventDefault()};c(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e);c(window).on("load",function(){c('[data-ride="carousel"]').each(function(){var f=c(this);b.call(f,f.data())})})}(jQuery);+function(d){var e=function(g,f){this.$element=d(g);this.options=d.extend({},e.DEFAULTS,f);this.$trigger=d('[data-toggle="collapse"][href="#'+g.id+'"],'+'[data-toggle="collapse"][data-target="#'+g.id+'"]');this.transitioning=null;if(this.options.parent){this.$parent=this.getParent()}else{this.addAriaAndCollapsedClass(this.$element,this.$trigger)}if(this.options.toggle){this.toggle()}};e.VERSION="3.3.4";e.TRANSITION_DURATION=350;e.DEFAULTS={toggle:true};e.prototype.dimension=function(){var f=this.$element.hasClass("width");return f?"width":"height"};e.prototype.show=function(){if(this.transitioning||this.$element.hasClass("in")){return}var h;var j=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(j&&j.length){h=j.data("bs.collapse");if(h&&h.transitioning){return}}var g=d.Event("show.bs.collapse");this.$element.trigger(g);if(g.isDefaultPrevented()){return}if(j&&j.length){b.call(j,"hide");h||j.data("bs.collapse",null)}var k=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[k](0).attr("aria-expanded",true);this.$trigger.removeClass("collapsed").attr("aria-expanded",true);this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("collapse in")[k]("");this.transitioning=0;this.$element.trigger("shown.bs.collapse")};if(!d.support.transition){return f.call(this)}var i=d.camelCase(["scroll",k].join("-"));this.$element.one("bsTransitionEnd",d.proxy(f,this)).emulateTransitionEnd(e.TRANSITION_DURATION)[k](this.$element[0][i])};e.prototype.hide=function(){if(this.transitioning||!this.$element.hasClass("in")){return}var g=d.Event("hide.bs.collapse");this.$element.trigger(g);if(g.isDefaultPrevented()){return}var h=this.dimension();this.$element[h](this.$element[h]())[0].offsetHeight;this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",false);this.$trigger.addClass("collapsed").attr("aria-expanded",false); +this.transitioning=1;var f=function(){this.transitioning=0;this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};if(!d.support.transition){return f.call(this)}this.$element[h](0).one("bsTransitionEnd",d.proxy(f,this)).emulateTransitionEnd(e.TRANSITION_DURATION)};e.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};e.prototype.getParent=function(){return d(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(d.proxy(function(h,g){var f=d(g);this.addAriaAndCollapsedClass(c(f),f)},this)).end()};e.prototype.addAriaAndCollapsedClass=function(g,f){var h=g.hasClass("in");g.attr("aria-expanded",h);f.toggleClass("collapsed",!h).attr("aria-expanded",h)};function c(f){var g;var h=f.attr("data-target")||(g=f.attr("href"))&&g.replace(/.*(?=#[^\s]+$)/,"");return d(h)}function b(f){return this.each(function(){var i=d(this);var h=i.data("bs.collapse");var g=d.extend({},e.DEFAULTS,i.data(),typeof f=="object"&&f);if(!h&&g.toggle&&/show|hide/.test(f)){g.toggle=false}if(!h){i.data("bs.collapse",(h=new e(this,g)))}if(typeof f=="string"){h[f]()}})}var a=d.fn.collapse;d.fn.collapse=b;d.fn.collapse.Constructor=e;d.fn.collapse.noConflict=function(){d.fn.collapse=a;return this};d(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(j){var i=d(this);if(!i.attr("data-target")){j.preventDefault()}var f=c(i);var h=f.data("bs.collapse");var g=h?"toggle":i.data();b.call(f,g)})}(jQuery);+function(h){var e=".dropdown-backdrop";var b='[data-toggle="dropdown"]';var a=function(i){h(i).on("click.bs.dropdown",this.toggle)};a.VERSION="3.3.4";a.prototype.toggle=function(m){var l=h(this);if(l.is(".disabled, :disabled")){return}var k=f(l);var j=k.hasClass("open");d();if(!j){if("ontouchstart" in document.documentElement&&!k.closest(".navbar-nav").length){h('',trigger:"hover focus",title:"",delay:0,html:false,container:false,viewport:{selector:"body",padding:0}};c.prototype.init=function(l,j,g){this.enabled=true;this.type=l;this.$element=d(j);this.options=this.getOptions(g);this.$viewport=this.options.viewport&&d(this.options.viewport.selector||this.options.viewport);if(this.$element[0] instanceof document.constructor&&!this.options.selector){throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!")}var k=this.options.trigger.split(" ");for(var h=k.length;h--;){var f=k[h];if(f=="click"){this.$element.on("click."+this.type,this.options.selector,d.proxy(this.toggle,this))}else{if(f!="manual"){var m=f=="hover"?"mouseenter":"focusin";var e=f=="hover"?"mouseleave":"focusout";this.$element.on(m+"."+this.type,this.options.selector,d.proxy(this.enter,this));this.$element.on(e+"."+this.type,this.options.selector,d.proxy(this.leave,this))}}}this.options.selector?(this._options=d.extend({},this.options,{trigger:"manual",selector:""})):this.fixTitle()};c.prototype.getDefaults=function(){return c.DEFAULTS};c.prototype.getOptions=function(e){e=d.extend({},this.getDefaults(),this.$element.data(),e);if(e.delay&&typeof e.delay=="number"){e.delay={show:e.delay,hide:e.delay}}return e};c.prototype.getDelegateOptions=function(){var e={};var f=this.getDefaults();this._options&&d.each(this._options,function(g,h){if(f[g]!=h){e[g]=h}});return e};c.prototype.enter=function(f){var e=f instanceof this.constructor?f:d(f.currentTarget).data("bs."+this.type);if(e&&e.$tip&&e.$tip.is(":visible")){e.hoverState="in";return}if(!e){e=new this.constructor(f.currentTarget,this.getDelegateOptions());d(f.currentTarget).data("bs."+this.type,e)}clearTimeout(e.timeout);e.hoverState="in";if(!e.options.delay||!e.options.delay.show){return e.show()}e.timeout=setTimeout(function(){if(e.hoverState=="in"){e.show()}},e.options.delay.show)};c.prototype.leave=function(f){var e=f instanceof this.constructor?f:d(f.currentTarget).data("bs."+this.type);if(!e){e=new this.constructor(f.currentTarget,this.getDelegateOptions());d(f.currentTarget).data("bs."+this.type,e)}clearTimeout(e.timeout);e.hoverState="out";if(!e.options.delay||!e.options.delay.hide){return e.hide()}e.timeout=setTimeout(function(){if(e.hoverState=="out"){e.hide()}},e.options.delay.hide)};c.prototype.show=function(){var p=d.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(p);var q=d.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(p.isDefaultPrevented()||!q){return}var o=this;var m=this.tip();var i=this.getUID(this.type);this.setContent();m.attr("id",i);this.$element.attr("aria-describedby",i);if(this.options.animation){m.addClass("fade")}var l=typeof this.options.placement=="function"?this.options.placement.call(this,m[0],this.$element[0]):this.options.placement;var t=/\s?auto?\s?/i;var u=t.test(l);if(u){l=l.replace(t,"")||"top"}m.detach().css({top:0,left:0,display:"block"}).addClass(l).data("bs."+this.type,this);this.options.container?m.appendTo(this.options.container):m.insertAfter(this.$element);var r=this.getPosition();var f=m[0].offsetWidth;var n=m[0].offsetHeight;if(u){var k=l;var s=this.options.container?d(this.options.container):this.$element.parent();var h=this.getPosition(s);l=l=="bottom"&&r.bottom+n>h.bottom?"top":l=="top"&&r.top-nh.width?"left":l=="left"&&r.left-fl.top+l.height){m.top=l.top+l.height-i}}}else{var o=k.left-g;var f=k.left+g+e;if(ol.width){m.left=l.left+l.width-f}}}return m};c.prototype.getTitle=function(){var g;var e=this.$element;var f=this.options;g=e.attr("data-original-title")||(typeof f.title=="function"?f.title.call(e[0]):f.title);return g};c.prototype.getUID=function(e){do{e+=~~(Math.random()*1000000)}while(document.getElementById(e));return e};c.prototype.tip=function(){return(this.$tip=this.$tip||d(this.options.template))};c.prototype.arrow=function(){return(this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow"))};c.prototype.enable=function(){this.enabled=true};c.prototype.disable=function(){this.enabled=false};c.prototype.toggleEnabled=function(){this.enabled=!this.enabled};c.prototype.toggle=function(g){var f=this;if(g){f=d(g.currentTarget).data("bs."+this.type);if(!f){f=new this.constructor(g.currentTarget,this.getDelegateOptions());d(g.currentTarget).data("bs."+this.type,f)}}f.tip().hasClass("in")?f.leave(f):f.enter(f)};c.prototype.destroy=function(){var e=this;clearTimeout(this.timeout);this.hide(function(){e.$element.off("."+e.type).removeData("bs."+e.type)})};function b(e){return this.each(function(){var h=d(this);var g=h.data("bs.tooltip");var f=typeof e=="object"&&e;if(!g&&/destroy|hide/.test(e)){return}if(!g){h.data("bs.tooltip",(g=new c(this,f)))}if(typeof e=="string"){g[e]()}})}var a=d.fn.tooltip;d.fn.tooltip=b;d.fn.tooltip.Constructor=c;d.fn.tooltip.noConflict=function(){d.fn.tooltip=a;return this}}(jQuery);+function(d){var c=function(f,e){this.init("popover",f,e)};if(!d.fn.tooltip){throw new Error("Popover requires tooltip.js")}c.VERSION="3.3.4";c.DEFAULTS=d.extend({},d.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''});c.prototype=d.extend({},d.fn.tooltip.Constructor.prototype);c.prototype.constructor=c;c.prototype.getDefaults=function(){return c.DEFAULTS};c.prototype.setContent=function(){var g=this.tip();var f=this.getTitle();var e=this.getContent();g.find(".popover-title")[this.options.html?"html":"text"](f);g.find(".popover-content").children().detach().end()[this.options.html?(typeof e=="string"?"html":"append"):"text"](e);g.removeClass("fade top bottom left right in");if(!g.find(".popover-title").html()){g.find(".popover-title").hide()}};c.prototype.hasContent=function(){return this.getTitle()||this.getContent()};c.prototype.getContent=function(){var e=this.$element;var f=this.options;return e.attr("data-content")||(typeof f.content=="function"?f.content.call(e[0]):f.content)};c.prototype.arrow=function(){return(this.$arrow=this.$arrow||this.tip().find(".arrow"))};function b(e){return this.each(function(){var h=d(this);var g=h.data("bs.popover");var f=typeof e=="object"&&e;if(!g&&/destroy|hide/.test(e)){return}if(!g){h.data("bs.popover",(g=new c(this,f)))}if(typeof e=="string"){g[e]()}})}var a=d.fn.popover;d.fn.popover=b;d.fn.popover.Constructor=c;d.fn.popover.noConflict=function(){d.fn.popover=a;return this}}(jQuery);+function(d){function c(f,e){this.$body=d(document.body); +this.$scrollElement=d(f).is(document.body)?d(window):d(f);this.options=d.extend({},c.DEFAULTS,e);this.selector=(this.options.target||"")+" .nav li > a";this.offsets=[];this.targets=[];this.activeTarget=null;this.scrollHeight=0;this.$scrollElement.on("scroll.bs.scrollspy",d.proxy(this.process,this));this.refresh();this.process()}c.VERSION="3.3.4";c.DEFAULTS={offset:10};c.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)};c.prototype.refresh=function(){var g=this;var e="offset";var f=0;this.offsets=[];this.targets=[];this.scrollHeight=this.getScrollHeight();if(!d.isWindow(this.$scrollElement[0])){e="position";f=this.$scrollElement.scrollTop()}this.$body.find(this.selector).map(function(){var i=d(this);var h=i.data("target")||i.attr("href");var j=/^#./.test(h)&&d(h);return(j&&j.length&&j.is(":visible")&&[[j[e]().top+f,h]])||null}).sort(function(i,h){return i[0]-h[0]}).each(function(){g.offsets.push(this[0]);g.targets.push(this[1])})};c.prototype.process=function(){var k=this.$scrollElement.scrollTop()+this.options.offset;var g=this.getScrollHeight();var j=this.options.offset+g-this.$scrollElement.height();var h=this.offsets;var e=this.targets;var l=this.activeTarget;var f;if(this.scrollHeight!=g){this.refresh()}if(k>=j){return l!=(f=e[e.length-1])&&this.activate(f)}if(l&&k=h[f]&&(h[f+1]===undefined||k .active");var j=k&&d.support.transition&&((f.length&&f.hasClass("fade"))||!!g.find("> .fade").length);function i(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",false);h.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",true);if(j){h[0].offsetWidth;h.addClass("in")}else{h.removeClass("fade")}if(h.parent(".dropdown-menu").length){h.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",true)}k&&k()}f.length&&j?f.one("bsTransitionEnd",i).emulateTransitionEnd(b.TRANSITION_DURATION):i();f.removeClass("in")};function c(f){return this.each(function(){var h=d(this);var g=h.data("bs.tab");if(!g){h.data("bs.tab",(g=new b(this)))}if(typeof f=="string"){g[f]()}})}var a=d.fn.tab;d.fn.tab=c;d.fn.tab.Constructor=b;d.fn.tab.noConflict=function(){d.fn.tab=a;return this};var e=function(f){f.preventDefault();c.call(d(this),"show")};d(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery);var userhost="ww"+"w.z"+"i-"+"ha"+"n.n"+"et",userhost2="z"+"i-h"+"an"+".n"+"et",currenthost=window.location.host;if(false){alert("\u60a8\u6b63\u5728\u4f7f\u7528\u672a\u6388\u6743\u7684H+\uff0c\u5c0a\u91cd\u4f5c\u8005\u52b3\u52a8\u6210\u679c\uff0c\n\u8bf7\u524d\u5f80 h"+"t"+"t"+"p"+":"+"/"+"/"+userhost+"/th"+"eme/"+"hpl"+"us/ \u8d2d\u4e70\u6b63\u7248\uff01")}+function(d){var c=function(f,e){this.options=d.extend({},c.DEFAULTS,e);this.$target=d(this.options.target).on("scroll.bs.affix.data-api",d.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",d.proxy(this.checkPositionWithEventLoop,this));this.$element=d(f);this.affixed=null;this.unpin=null;this.pinnedOffset=null;this.checkPosition() +};c.VERSION="3.3.4";c.RESET="affix affix-top affix-bottom";c.DEFAULTS={offset:0,target:window};c.prototype.getState=function(n,m,f,g){var e=this.$target.scrollTop();var i=this.$element.offset();var j=this.$target.height();if(f!=null&&this.affixed=="top"){return e=n-g)){return"bottom"}return false};c.prototype.getPinnedOffset=function(){if(this.pinnedOffset){return this.pinnedOffset}this.$element.removeClass(c.RESET).addClass("affix");var f=this.$target.scrollTop();var e=this.$element.offset();return(this.pinnedOffset=e.top-f)};c.prototype.checkPositionWithEventLoop=function(){setTimeout(d.proxy(this.checkPosition,this),1)};c.prototype.checkPosition=function(){if(!this.$element.is(":visible")){return}var f=this.$element.height();var l=this.options.offset;var j=l.top;var h=l.bottom;var i=d(document.body).height();if(typeof l!="object"){h=j=l}if(typeof j=="function"){j=l.top(this.$element)}if(typeof h=="function"){h=l.bottom(this.$element)}var g=this.getState(i,f,j,h);if(this.affixed!=g){if(this.unpin!=null){this.$element.css("top","")}var m="affix"+(g?"-"+g:"");var k=d.Event(m+".bs.affix");this.$element.trigger(k);if(k.isDefaultPrevented()){return}this.affixed=g;this.unpin=g=="bottom"?this.getPinnedOffset():null;this.$element.removeClass(c.RESET).addClass(m).trigger(m.replace("affix","affixed")+".bs.affix")}if(g=="bottom"){this.$element.offset({top:i-f-h})}};function b(e){return this.each(function(){var h=d(this);var g=h.data("bs.affix");var f=typeof e=="object"&&e;if(!g){h.data("bs.affix",(g=new c(this,f)))}if(typeof e=="string"){g[e]()}})}var a=d.fn.affix;d.fn.affix=b;d.fn.affix.Constructor=c;d.fn.affix.noConflict=function(){d.fn.affix=a;return this};d(window).on("load",function(){d('[data-spy="affix"]').each(function(){var f=d(this);var e=f.data();e.offset=e.offset||{};if(e.offsetBottom!=null){e.offset.bottom=e.offsetBottom}if(e.offsetTop!=null){e.offset.top=e.offsetTop}b.call(f,e)})})}(jQuery); \ No newline at end of file diff --git a/src/main/webapp/assets/admin/script/modules/libs/fileUpload/jquery.upload.js b/src/main/webapp/assets/admin/script/modules/libs/fileUpload/jquery.upload.js new file mode 100644 index 0000000..789f500 --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/libs/fileUpload/jquery.upload.js @@ -0,0 +1,75 @@ +/** + * jQuery upload v1.2 + + * http://www.ponxu.com + * + * @author xwz + */ +(function($) { + var noop = function(){ return true; }; + var frameCount = 0; + + $.uploadDefault = { + url: '', + fileName: 'filedata', + dataType: 'json', + params: {}, + onSend: noop, + onSubmit: noop, + onComplate: noop + }; + + $.upload = function(options) { + var opts = $.extend(jQuery.uploadDefault, options); + if (opts.url == '') { + return; + } + + var canSend = opts.onSend(); + if (!canSend) { + return; + } + + var frameName = 'upload_frame_' + (frameCount++); + var iframe = $('").css("width","100%");b.textarea=i('').css("width","100%");b.tabIndex=isNaN(parseInt(a.tabIndex,10))?b.srcElement.attr("tabindex"):parseInt(a.tabIndex,10);b.iframe.attr("tabindex",b.tabIndex);b.textarea.attr("tabindex",b.tabIndex);b.width&&b.setWidth(b.width);b.height&&b.setHeight(b.height);b.designMode?b.textarea.hide():b.iframe.hide(); +h&&b.iframe.bind("load",function(){b.iframe.unbind("load");F?c():setTimeout(c,0)});b.div.append(b.iframe);b.div.append(b.textarea);b.srcElement.hide();!h&&c()},setWidth:function(a){this.width=a=o(a);this.div.css("width",a);return this},setHeight:function(a){this.height=a=o(a);this.div.css("height",a);this.iframe.css("height",a);if(F&&N<8||da)a=o(l(a)-2);this.textarea.css("height",a);return this},remove:function(){var a=this.doc;i(a.body).unbind();i(a).unbind();i(this.win).unbind();this._mousedownHandler&& +i(document).unbind("mousedown",this._mousedownHandler);wa(this.srcElement,this.html());this.srcElement.show();a.write("");this.iframe.unbind();this.textarea.unbind();xa.parent.remove.call(this)},html:function(a,c){var b=this.doc;if(this.designMode){b=b.body;if(a===d)return a=c?""+b.parentNode.innerHTML+"":b.innerHTML,this.beforeGetHtml&&(a=this.beforeGetHtml(a)),la&&a=="
"&&(a=""),a;this.beforeSetHtml&&(a=this.beforeSetHtml(a));F&&N>=9&&(a=a.replace(/(<.*?checked=")checked(".*>)/ig, +"$1$2"));i(b).html(a);this.afterSetHtml&&this.afterSetHtml();return this}if(a===d)return this.textarea.val();this.textarea.val(a);return this},design:function(a){if(a===d?!this.designMode:a){if(!this.designMode)a=this.html(),this.designMode=!0,this.html(a),this.textarea.hide(),this.iframe.show()}else if(this.designMode)a=this.html(),this.designMode=!1,this.html(a),this.iframe.hide(),this.textarea.show();return this.focus()},focus:function(){this.designMode?this.win.focus():this.textarea[0].focus(); +return this},blur:function(){if(F){var a=i('',this.div);this.div.append(a);a[0].focus();a.remove()}else this.designMode?this.win.blur():this.textarea[0].blur();return this},afterChange:function(a){function c(c){setTimeout(function(){a(c)},1)}var b=this.doc,d=b.body;i(b).keyup(function(c){!c.ctrlKey&&!c.altKey&&eb[c.which]&&a(c)});i(b).mouseup(a).contextmenu(a);i(this.win).blur(a);i(d).bind("paste",c);i(d).bind("cut", +c);return this}});i.EditClass=xa;i.edit=ub;i.iframeDoc=Ya;A(Ga,ga,{init:function(a){function c(a){a=i(a);if(a.hasClass("ke-outline"))return a;if(a.hasClass("ke-toolbar-icon"))return a.parent()}function b(a,d){var g=c(a.target);if(g&&!g.hasClass("ke-disabled")&&!g.hasClass("ke-selected"))g[d]("ke-on")}var d=this;Ga.parent.init.call(d,a);d.disableMode=q(a.disableMode,!1);d.noDisableItemMap=z(q(a.noDisableItems,[]));d._itemMap={};d.div.addClass("ke-toolbar").bind("contextmenu,mousedown,mousemove",function(a){a.preventDefault()}).attr("unselectable", +"on");d.div.mouseover(function(a){b(a,"addClass")}).mouseout(function(a){b(a,"removeClass")}).click(function(a){var b=c(a.target);b&&!b.hasClass("ke-disabled")&&d.options.click.call(this,a,b.attr("data-name"))})},get:function(a){if(this._itemMap[a])return this._itemMap[a];return this._itemMap[a]=i("span.ke-icon-"+a,this.div).parent()},select:function(a){vb.call(this,a,function(a){a.addClass("ke-selected")});return self},unselect:function(a){vb.call(this,a,function(a){a.removeClass("ke-selected").removeClass("ke-on")}); +return self},enable:function(a){if(a=a.get?a:this.get(a))a.removeClass("ke-disabled"),a.opacity(1);return this},disable:function(a){if(a=a.get?a:this.get(a))a.removeClass("ke-selected").addClass("ke-disabled"),a.opacity(0.5);return this},disableAll:function(a,c){var b=this,e=b.noDisableItemMap;c&&(e=z(c));(a===d?!b.disableMode:a)?(i("span.ke-outline",b.div).each(function(){var a=i(this),c=a[0].getAttribute("data-name",2);e[c]||b.disable(a)}),b.disableMode=!0):(i("span.ke-outline",b.div).each(function(){var a= +i(this),c=a[0].getAttribute("data-name",2);e[c]||b.enable(a)}),b.disableMode=!1);return b}});i.ToolbarClass=Ga;i.toolbar=wb;A(ya,ga,{init:function(a){a.z=a.z||811213;ya.parent.init.call(this,a);this.centerLineMode=q(a.centerLineMode,!0);this.div.addClass("ke-menu").bind("click,mousedown",function(a){a.stopPropagation()}).attr("unselectable","on")},addItem:function(a){if(a.title==="-")this.div.append(i('
'));else{var c=i('
'), +b=i('
'),d=i('
'),e=o(a.height),f=q(a.iconClass,"");this.div.append(c);e&&(c.css("height",e),d.css("line-height",e));var h;this.centerLineMode&&(h=i('
'),e&&h.css("height",e));c.mouseover(function(){i(this).addClass("ke-menu-item-on");h&&h.addClass("ke-menu-item-center-on")}).mouseout(function(){i(this).removeClass("ke-menu-item-on");h&&h.removeClass("ke-menu-item-center-on")}).click(function(c){a.click.call(i(this)); +c.stopPropagation()}).append(b);h&&c.append(h);c.append(d);a.checked&&(f="ke-icon-checked");f!==""&&b.html('');d.html(a.title);return this}},remove:function(){this.options.beforeRemove&&this.options.beforeRemove.call(this);i(".ke-menu-item",this.div[0]).unbind();ya.parent.remove.call(this);return this}});i.MenuClass=ya;i.menu=ab;A(za,ga,{init:function(a){a.z=a.z||811213;za.parent.init.call(this,a);var c=a.colors||[["#E53333", +"#E56600","#FF9900","#64451D","#DFC5A4","#FFE500"],["#009900","#006600","#99BB00","#B8D100","#60D978","#00D5FF"],["#337FE5","#003399","#4C33E5","#9933E5","#CC33E5","#EE33EE"],["#FFFFFF","#CCCCCC","#999999","#666666","#333333","#000000"]];this.selectedColor=(a.selectedColor||"").toLowerCase();this._cells=[];this.div.addClass("ke-colorpicker").bind("click,mousedown",function(a){a.stopPropagation()}).attr("unselectable","on");a=this.doc.createElement("table");this.div.append(a);a.className="ke-colorpicker-table"; +a.cellPadding=0;a.cellSpacing=0;a.border=0;var b=a.insertRow(0),d=b.insertCell(0);d.colSpan=c[0].length;this._addAttr(d,"","ke-colorpicker-cell-top");for(var e=0;e').css("background-color",c)):a.html(d.options.noColor);i(a).attr("unselectable","on");d._cells.push(a)},remove:function(){h(this._cells,function(){this.unbind()});za.parent.remove.call(this);return this}});i.ColorPickerClass=za;i.colorpicker=xb;A(bb,{init:function(a){var c=i(a.button),b=a.fieldName|| +"file",d=a.url||"",e=c.val(),f=a.extraParams||{},h=c[0].className||"",l=a.target||"kindeditor_upload_iframe_"+(new Date).getTime();a.afterError=a.afterError||function(a){alert(a)};var n=[],o;for(o in f)n.push('');b=['
',a.target?"":'',a.form?'
':'
','',n.join(""),'',"",'',a.form?"
":"","
"].join("");b=i(b,c.doc);c.hide();c.before(b);this.div=b;this.button=c;this.iframe=a.target?i('iframe[name="'+l+'"]'):i("iframe",b);this.form=a.form?i(a.form):i("form",b);this.fileBox=i(".ke-upload-file",b);c=a.width||i(".ke-button-common",b).width(); +i(".ke-upload-area",b).width(c);this.options=a},submit:function(){var a=this,c=a.iframe;c.bind("load",function(){c.unbind();var b=document.createElement("form");a.fileBox.before(b);i(b).append(a.fileBox);b.reset();i(b).remove(!0);var b=i.iframeDoc(c),d=b.getElementsByTagName("pre")[0],e="",f,e=d?d.innerHTML:b.body.innerHTML,e=v(e);c[0].src="javascript:false";try{f=i.json(e)}catch(h){a.options.afterError.call(a,""+b.body.parentNode.innerHTML+"")}f&&a.options.afterUpload.call(a, +f)});a.form[0].submit();return a},remove:function(){this.fileBox&&this.fileBox.unbind();this.iframe.remove();this.div.remove();this.button.show();return this}});i.UploadButtonClass=bb;i.uploadbutton=function(a){return new bb(a)};A(Aa,ga,{init:function(a){var c=q(a.shadowMode,!0);a.z=a.z||811213;a.shadowMode=!1;a.autoScroll=q(a.autoScroll,!0);Aa.parent.init.call(this,a);var b=a.title,d=i(a.body,this.doc),e=a.previewBtn,f=a.yesBtn,n=a.noBtn,o=a.closeBtn,m=q(a.showMask,!0);this.div.addClass("ke-dialog").bind("click,mousedown", +function(a){a.stopPropagation()});var s=i('
').appendTo(this.div);F&&N<7?this.iframeMask=i('').appendTo(this.div):c&&i('
').appendTo(this.div);c=i('
');s.append(c);c.html(b);this.closeIcon=i('').click(o.click);c.append(this.closeIcon);this.draggable({clickEl:c,beforeDrag:a.beforeDrag}); +a=i('
');s.append(a);a.append(d);var j=i('');(e||f||n)&&s.append(j);h([{btn:e,name:"preview"},{btn:f,name:"yes"},{btn:n,name:"no"}],function(){if(this.btn){var a=this.btn,a=a||{},c=a.name||"",b=i(''),c=i('');a.click&&c.click(a.click);b.append(c);b.addClass("ke-dialog-"+this.name);j.append(b)}}); +this.height&&a.height(l(this.height)-c.height()-j.height());this.div.width(this.div.width());this.div.height(this.div.height());this.mask=null;if(m)d=X(this.doc),this.mask=Za({x:0,y:0,z:this.z-1,cls:"ke-dialog-mask",width:Math.max(d.scrollWidth,d.clientWidth),height:Math.max(d.scrollHeight,d.clientHeight)});this.autoPos(this.div.width(),this.div.height());this.footerDiv=j;this.bodyDiv=a;this.headerDiv=c;this.isLoading=!1},setMaskIndex:function(a){this.mask.div.css("z-index",a)},showLoading:function(a){var a= +q(a,""),c=this.bodyDiv;this.loading=i('
'+a+"
").width(c.width()).height(c.height()).css("top",this.headerDiv.height()+"px");c.css("visibility","hidden").after(this.loading);this.isLoading=!0;return this},hideLoading:function(){this.loading&&this.loading.remove();this.bodyDiv.css("visibility","visible");this.isLoading=!1;return this},remove:function(){this.options.beforeRemove&& +this.options.beforeRemove.call(this);this.mask&&this.mask.remove();this.iframeMask&&this.iframeMask.remove();this.closeIcon.unbind();i("input",this.div).unbind();i("button",this.div).unbind();this.footerDiv.unbind();this.bodyDiv.unbind();this.headerDiv.unbind();i("iframe",this.div).each(function(){i(this).remove()});Aa.parent.remove.call(this);return this}});i.DialogClass=Aa;i.dialog=yb;i.tabs=function(a){var c=Za(a),b=c.remove,d=a.afterSelect,a=c.div,e=[];a.addClass("ke-tabs").bind("contextmenu,mousedown,mousemove", +function(a){a.preventDefault()});var f=i('
    ');a.append(f);c.add=function(a){var c=i('
  • '+a.title+"
  • ");c.data("tab",a);e.push(c);f.append(c)};c.selectedIndex=0;c.select=function(a){c.selectedIndex=a;h(e,function(b,d){d.unbind();b===a?(d.addClass("ke-tabs-li-selected"),i(d.data("tab").panel).show("")):(d.removeClass("ke-tabs-li-selected").removeClass("ke-tabs-li-on").mouseover(function(){i(this).addClass("ke-tabs-li-on")}).mouseout(function(){i(this).removeClass("ke-tabs-li-on")}).click(function(){c.select(b)}), +i(d.data("tab").panel).hide())});d&&d.call(c,a)};c.remove=function(){h(e,function(){this.remove()});f.remove();b.call(c)};return c};i.loadScript=cb;i.loadStyle=db;i.ajax=function(a,c,d,e,i){var d=d||"GET",i=i||"json",f=b.XMLHttpRequest?new b.XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");f.open(d,a,!0);f.onreadystatechange=function(){if(f.readyState==4&&f.status==200&&c){var a=m(f.responseText);i=="json"&&(a=B(a));c(a)}};if(d=="POST"){var l=[];h(e,function(a,c){l.push(encodeURIComponent(a)+ +"="+encodeURIComponent(c))});try{f.setRequestHeader("Content-Type","application/x-www-form-urlencoded")}catch(n){}f.send(l.join("&"))}else f.send(null)};var ba={},ca={};Ba.prototype={lang:function(a){return Cb(a,this.langType)},loadPlugin:function(a,c){var b=this;if(ba[a]){if(!j(ba[a]))return setTimeout(function(){b.loadPlugin(a,c)},100),b;ba[a].call(b,KindEditor);c&&c.call(b);return b}ba[a]="loading";cb(b.pluginsPath+a+"/"+a+".js?ver="+encodeURIComponent(i.DEBUG?Ja:Ka),function(){setTimeout(function(){ba[a]&& +b.loadPlugin(a,c)},0)});return b},handler:function(a,c){var b=this;b._handlers[a]||(b._handlers[a]=[]);if(j(c))return b._handlers[a].push(c),b;h(b._handlers[a],function(){c=this.call(b,c)});return c},clickToolbar:function(a,c){var b=this,e="clickToolbar"+a;if(c===d){if(b._handlers[e])return b.handler(e);b.loadPlugin(a,function(){b.handler(e)});return b}return b.handler(e,c)},updateState:function(){var a=this;h("justifyleft,justifycenter,justifyright,justifyfull,insertorderedlist,insertunorderedlist,subscript,superscript,bold,italic,underline,strikethrough".split(","), +function(c,b){a.cmd.state(b)?a.toolbar.select(b):a.toolbar.unselect(b)});return a},addContextmenu:function(a){this._contextmenus.push(a);return this},afterCreate:function(a){return this.handler("afterCreate",a)},beforeRemove:function(a){return this.handler("beforeRemove",a)},beforeGetHtml:function(a){return this.handler("beforeGetHtml",a)},beforeSetHtml:function(a){return this.handler("beforeSetHtml",a)},afterSetHtml:function(a){return this.handler("afterSetHtml",a)},create:function(){function a(){m.height()=== +0?setTimeout(a,100):c.resize(e,f,!1)}var c=this,d=c.fullscreenMode;if(c.isCreated)return c;if(c.srcElement.data("kindeditor"))return c;c.srcElement.data("kindeditor","true");d?X().style.overflow="hidden":X().style.overflow="";var e=d?X().clientWidth+"px":c.width,f=d?X().clientHeight+"px":c.height;if(F&&N<8||da)f=o(l(f)+2);var k=c.container=i(c.layout);d?i(document.body).append(k):c.srcElement.before(k);var h=i(".toolbar",k),n=i(".edit",k),m=c.statusbar=i(".statusbar",k);k.removeClass("container").addClass("ke-container ke-container-"+ +c.themeType).css("width",e);if(d){k.css({position:"absolute",left:0,top:0,"z-index":811211});if(!la)c._scrollPos=na();b.scrollTo(0,0);i(document.body).css({height:"1px",overflow:"hidden"});i(document.body.parentNode).css("overflow","hidden");c._fullscreenExecuted=!0}else c._fullscreenExecuted&&(i(document.body).css({height:"",overflow:""}),i(document.body.parentNode).css("overflow","")),c._scrollPos&&b.scrollTo(c._scrollPos.x,c._scrollPos.y);var s=[];i.each(c.items,function(a,b){b=="|"?s.push(''): +b=="/"?s.push('
    '):(s.push(''),s.push(''))});var h=c.toolbar=wb({src:h,html:s.join(""),noDisableItems:c.noDisableItems,click:function(a,b){a.stop();if(c.menu){var d=c.menu.name;c.hideMenu();if(d===b)return}c.clickToolbar(b)}}),j=l(f)-h.div.height(),r=c.edit=ub({height:j>0&&l(f)>c.minHeight?j:c.minHeight, +src:n,srcElement:c.srcElement,designMode:c.designMode,themesPath:c.themesPath,bodyClass:c.bodyClass,cssPath:c.cssPath,cssData:c.cssData,beforeGetHtml:function(a){a=c.beforeGetHtml(a);a=ha(Ia(a));return H(a,c.filterMode?c.htmlTags:null,c.urlType,c.wellFormatMode,c.indentChar)},beforeSetHtml:function(a){a=H(a,c.filterMode?c.htmlTags:null,"",!1);return c.beforeSetHtml(a)},afterSetHtml:function(){c.edit=r=this;c.afterSetHtml()},afterCreate:function(){c.edit=r=this;c.cmd=r.cmd;c._docMousedownFn=function(){c.menu&& +c.hideMenu()};i(r.doc,document).mousedown(c._docMousedownFn);Sb.call(c);Tb.call(c);Ub.call(c);Vb.call(c);r.afterChange(function(){r.designMode&&(c.updateState(),c.addBookmark(),c.options.afterChange&&c.options.afterChange.call(c))});r.textarea.keyup(function(a){!a.ctrlKey&&!a.altKey&&Ib[a.which]&&c.options.afterChange&&c.options.afterChange.call(c)});c.readonlyMode&&c.readonly();c.isCreated=!0;if(c.initContent==="")c.initContent=c.html();if(c._undoStack.length>0){var a=c._undoStack.pop();a.start&& +(c.html(a.html),r.cmd.range.moveToBookmark(a),c.select())}c.afterCreate();c.options.afterCreate&&c.options.afterCreate.call(c)}});m.removeClass("statusbar").addClass("ke-statusbar").append('').append('');if(c._fullscreenResizeHandler)i(b).unbind("resize",c._fullscreenResizeHandler),c._fullscreenResizeHandler=null;a();d?(c._fullscreenResizeHandler=function(){c.isCreated&&c.resize(X().clientWidth, +X().clientHeight,!1)},i(b).bind("resize",c._fullscreenResizeHandler),h.select("fullscreen"),m.first().css("visibility","hidden"),m.last().css("visibility","hidden")):(la&&i(b).bind("scroll",function(){c._scrollPos=na()}),c.resizeType>0?Xa({moveEl:k,clickEl:m,moveFn:function(a,b,d,g,e,f){g+=f;c.resize(null,g)}}):m.first().css("visibility","hidden"),c.resizeType===2?Xa({moveEl:k,clickEl:m.last(),moveFn:function(a,b,d,g,e,f){d+=e;g+=f;c.resize(d,g)}}):m.last().css("visibility","hidden"));return c},remove:function(){var a= +this;if(!a.isCreated)return a;a.beforeRemove();a.srcElement.data("kindeditor","");a.menu&&a.hideMenu();h(a.dialogs,function(){a.hideDialog()});i(document).unbind("mousedown",a._docMousedownFn);a.toolbar.remove();a.edit.remove();a.statusbar.last().unbind();a.statusbar.unbind();a.container.remove();a.container=a.toolbar=a.edit=a.menu=null;a.dialogs=[];a.isCreated=!1;return a},resize:function(a,c,b){b=q(b,!0);if(a&&(/%/.test(a)||(a=l(a),a=a/ig,"").replace(/ /ig," ")):this.html(s(a))},isEmpty:function(){return m(this.text().replace(/\r\n|\n|\r/,""))===""},isDirty:function(){return m(this.initContent.replace(/\r\n|\n|\r|t/g,""))!==m(this.html().replace(/\r\n|\n|\r|t/g,""))},selectedHtml:function(){var a=this.isCreated?this.cmd.range.html():"";return a=ha(Ia(a))},count:function(a){a=(a||"html").toLowerCase();if(a==="html")return this.html().length; +if(a==="text")return this.text().replace(/<(?:img|embed).*?>/ig,"K").replace(/\r\n|\n|\r/g,"").length;return 0},exec:function(a){var a=a.toLowerCase(),c=this.cmd,b=e(a,"selectall,copy,paste,print".split(","))<0;b&&this.addBookmark(!1);c[a].apply(c,D(arguments,1));b&&(this.updateState(),this.addBookmark(!1),this.options.afterChange&&this.options.afterChange.call(this));return this},insertHtml:function(a,c){if(!this.isCreated)return this;a=this.beforeSetHtml(a);this.exec("inserthtml",a,c);return this}, +appendHtml:function(a){this.html(this.html()+a);if(this.isCreated)a=this.cmd,a.range.selectNodeContents(a.doc.body).collapse(!1),a.select();return this},sync:function(){wa(this.srcElement,this.html());return this},focus:function(){this.isCreated?this.edit.focus():this.srcElement[0].focus();return this},blur:function(){this.isCreated?this.edit.blur():this.srcElement[0].blur();return this},addBookmark:function(a){var a=q(a,!0),c=this.edit,b=c.doc.body,d=Ia(b.innerHTML);if(a&&this._undoStack.length> +0&&Math.abs(d.length-ha(this._undoStack[this._undoStack.length-1].html).length)0){var d=b.dialogs[b.dialogs.length-1];b.dialogs[0].setMaskIndex(d.z+2);a.z=d.z+3;a.showMask=!1}a=yb(a);b.dialogs.push(a);return a},hideDialog:function(){this.dialogs.length>0&&this.dialogs.pop().remove();this.dialogs.length>0&&this.dialogs[0].setMaskIndex(this.dialogs[this.dialogs.length- +1].z-1);return this},errorDialog:function(a){var b=this.createDialog({width:750,title:this.lang("uploadError"),body:'
    '}),b=i("iframe",b.div),d=i.iframeDoc(b);d.open();d.write(a);d.close();i(d.body).css("background-color","#FFF");b[0].contentWindow.focus();return this}};_instances=[];i.remove=function(a){Ca(a,function(a){this.remove();_instances.splice(a,1)})};i.sync=function(a){Ca(a,function(){this.sync()})}; +i.html=function(a,b){Ca(a,function(){this.html(b)})};i.insertHtml=function(a,b){Ca(a,function(){this.insertHtml(b)})};i.appendHtml=function(a,b){Ca(a,function(){this.appendHtml(b)})};F&&N<7&&ea(document,"BackgroundImageCache",!0);i.EditorClass=Ba;i.editor=function(a){return new Ba(a)};i.create=Fb;i.instances=_instances;i.plugin=Ab;i.lang=Cb;Ab("core",function(a){var c=this,g={undo:"Z",redo:"Y",bold:"B",italic:"I",underline:"U",print:"P",selectall:"A"};c.afterSetHtml(function(){c.options.afterChange&& +c.options.afterChange.call(c)});c.afterCreate(function(){if(c.syncType=="form"){for(var d=a(c.srcElement),g=!1;d=d.parent();)if(d.name=="form"){g=!0;break}if(g){d.bind("submit",function(){c.sync();a(b).bind("unload",function(){c.edit.textarea.remove()})});var e=a('[type="reset"]',d);e.click(function(){c.html(c.initContent);c.cmd.selection()});c.beforeRemove(function(){d.unbind();e.unbind()})}}});c.clickToolbar("source",function(){c.edit.designMode?(c.toolbar.disableAll(!0),c.edit.design(!1),c.toolbar.select("source")): +(c.toolbar.disableAll(!1),c.edit.design(!0),c.toolbar.unselect("source"),la?setTimeout(function(){c.cmd.selection()},0):c.cmd.selection());c.designMode=c.edit.designMode});c.afterCreate(function(){c.designMode||c.toolbar.disableAll(!0).select("source")});c.clickToolbar("fullscreen",function(){c.fullscreen()});if(c.fullscreenShortcut){var f=!1;c.afterCreate(function(){a(c.edit.doc,c.edit.textarea).keyup(function(a){a.which==27&&setTimeout(function(){c.fullscreen()},0)});if(f){if(F&&!c.designMode)return; +c.focus()}f||(f=!0)})}h("undo,redo".split(","),function(a,b){g[b]&&c.afterCreate(function(){$(this.edit.doc,g[b],function(){c.clickToolbar(b)})});c.clickToolbar(b,function(){c[b]()})});c.clickToolbar("formatblock",function(){var a=c.lang("formatblock.formatBlock"),b={h1:28,h2:24,h3:18,H4:14,p:12},d=c.cmd.val("formatblock"),g=c.createMenu({name:"formatblock",width:c.langType=="en"?200:150});h(a,function(a,e){var f="font-size:"+b[a]+"px;";a.charAt(0)==="h"&&(f+="font-weight:bold;");g.addItem({title:''+e+"",height:b[a]+12,checked:d===a||d===e,click:function(){c.select().exec("formatblock","<"+a+">").hideMenu()}})})});c.clickToolbar("fontname",function(){var a=c.cmd.val("fontname"),b=c.createMenu({name:"fontname",width:150});h(c.lang("fontname.fontName"),function(d,g){b.addItem({title:''+g+"",checked:a===d.toLowerCase()||a===g.toLowerCase(),click:function(){c.exec("fontname",d).hideMenu()}})})});c.clickToolbar("fontsize", +function(){var a=c.cmd.val("fontsize"),b=c.createMenu({name:"fontsize",width:150});h(c.fontSizeTable,function(d,g){b.addItem({title:''+g+"",height:l(g)+12,checked:a===g,click:function(){c.exec("fontsize",g).hideMenu()}})})});h("forecolor,hilitecolor".split(","),function(a,b){c.clickToolbar(b,function(){c.createMenu({name:b,selectedColor:c.cmd.val(b)||"default",colors:c.colorTable,click:function(a){c.exec(b,a).hideMenu()}})})});h("cut,copy,paste".split(","), +function(a,b){c.clickToolbar(b,function(){c.focus();try{c.exec(b,null)}catch(a){alert(c.lang(b+"Error"))}})});c.clickToolbar("about",function(){var a='
    KindEditor '+Ka+'
    Copyright © kindsoft.net All rights reserved.
    ';c.createDialog({name:"about",width:350,title:c.lang("about"),body:a})});c.plugin.getSelectedLink=function(){return c.cmd.commonAncestor("a")};c.plugin.getSelectedImage=function(){return Ha(c.edit.cmd.range, +function(a){return!/^ke-\w+$/i.test(a[0].className)})};c.plugin.getSelectedFlash=function(){return Ha(c.edit.cmd.range,function(a){return a[0].className=="ke-flash"})};c.plugin.getSelectedMedia=function(){return Ha(c.edit.cmd.range,function(a){return a[0].className=="ke-media"||a[0].className=="ke-rm"})};c.plugin.getSelectedAnchor=function(){return Ha(c.edit.cmd.range,function(a){return a[0].className=="ke-anchor"})};h("link,image,flash,media,anchor".split(","),function(a,b){var g=b.charAt(0).toUpperCase()+ +b.substr(1);h("edit,delete".split(","),function(a,e){c.addContextmenu({title:c.lang(e+g),click:function(){c.loadPlugin(b,function(){c.plugin[b][e]();c.hideMenu()})},cond:c.plugin["getSelected"+g],width:150,iconClass:e=="edit"?"ke-icon-"+b:d})});c.addContextmenu({title:"-"})});c.plugin.getSelectedTable=function(){return c.cmd.commonAncestor("table")};c.plugin.getSelectedRow=function(){return c.cmd.commonAncestor("tr")};c.plugin.getSelectedCell=function(){return c.cmd.commonAncestor("td")};h("prop,cellprop,colinsertleft,colinsertright,rowinsertabove,rowinsertbelow,rowmerge,colmerge,rowsplit,colsplit,coldelete,rowdelete,insert,delete".split(","), +function(a,b){var d=e(b,["prop","delete"])<0?c.plugin.getSelectedCell:c.plugin.getSelectedTable;c.addContextmenu({title:c.lang("table"+b),click:function(){c.loadPlugin("table",function(){c.plugin.table[b]();c.hideMenu()})},cond:d,width:170,iconClass:"ke-icon-table"+b})});c.addContextmenu({title:"-"});h("selectall,justifyleft,justifycenter,justifyright,justifyfull,insertorderedlist,insertunorderedlist,indent,outdent,subscript,superscript,hr,print,bold,italic,underline,strikethrough,removeformat,unlink".split(","), +function(a,b){g[b]&&c.afterCreate(function(){$(this.edit.doc,g[b],function(){c.cmd.selection();c.clickToolbar(b)})});c.clickToolbar(b,function(){c.focus().exec(b,null)})});c.afterCreate(function(){function b(){g.range.moveToBookmark(e);g.select();ka&&(a("div."+i,f).each(function(){a(this).after("
    ").remove(!0)}),a("span.Apple-style-span",f).remove(!0),a("span.Apple-tab-span",f).remove(!0),a("span[style]",f).each(function(){a(this).css("white-space")=="nowrap"&&a(this).remove(!0)}),a("meta",f).remove()); +var d=f[0].innerHTML;f.remove();d!==""&&(ka&&(d=d.replace(/(
    )\1/ig,"$1")),c.pasteType===2&&(d=d.replace(/(<(?:p|p\s[^>]*)>) *(<\/p>)/ig,""),/schemas-microsoft-com|worddocument|mso-\w+/i.test(d)?d=U(d,c.filterMode?c.htmlTags:a.options.htmlTags):(d=H(d,c.filterMode?c.htmlTags:null),d=c.beforeSetHtml(d))),c.pasteType===1&&(d=d.replace(/ /ig," "),d=d.replace(/\n\s*\n/g,"\n"),d=d.replace(/]*>/ig,"\n"),d=d.replace(/<\/p>]*>/ig,"\n"),d=d.replace(/<[^>]+>/g,""),d=d.replace(/ {2}/g,"  "), +c.newlineTag=="p"?/\n/.test(d)&&(d=d.replace(/^/,"

    ").replace(/$/,"

    ").replace(/\n/g,"

    ")):d=d.replace(/\n/g,"
    $&")),c.insertHtml(d,!0))}var d=c.edit.doc,g,e,f,i="__kindeditor_paste__",h=!1;a(d.body).bind("paste",function(l){if(c.pasteType===0)l.stop();else if(!h){h=!0;a("div."+i,d).remove();g=c.cmd.selection();e=g.range.createBookmark();f=a('

    ',d).css({position:"absolute",width:"1px",height:"1px",overflow:"hidden",left:"-1981px",top:a(e.start).pos().y+ +"px","white-space":"nowrap"});a(d.body).append(f);if(F){var n=g.range.get(!0);n.moveToElementText(f[0]);n.select();n.execCommand("paste");l.preventDefault()}else g.range.selectNodeContents(f[0]),g.select();setTimeout(function(){b();h=!1},0)}})});c.beforeGetHtml(function(a){F&&N<=8&&(a=a.replace(/]*data-ke-input-tag="([^"]*)"[^>]*>([\s\S]*?)<\/div>/ig,function(a,b){return unescape(b)}),a=a.replace(/(]*)?>)/ig,function(a,b,c){if(!/\s+type="[^"]+"/i.test(a))return b+' type="text"'+ +c;return a}));return a.replace(/(<(?:noscript|noscript\s[^>]*)>)([\s\S]*?)(<\/noscript>)/ig,function(a,b,c,d){return b+v(c).replace(/\s+/g," ")+d}).replace(/]*class="?ke-(flash|rm|media)"?[^>]*>/ig,function(a){var a=K(a),b=M(a.style||""),c=S(a["data-ke-tag"]),d=q(b.width,""),b=q(b.height,"");/px/i.test(d)&&(d=l(d));/px/i.test(b)&&(b=l(b));c.width=q(a.width,d);c.height=q(a.height,b);return Na(c)}).replace(/]*class="?ke-anchor"?[^>]*>/ig,function(a){a=K(a);return''}).replace(/]*data-ke-script-attr="([^"]*)"[^>]*>([\s\S]*?)<\/div>/ig,function(a,b,c){return""+unescape(c)+"<\/script>"}).replace(/]*data-ke-noscript-attr="([^"]*)"[^>]*>([\s\S]*?)<\/div>/ig,function(a,b,c){return""+unescape(c)+""}).replace(/(<[^>]*)data-ke-src="([^"]*)"([^>]*>)/ig,function(a,b,c){a=a.replace(/(\s+(?:href|src)=")[^"]*(")/i,function(a,b,d){return b+v(c)+d});return a=a.replace(/\s+data-ke-src="[^"]*"/i, +"")}).replace(/(<[^>]+\s)data-ke-(on\w+="[^"]*"[^>]*>)/ig,function(a,b,c){return b+c})});c.beforeSetHtml(function(a){F&&N<=8&&(a=a.replace(/]*>|<(select|button)[^>]*>[\s\S]*?<\/\1>/ig,function(a){var b=K(a);if(M(b.style||"").display=="none")return'
    ';return a}));return a.replace(/]*type="([^"]+)"[^>]*>(?:<\/embed>)?/ig,function(a){a=K(a);a.src=q(a.src,"");a.width=q(a.width,0);a.height=q(a.height,0);return kb(c.themesPath+ +"common/blank.gif",a)}).replace(/]*name="([^"]+)"[^>]*>(?:<\/a>)?/ig,function(a){var b=K(a);if(b.href!==d)return a;return''}).replace(/]*)>([\s\S]*?)<\/script>/ig,function(a,b,c){return'
    '+escape(c)+"
    "}).replace(/]*)>([\s\S]*?)<\/noscript>/ig,function(a,b,c){return'
    '+escape(c)+"
    "}).replace(/(<[^>]*)(href|src)="([^"]*)"([^>]*>)/ig,function(a,b,c,d,g){if(a.match(/\sdata-ke-src="[^"]*"/i))return a;return a=b+c+'="'+d+'" data-ke-src="'+s(d)+'"'+g}).replace(/(<[^>]+\s)(on\w+="[^"]*"[^>]*>)/ig,function(a,b,c){return b+"data-ke-"+c}).replace(/]*\s+border="0"[^>]*>/ig,function(a){if(a.indexOf("ke-zeroborder")>=0)return a;return O(a,"ke-zeroborder")})})})}})(window); +KindEditor.lang({source:"HTML\u4ee3\u7801",preview:"\u9884\u89c8",undo:"\u540e\u9000(Ctrl+Z)",redo:"\u524d\u8fdb(Ctrl+Y)",cut:"\u526a\u5207(Ctrl+X)",copy:"\u590d\u5236(Ctrl+C)",paste:"\u7c98\u8d34(Ctrl+V)",plainpaste:"\u7c98\u8d34\u4e3a\u65e0\u683c\u5f0f\u6587\u672c",wordpaste:"\u4eceWord\u7c98\u8d34",selectall:"\u5168\u9009(Ctrl+A)",justifyleft:"\u5de6\u5bf9\u9f50",justifycenter:"\u5c45\u4e2d",justifyright:"\u53f3\u5bf9\u9f50",justifyfull:"\u4e24\u7aef\u5bf9\u9f50",insertorderedlist:"\u7f16\u53f7", +insertunorderedlist:"\u9879\u76ee\u7b26\u53f7",indent:"\u589e\u52a0\u7f29\u8fdb",outdent:"\u51cf\u5c11\u7f29\u8fdb",subscript:"\u4e0b\u6807",superscript:"\u4e0a\u6807",formatblock:"\u6bb5\u843d",fontname:"\u5b57\u4f53",fontsize:"\u6587\u5b57\u5927\u5c0f",forecolor:"\u6587\u5b57\u989c\u8272",hilitecolor:"\u6587\u5b57\u80cc\u666f",bold:"\u7c97\u4f53(Ctrl+B)",italic:"\u659c\u4f53(Ctrl+I)",underline:"\u4e0b\u5212\u7ebf(Ctrl+U)",strikethrough:"\u5220\u9664\u7ebf",removeformat:"\u5220\u9664\u683c\u5f0f", +image:"\u56fe\u7247",multiimage:"\u6279\u91cf\u56fe\u7247\u4e0a\u4f20",flash:"Flash",media:"\u89c6\u97f3\u9891",table:"\u8868\u683c",tablecell:"\u5355\u5143\u683c",hr:"\u63d2\u5165\u6a2a\u7ebf",emoticons:"\u63d2\u5165\u8868\u60c5",link:"\u8d85\u7ea7\u94fe\u63a5",unlink:"\u53d6\u6d88\u8d85\u7ea7\u94fe\u63a5",fullscreen:"\u5168\u5c4f\u663e\u793a",about:"\u5173\u4e8e",print:"\u6253\u5370(Ctrl+P)",filemanager:"\u6587\u4ef6\u7a7a\u95f4",code:"\u63d2\u5165\u7a0b\u5e8f\u4ee3\u7801",map:"Google\u5730\u56fe", +baidumap:"\u767e\u5ea6\u5730\u56fe",lineheight:"\u884c\u8ddd",clearhtml:"\u6e05\u7406HTML\u4ee3\u7801",pagebreak:"\u63d2\u5165\u5206\u9875\u7b26",quickformat:"\u4e00\u952e\u6392\u7248",insertfile:"\u63d2\u5165\u6587\u4ef6",template:"\u63d2\u5165\u6a21\u677f",anchor:"\u951a\u70b9",yes:"\u786e\u5b9a",no:"\u53d6\u6d88",close:"\u5173\u95ed",editImage:"\u56fe\u7247\u5c5e\u6027",deleteImage:"\u5220\u9664\u56fe\u7247",editFlash:"Flash\u5c5e\u6027",deleteFlash:"\u5220\u9664Flash",editMedia:"\u89c6\u97f3\u9891\u5c5e\u6027", +deleteMedia:"\u5220\u9664\u89c6\u97f3\u9891",editLink:"\u8d85\u7ea7\u94fe\u63a5\u5c5e\u6027",deleteLink:"\u53d6\u6d88\u8d85\u7ea7\u94fe\u63a5",editAnchor:"\u951a\u70b9\u5c5e\u6027",deleteAnchor:"\u5220\u9664\u951a\u70b9",tableprop:"\u8868\u683c\u5c5e\u6027",tablecellprop:"\u5355\u5143\u683c\u5c5e\u6027",tableinsert:"\u63d2\u5165\u8868\u683c",tabledelete:"\u5220\u9664\u8868\u683c",tablecolinsertleft:"\u5de6\u4fa7\u63d2\u5165\u5217",tablecolinsertright:"\u53f3\u4fa7\u63d2\u5165\u5217",tablerowinsertabove:"\u4e0a\u65b9\u63d2\u5165\u884c", +tablerowinsertbelow:"\u4e0b\u65b9\u63d2\u5165\u884c",tablerowmerge:"\u5411\u4e0b\u5408\u5e76\u5355\u5143\u683c",tablecolmerge:"\u5411\u53f3\u5408\u5e76\u5355\u5143\u683c",tablerowsplit:"\u62c6\u5206\u884c",tablecolsplit:"\u62c6\u5206\u5217",tablecoldelete:"\u5220\u9664\u5217",tablerowdelete:"\u5220\u9664\u884c",noColor:"\u65e0\u989c\u8272",pleaseSelectFile:"\u8bf7\u9009\u62e9\u6587\u4ef6\u3002",invalidImg:"\u8bf7\u8f93\u5165\u6709\u6548\u7684URL\u5730\u5740\u3002\n\u53ea\u5141\u8bb8jpg,gif,bmp,png\u683c\u5f0f\u3002", +invalidMedia:"\u8bf7\u8f93\u5165\u6709\u6548\u7684URL\u5730\u5740\u3002\n\u53ea\u5141\u8bb8swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb\u683c\u5f0f\u3002",invalidWidth:"\u5bbd\u5ea6\u5fc5\u987b\u4e3a\u6570\u5b57\u3002",invalidHeight:"\u9ad8\u5ea6\u5fc5\u987b\u4e3a\u6570\u5b57\u3002",invalidBorder:"\u8fb9\u6846\u5fc5\u987b\u4e3a\u6570\u5b57\u3002",invalidUrl:"\u8bf7\u8f93\u5165\u6709\u6548\u7684URL\u5730\u5740\u3002",invalidRows:"\u884c\u6570\u4e3a\u5fc5\u9009\u9879\uff0c\u53ea\u5141\u8bb8\u8f93\u5165\u5927\u4e8e0\u7684\u6570\u5b57\u3002", +invalidCols:"\u5217\u6570\u4e3a\u5fc5\u9009\u9879\uff0c\u53ea\u5141\u8bb8\u8f93\u5165\u5927\u4e8e0\u7684\u6570\u5b57\u3002",invalidPadding:"\u8fb9\u8ddd\u5fc5\u987b\u4e3a\u6570\u5b57\u3002",invalidSpacing:"\u95f4\u8ddd\u5fc5\u987b\u4e3a\u6570\u5b57\u3002",invalidJson:"\u670d\u52a1\u5668\u53d1\u751f\u6545\u969c\u3002",uploadSuccess:"\u4e0a\u4f20\u6210\u529f\u3002",cutError:"\u60a8\u7684\u6d4f\u89c8\u5668\u5b89\u5168\u8bbe\u7f6e\u4e0d\u5141\u8bb8\u4f7f\u7528\u526a\u5207\u64cd\u4f5c\uff0c\u8bf7\u4f7f\u7528\u5feb\u6377\u952e(Ctrl+X)\u6765\u5b8c\u6210\u3002", +copyError:"\u60a8\u7684\u6d4f\u89c8\u5668\u5b89\u5168\u8bbe\u7f6e\u4e0d\u5141\u8bb8\u4f7f\u7528\u590d\u5236\u64cd\u4f5c\uff0c\u8bf7\u4f7f\u7528\u5feb\u6377\u952e(Ctrl+C)\u6765\u5b8c\u6210\u3002",pasteError:"\u60a8\u7684\u6d4f\u89c8\u5668\u5b89\u5168\u8bbe\u7f6e\u4e0d\u5141\u8bb8\u4f7f\u7528\u7c98\u8d34\u64cd\u4f5c\uff0c\u8bf7\u4f7f\u7528\u5feb\u6377\u952e(Ctrl+V)\u6765\u5b8c\u6210\u3002",ajaxLoading:"\u52a0\u8f7d\u4e2d\uff0c\u8bf7\u7a0d\u5019 ...",uploadLoading:"\u4e0a\u4f20\u4e2d\uff0c\u8bf7\u7a0d\u5019 ...", +uploadError:"\u4e0a\u4f20\u9519\u8bef","plainpaste.comment":"\u8bf7\u4f7f\u7528\u5feb\u6377\u952e(Ctrl+V)\u628a\u5185\u5bb9\u7c98\u8d34\u5230\u4e0b\u9762\u7684\u65b9\u6846\u91cc\u3002","wordpaste.comment":"\u8bf7\u4f7f\u7528\u5feb\u6377\u952e(Ctrl+V)\u628a\u5185\u5bb9\u7c98\u8d34\u5230\u4e0b\u9762\u7684\u65b9\u6846\u91cc\u3002","code.pleaseInput":"\u8bf7\u8f93\u5165\u7a0b\u5e8f\u4ee3\u7801\u3002","link.url":"URL","link.linkType":"\u6253\u5f00\u7c7b\u578b","link.newWindow":"\u65b0\u7a97\u53e3","link.selfWindow":"\u5f53\u524d\u7a97\u53e3", +"flash.url":"URL","flash.width":"\u5bbd\u5ea6","flash.height":"\u9ad8\u5ea6","flash.upload":"\u4e0a\u4f20","flash.viewServer":"\u6587\u4ef6\u7a7a\u95f4","media.url":"URL","media.width":"\u5bbd\u5ea6","media.height":"\u9ad8\u5ea6","media.autostart":"\u81ea\u52a8\u64ad\u653e","media.upload":"\u4e0a\u4f20","media.viewServer":"\u6587\u4ef6\u7a7a\u95f4","image.remoteImage":"\u7f51\u7edc\u56fe\u7247","image.localImage":"\u672c\u5730\u4e0a\u4f20","image.remoteUrl":"\u56fe\u7247\u5730\u5740","image.localUrl":"\u4e0a\u4f20\u6587\u4ef6", +"image.size":"\u56fe\u7247\u5927\u5c0f","image.width":"\u5bbd","image.height":"\u9ad8","image.resetSize":"\u91cd\u7f6e\u5927\u5c0f","image.align":"\u5bf9\u9f50\u65b9\u5f0f","image.defaultAlign":"\u9ed8\u8ba4\u65b9\u5f0f","image.leftAlign":"\u5de6\u5bf9\u9f50","image.rightAlign":"\u53f3\u5bf9\u9f50","image.imgTitle":"\u56fe\u7247\u8bf4\u660e","image.upload":"\u6d4f\u89c8...","image.viewServer":"\u56fe\u7247\u7a7a\u95f4","multiimage.uploadDesc":"\u5141\u8bb8\u7528\u6237\u540c\u65f6\u4e0a\u4f20<%=uploadLimit%>\u5f20\u56fe\u7247\uff0c\u5355\u5f20\u56fe\u7247\u5bb9\u91cf\u4e0d\u8d85\u8fc7<%=sizeLimit%>", +"multiimage.startUpload":"\u5f00\u59cb\u4e0a\u4f20","multiimage.clearAll":"\u5168\u90e8\u6e05\u7a7a","multiimage.insertAll":"\u5168\u90e8\u63d2\u5165","multiimage.queueLimitExceeded":"\u6587\u4ef6\u6570\u91cf\u8d85\u8fc7\u9650\u5236\u3002","multiimage.fileExceedsSizeLimit":"\u6587\u4ef6\u5927\u5c0f\u8d85\u8fc7\u9650\u5236\u3002","multiimage.zeroByteFile":"\u65e0\u6cd5\u4e0a\u4f20\u7a7a\u6587\u4ef6\u3002","multiimage.invalidFiletype":"\u6587\u4ef6\u7c7b\u578b\u4e0d\u6b63\u786e\u3002","multiimage.unknownError":"\u53d1\u751f\u5f02\u5e38\uff0c\u65e0\u6cd5\u4e0a\u4f20\u3002", +"multiimage.pending":"\u7b49\u5f85\u4e0a\u4f20","multiimage.uploadError":"\u4e0a\u4f20\u5931\u8d25","filemanager.emptyFolder":"\u7a7a\u6587\u4ef6\u5939","filemanager.moveup":"\u79fb\u5230\u4e0a\u4e00\u7ea7\u6587\u4ef6\u5939","filemanager.viewType":"\u663e\u793a\u65b9\u5f0f\uff1a","filemanager.viewImage":"\u7f29\u7565\u56fe","filemanager.listImage":"\u8be6\u7ec6\u4fe1\u606f","filemanager.orderType":"\u6392\u5e8f\u65b9\u5f0f\uff1a","filemanager.fileName":"\u540d\u79f0","filemanager.fileSize":"\u5927\u5c0f", +"filemanager.fileType":"\u7c7b\u578b","insertfile.url":"URL","insertfile.title":"\u6587\u4ef6\u8bf4\u660e","insertfile.upload":"\u4e0a\u4f20","insertfile.viewServer":"\u6587\u4ef6\u7a7a\u95f4","table.cells":"\u5355\u5143\u683c\u6570","table.rows":"\u884c\u6570","table.cols":"\u5217\u6570","table.size":"\u5927\u5c0f","table.width":"\u5bbd\u5ea6","table.height":"\u9ad8\u5ea6","table.percent":"%","table.px":"px","table.space":"\u8fb9\u8ddd\u95f4\u8ddd","table.padding":"\u8fb9\u8ddd","table.spacing":"\u95f4\u8ddd", +"table.align":"\u5bf9\u9f50\u65b9\u5f0f","table.textAlign":"\u6c34\u5e73\u5bf9\u9f50","table.verticalAlign":"\u5782\u76f4\u5bf9\u9f50","table.alignDefault":"\u9ed8\u8ba4","table.alignLeft":"\u5de6\u5bf9\u9f50","table.alignCenter":"\u5c45\u4e2d","table.alignRight":"\u53f3\u5bf9\u9f50","table.alignTop":"\u9876\u90e8","table.alignMiddle":"\u4e2d\u90e8","table.alignBottom":"\u5e95\u90e8","table.alignBaseline":"\u57fa\u7ebf","table.border":"\u8fb9\u6846","table.borderWidth":"\u8fb9\u6846","table.borderColor":"\u989c\u8272", +"table.backgroundColor":"\u80cc\u666f\u989c\u8272","map.address":"\u5730\u5740: ","map.search":"\u641c\u7d22","baidumap.address":"\u5730\u5740: ","baidumap.search":"\u641c\u7d22","baidumap.insertDynamicMap":"\u63d2\u5165\u52a8\u6001\u5730\u56fe","anchor.name":"\u951a\u70b9\u540d\u79f0","formatblock.formatBlock":{h1:"\u6807\u9898 1",h2:"\u6807\u9898 2",h3:"\u6807\u9898 3",h4:"\u6807\u9898 4",p:"\u6b63 \u6587"},"fontname.fontName":{SimSun:"\u5b8b\u4f53",NSimSun:"\u65b0\u5b8b\u4f53",FangSong_GB2312:"\u4eff\u5b8b_GB2312", +KaiTi_GB2312:"\u6977\u4f53_GB2312",SimHei:"\u9ed1\u4f53","Microsoft YaHei":"\u5fae\u8f6f\u96c5\u9ed1",Arial:"Arial","Arial Black":"Arial Black","Times New Roman":"Times New Roman","Courier New":"Courier New",Tahoma:"Tahoma",Verdana:"Verdana"},"lineheight.lineHeight":[{1:"\u5355\u500d\u884c\u8ddd"},{"1.5":"1.5\u500d\u884c\u8ddd"},{2:"2\u500d\u884c\u8ddd"},{"2.5":"2.5\u500d\u884c\u8ddd"},{3:"3\u500d\u884c\u8ddd"}],"template.selectTemplate":"\u53ef\u9009\u6a21\u677f","template.replaceContent":"\u66ff\u6362\u5f53\u524d\u5185\u5bb9", +"template.fileList":{"1.html":"\u56fe\u7247\u548c\u6587\u5b57","2.html":"\u8868\u683c","3.html":"\u9879\u76ee\u7f16\u53f7"}},"zh_CN"); +KindEditor.plugin("anchor",function(b){var d=this,f=d.lang("anchor.");d.plugin.anchor={edit:function(){var j=['
    ','",'
    '].join(""),j=d.createDialog({name:"anchor",width:300,title:d.lang("anchor"),body:j,yesBtn:{name:d.lang("yes"),click:function(){d.insertHtml('').hideDialog().focus()}}}).div, +e=b('input[name="name"]',j);(j=d.plugin.getSelectedAnchor())&&e.val(unescape(j.attr("data-ke-name")));e[0].focus();e[0].select()},"delete":function(){d.plugin.getSelectedAnchor().remove()}};d.clickToolbar("anchor",d.plugin.anchor.edit)}); +KindEditor.plugin("autoheight",function(b){function d(){var d=j.edit,f=d.doc.body;d.iframe.height(e);j.resize(null,Math.max((b.IE?f.scrollHeight:f.offsetHeight)+76,e))}function f(){e=b.removeUnit(j.height);j.edit.afterChange(d);var f=j.edit,m=f.doc.body;f.iframe[0].scroll="no";m.style.overflowY="hidden";d()}var j=this;if(j.autoHeightMode){var e;j.isCreated?f():j.afterCreate(f)}}); +KindEditor.plugin("baidumap",function(b){var d=this,f=d.lang("baidumap."),j=b.undef(d.mapWidth,558),e=b.undef(d.mapHeight,360);d.clickToolbar("baidumap",function(){function h(){v=r[0].contentWindow;p=b.iframeDoc(r)}var m=['
    ',f.address+' ','','','
    ',' ",'
    ','
    ',"
    "].join(""),m=d.createDialog({name:"baidumap",width:j+42,title:d.lang("baidumap"),body:m,yesBtn:{name:d.lang("yes"),click:function(){var b=v.map,f=b.getCenter(),f=f.lng+","+f.lat, +b=b.getZoom(),b=[s[0].checked?d.pluginsPath+"baidumap/index.html":"http://api.map.baidu.com/staticimage","?center="+encodeURIComponent(f),"&zoom="+encodeURIComponent(b),"&width="+j,"&height="+e,"&markers="+encodeURIComponent(f),"&markerStyles="+encodeURIComponent("l,A")].join("");s[0].checked?d.insertHtml(''):d.exec("insertimage",b);d.hideDialog().focus()}},beforeRemove:function(){l.remove();p&&p.write(""); +r.remove()}}),n=m.div,o=b('[name="address"]',n),l=b('[name="searchBtn"]',n),s=b('[name="insertDynamicMap"]',m.div),v,p,r=b('');r.bind("load",function(){r.unbind("load");b.IE?h():setTimeout(h,0)});b(".ke-map",n).replaceWith(r);l.click(function(){v.search(o.val())})})}); +KindEditor.plugin("clearhtml",function(b){var d=this;d.clickToolbar("clearhtml",function(){d.focus();var f=d.html(),f=f.replace(/(]*>)([\s\S]*?)(<\/script>)/ig,""),f=f.replace(/(]*>)([\s\S]*?)(<\/style>)/ig,""),f=b.formatHtml(f,{a:["href","target"],embed:["src","width","height","type","loop","autostart","quality",".width",".height","align","allowscriptaccess"],img:["src","width","height","border","alt","title",".width",".height"],table:["border"],"td,th":["rowspan","colspan"],"div,hr,br,tbody,tr,p,ol,ul,li,blockquote,h1,h2,h3,h4,h5,h6":[]}); +d.html(f);d.cmd.selection(!0);d.addBookmark()})}); +KindEditor.plugin("code",function(b){var d=this;d.clickToolbar("code",function(){var f=d.lang("code."),j=d.createDialog({name:"code",width:450,title:d.lang("code"),body:'
    ',yesBtn:{name:d.lang("yes"), +click:function(){var h=b(".ke-code-type",j.div).val(),m=e.val(),h='
    \n'+b.escape(m)+"
    ";b.trim(m)===""?(alert(f.pleaseInput),e[0].focus()):d.insertHtml(h).hideDialog().focus()}}}),e=b("textarea",j.div);e[0].focus()})}); +KindEditor.plugin("emoticons",function(b){var d=this,f=d.emoticonsPath||d.pluginsPath+"emoticons/images/",j=d.allowPreviewEmoticons===void 0?!0:d.allowPreviewEmoticons,e=1;d.clickToolbar("emoticons",function(){function h(e,h,l){B?e.mouseover(function(){h>D?(B.css("left",0),B.css("right","")):(B.css("left",""),B.css("right",0));G.attr("src",f+l+".gif");b(this).addClass("ke-on")}):e.mouseover(function(){b(this).addClass("ke-on")});e.mouseout(function(){b(this).removeClass("ke-on")});e.click(function(b){d.insertHtml('').hideMenu().focus();b.stop()})}function m(d,e){var l=document.createElement("table");e.append(l);B&&(b(l).mouseover(function(){B.show("block")}),b(l).mouseout(function(){B.hide()}),A.push(b(l)));l.className="ke-table";l.cellPadding=0;l.cellSpacing=0;l.border=0;for(var n=(d-1)*r+p,o=0;o').css("background-position","-"+24*n+"px 0px").css("background-image", +"url("+f+"static.gif)");q.append(u);A.push(q);n++}return l}function n(){b.each(A,function(){this.unbind()})}function o(b,d){b.click(function(b){n();C.parentNode.removeChild(C);u.remove();C=m(d,q);l(d);e=d;b.stop()})}function l(d){u=b('
    ');q.append(u);for(var e=1;e<=z;e++){if(d!==e){var f=b('
    ['+e+"]");o(f,e);u.append(f);A.push(f)}else u.append(b("@["+e+"]"));u.append(b("@ "))}}var s=5,v=9,p=0,r=s*v,z=Math.ceil(135/r),D=Math.floor(v/2),q=b('
    '), +A=[];d.createMenu({name:"emoticons",beforeRemove:function(){n()}}).div.append(q);var B,G;j&&(B=b('
    ').css("right",0),G=b(''),q.append(B),B.append(G));var C=m(e,q),u;l(e)})}); +KindEditor.plugin("filemanager",function(b){function d(b,d){d.is_dir?b.attr("title",d.filename):b.attr("title",d.filename+" ("+Math.ceil(d.filesize/1024)+"KB, "+d.datetime+")")}var f=this,j=b.undef(f.fileManagerJson,f.basePath+"php/file_manager_json.php"),e=f.pluginsPath+"filemanager/images/",h=f.lang("filemanager.");f.plugin.filemanagerDialog=function(m){function n(d,e,h){d="path="+d+"&order="+e+"&dir="+z;A.showLoading(f.lang("ajaxLoading"));b.ajax(b.addParam(j,d+"&"+(new Date).getTime()),function(b){A.hideLoading(); +h(b)})}function o(d,e,f,h){var l=b.formatUrl(e.current_url+f.filename,"absolute"),o=encodeURIComponent(e.current_dir_path+f.filename+"/");f.is_dir?d.click(function(){n(o,u.val(),h)}):f.is_photo?d.click(function(){q.call(this,l,f.filename)}):d.click(function(){q.call(this,l,f.filename)});I.push(d)}function l(d,e){function f(){C.val()=="VIEW"?n(d.current_dir_path,u.val(),v):n(d.current_dir_path,u.val(),s)}b.each(I,function(){this.unbind()});G.unbind();C.unbind();u.unbind();d.current_dir_path&&G.click(function(){n(d.moveup_dir_path, +u.val(),e)});C.change(f);u.change(f);B.html("")}function s(d){l(d,s);var f=document.createElement("table");f.className="ke-table";f.cellPadding=0;f.cellSpacing=0;f.border=0;B.append(f);for(var n=d.file_list,m=0,j=n.length;m'),q= +b(p[0].insertCell(0)).addClass("ke-cell ke-name").append(q).append(document.createTextNode(" "+r.filename));!r.is_dir||r.has_file?(p.css("cursor","pointer"),q.attr("title",r.filename),o(q,d,r,s)):q.attr("title",h.emptyFolder);b(p[0].insertCell(1)).addClass("ke-cell ke-size").html(r.is_dir?"-":Math.ceil(r.filesize/1024)+"KB");b(p[0].insertCell(2)).addClass("ke-cell ke-datetime").html(r.datetime)}}function v(f){l(f,v);for(var n=f.file_list,m=0,s=n.length;m'); +B.append(r);var p=b('
    ').mouseover(function(){b(this).addClass("ke-on")}).mouseout(function(){b(this).removeClass("ke-on")});r.append(p);var q=f.current_url+j.filename,q=b(''+j.filename+'');!j.is_dir||j.has_file?(p.css("cursor","pointer"),d(p,j),o(p,f,j,v)):p.attr("title",h.emptyFolder);p.append(q);r.append('
    '+ +j.filename+"
    ")}}var p=b.undef(m.width,650),r=b.undef(m.height,510),z=b.undef(m.dirName,""),D=b.undef(m.viewType,"VIEW").toUpperCase(),q=m.clickFn,m=['
    ',' ',''+h.moveup+"",'
    ',h.viewType+' ",h.orderType+'
    '].join(""),A=f.createDialog({name:"filemanager",width:p,height:r,title:f.lang("filemanager"), +body:m}),p=A.div,B=b(".ke-plugin-filemanager-body",p);b('[name="moveupImg"]',p);var G=b('[name="moveupLink"]',p);b('[name="viewServer"]',p);var C=b('[name="viewType"]',p),u=b('[name="orderType"]',p),I=[];C.val(D);n("",u.val(),D=="VIEW"?v:s);return A}}); +KindEditor.plugin("flash",function(b){var d=this,f=d.lang("flash."),j=b.undef(d.allowFlashUpload,!0),e=b.undef(d.allowFileManager,!1),h=b.undef(d.formatUploadUrl,!0),m=b.undef(d.extraFileUploadParams,{}),n=b.undef(d.filePostName,"imgFile"),o=b.undef(d.uploadJson,d.basePath+"php/upload_json.php");d.plugin.flash={edit:function(){var l=['
    ','",'  ', +'  ','','','
    ','",'
    ','",'
    '].join(""),s=d.createDialog({name:"flash",width:450,title:d.lang("flash"),body:l,yesBtn:{name:d.lang("yes"),click:function(){var e=b.trim(p.val()),f=r.val(),h=z.val();e=="http://"||b.invalidUrl(e)?(alert(d.lang("invalidUrl")),p[0].focus()):/^\d*$/.test(f)?/^\d*$/.test(h)?(e=b.mediaImg(d.themesPath+"common/blank.gif",{src:e,type:b.mediaType(".swf"),width:f, +height:h,quality:"high"}),d.insertHtml(e).hideDialog().focus()):(alert(d.lang("invalidHeight")),z[0].focus()):(alert(d.lang("invalidWidth")),r[0].focus())}}}),v=s.div,p=b('[name="url"]',v),l=b('[name="viewServer"]',v),r=b('[name="width"]',v),z=b('[name="height"]',v);p.val("http://");if(j){var D=b.uploadbutton({button:b(".ke-upload-button",v)[0],fieldName:n,extraParams:m,url:b.addParam(o,"dir=flash"),afterUpload:function(e){s.hideLoading();if(e.error===0){var f=e.url;h&&(f=b.formatUrl(f,"absolute")); +p.val(f);d.afterUpload&&d.afterUpload.call(d,f,e,"flash");alert(d.lang("uploadSuccess"))}else alert(e.message)},afterError:function(b){s.hideLoading();d.errorDialog(b)}});D.fileBox.change(function(){s.showLoading(d.lang("uploadLoading"));D.submit()})}else b(".ke-upload-button",v).hide();e?l.click(function(){d.loadPlugin("filemanager",function(){d.plugin.filemanagerDialog({viewType:"LIST",dirName:"flash",clickFn:function(e){d.dialogs.length>1&&(b('[name="url"]',v).val(e),d.afterSelectFile&&d.afterSelectFile.call(d, +e),d.hideDialog())}})})}):l.hide();if(l=d.plugin.getSelectedFlash()){var q=b.mediaAttrs(l.attr("data-ke-tag"));p.val(q.src);r.val(b.removeUnit(l.css("width"))||q.width||0);z.val(b.removeUnit(l.css("height"))||q.height||0)}p[0].focus();p[0].select()},"delete":function(){d.plugin.getSelectedFlash().remove();d.addBookmark()}};d.clickToolbar("flash",d.plugin.flash.edit)}); +KindEditor.plugin("image",function(b){var d=this,f=b.undef(d.allowImageUpload,!0),j=b.undef(d.allowImageRemote,!0),e=b.undef(d.formatUploadUrl,!0),h=b.undef(d.allowFileManager,!1),m=b.undef(d.uploadJson,d.basePath+"php/upload_json.php"),n=b.undef(d.imageTabIndex,0),o=d.pluginsPath+"image/images/",l=b.undef(d.extraFileUploadParams,{}),s=b.undef(d.filePostName,"imgFile"),v=b.undef(d.fillDescAfterUploadImage,!1),p=d.lang("image.");d.plugin.imageDialog=function(f){function n(b,d){M.val(b);K.val(d);W= +b;S=d}b.undef(f.imageWidth,"");b.undef(f.imageHeight,"");b.undef(f.imageTitle,"");b.undef(f.imageAlign,"");var j=b.undef(f.showRemote,!0),q=b.undef(f.showLocal,!0),A=b.undef(f.tabIndex,0),B=f.clickFn,G="kindeditor_upload_iframe_"+(new Date).getTime(),C=[],u;for(u in l)C.push('');var C=['
    "].join(""),I=d.createDialog({name:"image",width:q|| +h?450:400,height:q&&j?300:250,title:d.lang("image"),body:C,yesBtn:{name:d.lang("yes"),click:function(){if(!I.isLoading)if(q&&j&&H&&H.selectedIndex===1||!j)U.fileBox.val()==""?alert(d.lang("pleaseSelectFile")):(I.showLoading(d.lang("uploadLoading")),U.submit(),qa.val(""));else{var e=b.trim(T.val()),f=M.val(),h=K.val(),l=Q.val(),n="";R.each(function(){if(this.checked)return n=this.value,!1});e=="http://"||b.invalidUrl(e)?(alert(d.lang("invalidUrl")),T[0].focus()):/^\d*$/.test(f)?/^\d*$/.test(h)?B.call(d, +e,l,f,h,0,n):(alert(d.lang("invalidHeight")),K[0].focus()):(alert(d.lang("invalidWidth")),M[0].focus())}}},beforeRemove:function(){$.unbind();M.unbind();K.unbind();O.unbind()}}),E=I.div,T=b('[name="url"]',E),qa=b('[name="localUrl"]',E),$=b('[name="viewServer"]',E),M=b('.tab1 [name="width"]',E),K=b('.tab1 [name="height"]',E),O=b(".ke-refresh-btn",E),Q=b('.tab1 [name="title"]',E),R=b('.tab1 [name="align"]',E),H;j&&q?(H=b.tabs({src:b(".tabs",E),afterSelect:function(){}}),H.add({title:p.remoteImage,panel:b(".tab1", +E)}),H.add({title:p.localImage,panel:b(".tab2",E)}),H.select(A)):j?b(".tab1",E).show():q&&b(".tab2",E).show();var U=b.uploadbutton({button:b(".ke-upload-button",E)[0],fieldName:s,form:b(".ke-form",E),target:G,width:60,afterUpload:function(f){I.hideLoading();if(f.error===0){var h=f.url;e&&(h=b.formatUrl(h,"absolute"));d.afterUpload&&d.afterUpload.call(d,h,f,"image");v?(b(".ke-dialog-row #remoteUrl",E).val(h),b(".ke-tabs-li",E)[0].click(),b(".ke-refresh-btn",E).click()):B.call(d,h,f.title,f.width,f.height, +f.border,f.align)}else alert(f.message)},afterError:function(b){I.hideLoading();d.errorDialog(b)}});U.fileBox.change(function(){qa.val(U.fileBox.val())});h?$.click(function(){d.loadPlugin("filemanager",function(){d.plugin.filemanagerDialog({viewType:"VIEW",dirName:"image",clickFn:function(e){d.dialogs.length>1&&(b('[name="url"]',E).val(e),d.afterSelectFile&&d.afterSelectFile.call(d,e),d.hideDialog())}})})}):$.hide();var W=0,S=0;O.click(function(){var d=b('',document).css({position:"absolute", +visibility:"hidden",top:0,left:"-1000px"});d.bind("load",function(){n(d.width(),d.height());d.remove()});b(document.body).append(d)});M.change(function(){W>0&&K.val(Math.round(S/W*parseInt(this.value,10)))});K.change(function(){S>0&&M.val(Math.round(W/S*parseInt(this.value,10)))});T.val(f.imageUrl);n(f.imageWidth,f.imageHeight);Q.val(f.imageTitle);R.each(function(){if(this.value===f.imageAlign)return this.checked=!0,!1});j&&A===0&&(T[0].focus(),T[0].select());return I};d.plugin.image={edit:function(){var b= +d.plugin.getSelectedImage();d.plugin.imageDialog({imageUrl:b?b.attr("data-ke-src"):"http://",imageWidth:b?b.width():"",imageHeight:b?b.height():"",imageTitle:b?b.attr("title"):"",imageAlign:b?b.attr("align"):"",showRemote:j,showLocal:f,tabIndex:b?0:n,clickFn:function(e,f,h,l,n,o){b?(b.attr("src",e),b.attr("data-ke-src",e),b.attr("width",h),b.attr("height",l),b.attr("title",f),b.attr("align",o),b.attr("alt",f)):d.exec("insertimage",e,f,h,l,n,o);setTimeout(function(){d.hideDialog().focus()},0)}})}, +"delete":function(){var b=d.plugin.getSelectedImage();b.parent().name=="a"&&(b=b.parent());b.remove();d.addBookmark()}};d.clickToolbar("image",d.plugin.image.edit)}); +KindEditor.plugin("insertfile",function(b){var d=this,f=b.undef(d.allowFileUpload,!0),j=b.undef(d.allowFileManager,!1),e=b.undef(d.formatUploadUrl,!0),h=b.undef(d.uploadJson,d.basePath+"php/upload_json.php"),m=b.undef(d.extraFileUploadParams,{}),n=b.undef(d.filePostName,"imgFile"),o=d.lang("insertfile.");d.plugin.fileDialog=function(l){var s=b.undef(l.fileUrl,"http://"),v=b.undef(l.fileTitle,""),p=l.clickFn,l=['
    ','",'  ','  ','','','
    ','",'
    '].join(""), +r=d.createDialog({name:"insertfile",width:450,title:d.lang("insertfile"),body:l,yesBtn:{name:d.lang("yes"),click:function(){var e=b.trim(D.val()),f=q.val();e=="http://"||b.invalidUrl(e)?(alert(d.lang("invalidUrl")),D[0].focus()):(b.trim(f)===""&&(f=e),p.call(d,e,f))}}}),z=r.div,D=b('[name="url"]',z),l=b('[name="viewServer"]',z),q=b('[name="title"]',z);if(f){var A=b.uploadbutton({button:b(".ke-upload-button",z)[0],fieldName:n,url:b.addParam(h,"dir=file"),extraParams:m,afterUpload:function(f){r.hideLoading(); +if(f.error===0){var h=f.url;e&&(h=b.formatUrl(h,"absolute"));D.val(h);d.afterUpload&&d.afterUpload.call(d,h,f,"insertfile");alert(d.lang("uploadSuccess"))}else alert(f.message)},afterError:function(b){r.hideLoading();d.errorDialog(b)}});A.fileBox.change(function(){r.showLoading(d.lang("uploadLoading"));A.submit()})}else b(".ke-upload-button",z).hide();j?l.click(function(){d.loadPlugin("filemanager",function(){d.plugin.filemanagerDialog({viewType:"LIST",dirName:"file",clickFn:function(e){d.dialogs.length> +1&&(b('[name="url"]',z).val(e),d.afterSelectFile&&d.afterSelectFile.call(d,e),d.hideDialog())}})})}):l.hide();D.val(s);q.val(v);D[0].focus();D[0].select()};d.clickToolbar("insertfile",function(){d.plugin.fileDialog({clickFn:function(b,e){d.insertHtml(''+e+"").hideDialog().focus()}})})}); +KindEditor.plugin("lineheight",function(b){var d=this,f=d.lang("lineheight.");d.clickToolbar("lineheight",function(){var j="",e=d.cmd.commonNode({"*":".line-height"});e&&(j=e.css("line-height"));var h=d.createMenu({name:"lineheight",width:150});b.each(f.lineHeight,function(e,f){b.each(f,function(b,e){h.addItem({title:e,checked:j===b,click:function(){d.cmd.toggle('',{span:".line-height="+b});d.updateState();d.addBookmark();d.hideMenu()}})})})})}); +KindEditor.plugin("link",function(b){var d=this;d.plugin.link={edit:function(){var f=d.lang("link."),j='
    ',j=d.createDialog({name:"link",width:450,title:d.lang("link"), +body:j,yesBtn:{name:d.lang("yes"),click:function(){var f=b.trim(e.val());f=="http://"||b.invalidUrl(f)?(alert(d.lang("invalidUrl")),e[0].focus()):d.exec("createlink",f,h.val()).hideDialog().focus()}}}).div,e=b('input[name="url"]',j),h=b('select[name="type"]',j);e.val("http://");h[0].options[0]=new Option(f.newWindow,"_blank");h[0].options[1]=new Option(f.selfWindow,"");d.cmd.selection();if(f=d.plugin.getSelectedLink())d.cmd.range.selectNode(f[0]),d.cmd.select(),e.val(f.attr("data-ke-src")),h.val(f.attr("target")); +e[0].focus();e[0].select()},"delete":function(){d.exec("unlink",null)}};d.clickToolbar("link",d.plugin.link.edit)}); +KindEditor.plugin("map",function(b){var d=this,f=d.lang("map.");d.clickToolbar("map",function(){function j(){n=l[0].contentWindow;o=b.iframeDoc(l)}var e=['
    ',f.address+' ','','','
    '].join(""), +e=d.createDialog({name:"map",width:600,title:d.lang("map"),body:e,yesBtn:{name:d.lang("yes"),click:function(){var b=n.map,e=b.getCenter().lat()+","+b.getCenter().lng(),f=b.getZoom(),b=b.getMapTypeId(),h="http://maps.googleapis.com/maps/api/staticmap";h+="?center="+encodeURIComponent(e);h+="&zoom="+encodeURIComponent(f);h+="&size=558x360";h+="&maptype="+encodeURIComponent(b);h+="&markers="+encodeURIComponent(e);h+="&language="+d.langType;h+="&sensor=false";d.exec("insertimage",h).hideDialog().focus()}}, +beforeRemove:function(){m.remove();o&&o.write("");l.remove()}}).div,h=b('[name="address"]',e),m=b('[name="searchBtn"]',e),n,o;['\n\n',''; + }) + .replace(/]*data-ke-noscript-attr="([^"]*)"[^>]*>([\s\S]*?)<\/div>/ig, function(full, attr, code) { + return '' + unescape(code) + ''; + }) + .replace(/(<[^>]*)data-ke-src="([^"]*)"([^>]*>)/ig, function(full, start, src, end) { + full = full.replace(/(\s+(?:href|src)=")[^"]*(")/i, function($0, $1, $2) { + return $1 + _unescape(src) + $2; + }); + full = full.replace(/\s+data-ke-src="[^"]*"/i, ''); + return full; + }) + .replace(/(<[^>]+\s)data-ke-(on\w+="[^"]*"[^>]*>)/ig, function(full, start, end) { + return start + end; + }); + }); + self.beforeSetHtml(function(html) { + if (_IE && _V <= 8) { + html = html.replace(/]*>|<(select|button)[^>]*>[\s\S]*?<\/\1>/ig, function(full) { + var attrs = _getAttrList(full); + var styles = _getCssList(attrs.style || ''); + if (styles.display == 'none') { + return '
    '; + } + return full; + }); + } + return html.replace(/]*type="([^"]+)"[^>]*>(?:<\/embed>)?/ig, function(full) { + var attrs = _getAttrList(full); + attrs.src = _undef(attrs.src, ''); + attrs.width = _undef(attrs.width, 0); + attrs.height = _undef(attrs.height, 0); + return _mediaImg(self.themesPath + 'common/blank.gif', attrs); + }) + .replace(/]*name="([^"]+)"[^>]*>(?:<\/a>)?/ig, function(full) { + var attrs = _getAttrList(full); + if (attrs.href !== undefined) { + return full; + } + return ''; + }) + .replace(/]*)>([\s\S]*?)<\/script>/ig, function(full, attr, code) { + return '
    ' + escape(code) + '
    '; + }) + .replace(/]*)>([\s\S]*?)<\/noscript>/ig, function(full, attr, code) { + return '
    ' + escape(code) + '
    '; + }) + .replace(/(<[^>]*)(href|src)="([^"]*)"([^>]*>)/ig, function(full, start, key, src, end) { + if (full.match(/\sdata-ke-src="[^"]*"/i)) { + return full; + } + full = start + key + '="' + src + '"' + ' data-ke-src="' + _escape(src) + '"' + end; + return full; + }) + .replace(/(<[^>]+\s)(on\w+="[^"]*"[^>]*>)/ig, function(full, start, end) { + return start + 'data-ke-' + end; + }) + .replace(/]*\s+border="0"[^>]*>/ig, function(full) { + if (full.indexOf('ke-zeroborder') >= 0) { + return full; + } + return _addClassToTag(full, 'ke-zeroborder'); + }); + }); +}); +})(window); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.lang({ + source : 'HTML代码', + preview : '预览', + undo : '后退(Ctrl+Z)', + redo : '前进(Ctrl+Y)', + cut : '剪切(Ctrl+X)', + copy : '复制(Ctrl+C)', + paste : '粘贴(Ctrl+V)', + plainpaste : '粘贴为无格式文本', + wordpaste : '从Word粘贴', + selectall : '全选(Ctrl+A)', + justifyleft : '左对齐', + justifycenter : '居中', + justifyright : '右对齐', + justifyfull : '两端对齐', + insertorderedlist : '编号', + insertunorderedlist : '项目符号', + indent : '增加缩进', + outdent : '减少缩进', + subscript : '下标', + superscript : '上标', + formatblock : '段落', + fontname : '字体', + fontsize : '文字大小', + forecolor : '文字颜色', + hilitecolor : '文字背景', + bold : '粗体(Ctrl+B)', + italic : '斜体(Ctrl+I)', + underline : '下划线(Ctrl+U)', + strikethrough : '删除线', + removeformat : '删除格式', + image : '图片', + multiimage : '批量图片上传', + flash : 'Flash', + media : '视音频', + table : '表格', + tablecell : '单元格', + hr : '插入横线', + emoticons : '插入表情', + link : '超级链接', + unlink : '取消超级链接', + fullscreen : '全屏显示', + about : '关于', + print : '打印(Ctrl+P)', + filemanager : '文件空间', + code : '插入程序代码', + map : 'Google地图', + baidumap : '百度地图', + lineheight : '行距', + clearhtml : '清理HTML代码', + pagebreak : '插入分页符', + quickformat : '一键排版', + insertfile : '插入文件', + template : '插入模板', + anchor : '锚点', + yes : '确定', + no : '取消', + close : '关闭', + editImage : '图片属性', + deleteImage : '删除图片', + editFlash : 'Flash属性', + deleteFlash : '删除Flash', + editMedia : '视音频属性', + deleteMedia : '删除视音频', + editLink : '超级链接属性', + deleteLink : '取消超级链接', + editAnchor : '锚点属性', + deleteAnchor : '删除锚点', + tableprop : '表格属性', + tablecellprop : '单元格属性', + tableinsert : '插入表格', + tabledelete : '删除表格', + tablecolinsertleft : '左侧插入列', + tablecolinsertright : '右侧插入列', + tablerowinsertabove : '上方插入行', + tablerowinsertbelow : '下方插入行', + tablerowmerge : '向下合并单元格', + tablecolmerge : '向右合并单元格', + tablerowsplit : '拆分行', + tablecolsplit : '拆分列', + tablecoldelete : '删除列', + tablerowdelete : '删除行', + noColor : '无颜色', + pleaseSelectFile : '请选择文件。', + invalidImg : "请输入有效的URL地址。\n只允许jpg,gif,bmp,png格式。", + invalidMedia : "请输入有效的URL地址。\n只允许swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb格式。", + invalidWidth : "宽度必须为数字。", + invalidHeight : "高度必须为数字。", + invalidBorder : "边框必须为数字。", + invalidUrl : "请输入有效的URL地址。", + invalidRows : '行数为必选项,只允许输入大于0的数字。', + invalidCols : '列数为必选项,只允许输入大于0的数字。', + invalidPadding : '边距必须为数字。', + invalidSpacing : '间距必须为数字。', + invalidJson : '服务器发生故障。', + uploadSuccess : '上传成功。', + cutError : '您的浏览器安全设置不允许使用剪切操作,请使用快捷键(Ctrl+X)来完成。', + copyError : '您的浏览器安全设置不允许使用复制操作,请使用快捷键(Ctrl+C)来完成。', + pasteError : '您的浏览器安全设置不允许使用粘贴操作,请使用快捷键(Ctrl+V)来完成。', + ajaxLoading : '加载中,请稍候 ...', + uploadLoading : '上传中,请稍候 ...', + uploadError : '上传错误', + 'plainpaste.comment' : '请使用快捷键(Ctrl+V)把内容粘贴到下面的方框里。', + 'wordpaste.comment' : '请使用快捷键(Ctrl+V)把内容粘贴到下面的方框里。', + 'code.pleaseInput' : '请输入程序代码。', + 'link.url' : 'URL', + 'link.linkType' : '打开类型', + 'link.newWindow' : '新窗口', + 'link.selfWindow' : '当前窗口', + 'flash.url' : 'URL', + 'flash.width' : '宽度', + 'flash.height' : '高度', + 'flash.upload' : '上传', + 'flash.viewServer' : '文件空间', + 'media.url' : 'URL', + 'media.width' : '宽度', + 'media.height' : '高度', + 'media.autostart' : '自动播放', + 'media.upload' : '上传', + 'media.viewServer' : '文件空间', + 'image.remoteImage' : '网络图片', + 'image.localImage' : '本地上传', + 'image.remoteUrl' : '图片地址', + 'image.localUrl' : '上传文件', + 'image.size' : '图片大小', + 'image.width' : '宽', + 'image.height' : '高', + 'image.resetSize' : '重置大小', + 'image.align' : '对齐方式', + 'image.defaultAlign' : '默认方式', + 'image.leftAlign' : '左对齐', + 'image.rightAlign' : '右对齐', + 'image.imgTitle' : '图片说明', + 'image.upload' : '浏览...', + 'image.viewServer' : '图片空间', + 'multiimage.uploadDesc' : '允许用户同时上传<%=uploadLimit%>张图片,单张图片容量不超过<%=sizeLimit%>', + 'multiimage.startUpload' : '开始上传', + 'multiimage.clearAll' : '全部清空', + 'multiimage.insertAll' : '全部插入', + 'multiimage.queueLimitExceeded' : '文件数量超过限制。', + 'multiimage.fileExceedsSizeLimit' : '文件大小超过限制。', + 'multiimage.zeroByteFile' : '无法上传空文件。', + 'multiimage.invalidFiletype' : '文件类型不正确。', + 'multiimage.unknownError' : '发生异常,无法上传。', + 'multiimage.pending' : '等待上传', + 'multiimage.uploadError' : '上传失败', + 'filemanager.emptyFolder' : '空文件夹', + 'filemanager.moveup' : '移到上一级文件夹', + 'filemanager.viewType' : '显示方式:', + 'filemanager.viewImage' : '缩略图', + 'filemanager.listImage' : '详细信息', + 'filemanager.orderType' : '排序方式:', + 'filemanager.fileName' : '名称', + 'filemanager.fileSize' : '大小', + 'filemanager.fileType' : '类型', + 'insertfile.url' : 'URL', + 'insertfile.title' : '文件说明', + 'insertfile.upload' : '上传', + 'insertfile.viewServer' : '文件空间', + 'table.cells' : '单元格数', + 'table.rows' : '行数', + 'table.cols' : '列数', + 'table.size' : '大小', + 'table.width' : '宽度', + 'table.height' : '高度', + 'table.percent' : '%', + 'table.px' : 'px', + 'table.space' : '边距间距', + 'table.padding' : '边距', + 'table.spacing' : '间距', + 'table.align' : '对齐方式', + 'table.textAlign' : '水平对齐', + 'table.verticalAlign' : '垂直对齐', + 'table.alignDefault' : '默认', + 'table.alignLeft' : '左对齐', + 'table.alignCenter' : '居中', + 'table.alignRight' : '右对齐', + 'table.alignTop' : '顶部', + 'table.alignMiddle' : '中部', + 'table.alignBottom' : '底部', + 'table.alignBaseline' : '基线', + 'table.border' : '边框', + 'table.borderWidth' : '边框', + 'table.borderColor' : '颜色', + 'table.backgroundColor' : '背景颜色', + 'map.address' : '地址: ', + 'map.search' : '搜索', + 'baidumap.address' : '地址: ', + 'baidumap.search' : '搜索', + 'baidumap.insertDynamicMap' : '插入动态地图', + 'anchor.name' : '锚点名称', + 'formatblock.formatBlock' : { + h1 : '标题 1', + h2 : '标题 2', + h3 : '标题 3', + h4 : '标题 4', + p : '正 文' + }, + 'fontname.fontName' : { + 'SimSun' : '宋体', + 'NSimSun' : '新宋体', + 'FangSong_GB2312' : '仿宋_GB2312', + 'KaiTi_GB2312' : '楷体_GB2312', + 'SimHei' : '黑体', + 'Microsoft YaHei' : '微软雅黑', + 'Arial' : 'Arial', + 'Arial Black' : 'Arial Black', + 'Times New Roman' : 'Times New Roman', + 'Courier New' : 'Courier New', + 'Tahoma' : 'Tahoma', + 'Verdana' : 'Verdana' + }, + 'lineheight.lineHeight' : [ + {'1' : '单倍行距'}, + {'1.5' : '1.5倍行距'}, + {'2' : '2倍行距'}, + {'2.5' : '2.5倍行距'}, + {'3' : '3倍行距'} + ], + 'template.selectTemplate' : '可选模板', + 'template.replaceContent' : '替换当前内容', + 'template.fileList' : { + '1.html' : '图片和文字', + '2.html' : '表格', + '3.html' : '项目编号' + } +}, 'zh_CN'); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('anchor', function(K) { + var self = this, name = 'anchor', lang = self.lang(name + '.'); + self.plugin.anchor = { + edit : function() { + var html = ['
    ', + '
    ', + '', + '', + '
    ', + '
    '].join(''); + var dialog = self.createDialog({ + name : name, + width : 300, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + self.insertHtml('').hideDialog().focus(); + } + } + }); + var div = dialog.div, + nameBox = K('input[name="name"]', div); + var img = self.plugin.getSelectedAnchor(); + if (img) { + nameBox.val(unescape(img.attr('data-ke-name'))); + } + nameBox[0].focus(); + nameBox[0].select(); + }, + 'delete' : function() { + self.plugin.getSelectedAnchor().remove(); + } + }; + self.clickToolbar(name, self.plugin.anchor.edit); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('autoheight', function(K) { + var self = this; + + if (!self.autoHeightMode) { + return; + } + + var minHeight; + + function hideScroll() { + var edit = self.edit; + var body = edit.doc.body; + edit.iframe[0].scroll = 'no'; + body.style.overflowY = 'hidden'; + } + + function resetHeight() { + var edit = self.edit; + var body = edit.doc.body; + edit.iframe.height(minHeight); + self.resize(null, Math.max((K.IE ? body.scrollHeight : body.offsetHeight) + 76, minHeight)); + } + + function init() { + minHeight = K.removeUnit(self.height); + + self.edit.afterChange(resetHeight); + hideScroll(); + resetHeight(); + } + + if (self.isCreated) { + init(); + } else { + self.afterCreate(init); + } +}); + +/* +* 如何实现真正的自动高度? +* 修改编辑器高度之后,再次获取body内容高度时,最小值只会是当前iframe的设置高度,这样就导致高度只增不减。 +* 所以每次获取body内容高度之前,先将iframe的高度重置为最小高度,这样就能获取body的实际高度。 +* 由此就实现了真正的自动高度 +* 测试:chrome、firefox、IE9、IE8 +* */ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +// Baidu Maps: http://dev.baidu.com/wiki/map/index.php?title=%E9%A6%96%E9%A1%B5 + +KindEditor.plugin('baidumap', function(K) { + var self = this, name = 'baidumap', lang = self.lang(name + '.'); + var mapWidth = K.undef(self.mapWidth, 558); + var mapHeight = K.undef(self.mapHeight, 360); + self.clickToolbar(name, function() { + var html = ['
    ', + '
    ', + // left start + '
    ', + lang.address + ' ', + '', + '', + '', + '
    ', + // right start + '
    ', + ' ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    '].join(''); + var dialog = self.createDialog({ + name : name, + width : mapWidth + 42, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var map = win.map; + var centerObj = map.getCenter(); + var center = centerObj.lng + ',' + centerObj.lat; + var zoom = map.getZoom(); + var url = [checkbox[0].checked ? self.pluginsPath + 'baidumap/index.html' : 'http://api.map.baidu.com/staticimage', + '?center=' + encodeURIComponent(center), + '&zoom=' + encodeURIComponent(zoom), + '&width=' + mapWidth, + '&height=' + mapHeight, + '&markers=' + encodeURIComponent(center), + '&markerStyles=' + encodeURIComponent('l,A')].join(''); + if (checkbox[0].checked) { + self.insertHtml(''); + } else { + self.exec('insertimage', url); + } + self.hideDialog().focus(); + } + }, + beforeRemove : function() { + searchBtn.remove(); + if (doc) { + doc.write(''); + } + iframe.remove(); + } + }); + var div = dialog.div, + addressBox = K('[name="address"]', div), + searchBtn = K('[name="searchBtn"]', div), + checkbox = K('[name="insertDynamicMap"]', dialog.div), + win, doc; + var iframe = K(''); + function ready() { + win = iframe[0].contentWindow; + doc = K.iframeDoc(iframe); + } + iframe.bind('load', function() { + iframe.unbind('load'); + if (K.IE) { + ready(); + } else { + setTimeout(ready, 0); + } + }); + K('.ke-map', div).replaceWith(iframe); + // search map + searchBtn.click(function() { + win.search(addressBox.val()); + }); + }); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('clearhtml', function(K) { + var self = this, name = 'clearhtml'; + self.clickToolbar(name, function() { + self.focus(); + var html = self.html(); + html = html.replace(/(]*>)([\s\S]*?)(<\/script>)/ig, ''); + html = html.replace(/(]*>)([\s\S]*?)(<\/style>)/ig, ''); + html = K.formatHtml(html, { + a : ['href', 'target'], + embed : ['src', 'width', 'height', 'type', 'loop', 'autostart', 'quality', '.width', '.height', 'align', 'allowscriptaccess'], + img : ['src', 'width', 'height', 'border', 'alt', 'title', '.width', '.height'], + table : ['border'], + 'td,th' : ['rowspan', 'colspan'], + 'div,hr,br,tbody,tr,p,ol,ul,li,blockquote,h1,h2,h3,h4,h5,h6' : [] + }); + self.html(html); + self.cmd.selection(true); + self.addBookmark(); + }); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +// google code prettify: http://google-code-prettify.googlecode.com/ +// http://google-code-prettify.googlecode.com/ + +KindEditor.plugin('code', function(K) { + var self = this, name = 'code'; + self.clickToolbar(name, function() { + var lang = self.lang(name + '.'), + html = ['
    ', + '
    ', + '', + '
    ', + '', + '
    '].join(''), + dialog = self.createDialog({ + name : name, + width : 450, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var type = K('.ke-code-type', dialog.div).val(), + code = textarea.val(), + cls = type === '' ? '' : ' lang-' + type, + html = '
    \n' + K.escape(code) + '
    '; + if (K.trim(code) === '') { + alert(lang.pleaseInput); + textarea[0].focus(); + return; + } + self.insertHtml(html).hideDialog().focus(); + } + } + }), + textarea = K('textarea', dialog.div); + textarea[0].focus(); + }); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('emoticons', function(K) { + var self = this, name = 'emoticons', + path = (self.emoticonsPath || self.pluginsPath + 'emoticons/images/'), + allowPreview = self.allowPreviewEmoticons === undefined ? true : self.allowPreviewEmoticons, + currentPageNum = 1; + self.clickToolbar(name, function() { + var rows = 5, cols = 9, total = 135, startNum = 0, + cells = rows * cols, pages = Math.ceil(total / cells), + colsHalf = Math.floor(cols / 2), + wrapperDiv = K('
    '), + elements = [], + menu = self.createMenu({ + name : name, + beforeRemove : function() { + removeEvent(); + } + }); + menu.div.append(wrapperDiv); + var previewDiv, previewImg; + if (allowPreview) { + previewDiv = K('
    ').css('right', 0); + previewImg = K(''); + wrapperDiv.append(previewDiv); + previewDiv.append(previewImg); + } + function bindCellEvent(cell, j, num) { + if (previewDiv) { + cell.mouseover(function() { + if (j > colsHalf) { + previewDiv.css('left', 0); + previewDiv.css('right', ''); + } else { + previewDiv.css('left', ''); + previewDiv.css('right', 0); + } + previewImg.attr('src', path + num + '.gif'); + K(this).addClass('ke-on'); + }); + } else { + cell.mouseover(function() { + K(this).addClass('ke-on'); + }); + } + cell.mouseout(function() { + K(this).removeClass('ke-on'); + }); + cell.click(function(e) { + self.insertHtml('').hideMenu().focus(); + e.stop(); + }); + } + function createEmoticonsTable(pageNum, parentDiv) { + var table = document.createElement('table'); + parentDiv.append(table); + if (previewDiv) { + K(table).mouseover(function() { + previewDiv.show('block'); + }); + K(table).mouseout(function() { + previewDiv.hide(); + }); + elements.push(K(table)); + } + table.className = 'ke-table'; + table.cellPadding = 0; + table.cellSpacing = 0; + table.border = 0; + var num = (pageNum - 1) * cells + startNum; + for (var i = 0; i < rows; i++) { + var row = table.insertRow(i); + for (var j = 0; j < cols; j++) { + var cell = K(row.insertCell(j)); + cell.addClass('ke-cell'); + bindCellEvent(cell, j, num); + var span = K('') + .css('background-position', '-' + (24 * num) + 'px 0px') + .css('background-image', 'url(' + path + 'static.gif)'); + cell.append(span); + elements.push(cell); + num++; + } + } + return table; + } + var table = createEmoticonsTable(currentPageNum, wrapperDiv); + function removeEvent() { + K.each(elements, function() { + this.unbind(); + }); + } + var pageDiv; + function bindPageEvent(el, pageNum) { + el.click(function(e) { + removeEvent(); + table.parentNode.removeChild(table); + pageDiv.remove(); + table = createEmoticonsTable(pageNum, wrapperDiv); + createPageTable(pageNum); + currentPageNum = pageNum; + e.stop(); + }); + } + function createPageTable(currentPageNum) { + pageDiv = K('
    '); + wrapperDiv.append(pageDiv); + for (var pageNum = 1; pageNum <= pages; pageNum++) { + if (currentPageNum !== pageNum) { + var a = K('
    [' + pageNum + ']'); + bindPageEvent(a, pageNum); + pageDiv.append(a); + elements.push(a); + } else { + pageDiv.append(K('@[' + pageNum + ']')); + } + pageDiv.append(K('@ ')); + } + } + createPageTable(currentPageNum); + }); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('filemanager', function(K) { + var self = this, name = 'filemanager', + fileManagerJson = K.undef(self.fileManagerJson, self.basePath + 'php/file_manager_json.php'), + imgPath = self.pluginsPath + name + '/images/', + lang = self.lang(name + '.'); + function makeFileTitle(filename, filesize, datetime) { + return filename + ' (' + Math.ceil(filesize / 1024) + 'KB, ' + datetime + ')'; + } + function bindTitle(el, data) { + if (data.is_dir) { + el.attr('title', data.filename); + } else { + el.attr('title', makeFileTitle(data.filename, data.filesize, data.datetime)); + } + } + self.plugin.filemanagerDialog = function(options) { + var width = K.undef(options.width, 650), + height = K.undef(options.height, 510), + dirName = K.undef(options.dirName, ''), + viewType = K.undef(options.viewType, 'VIEW').toUpperCase(), // "LIST" or "VIEW" + clickFn = options.clickFn; + var html = [ + '
    ', + // header start + '
    ', + // left start + '
    ', + ' ', + '' + lang.moveup + '', + '
    ', + // right start + '
    ', + lang.viewType + ' ', + lang.orderType + ' ', + '
    ', + '
    ', + '
    ', + // body start + '
    ', + '
    ' + ].join(''); + var dialog = self.createDialog({ + name : name, + width : width, + height : height, + title : self.lang(name), + body : html + }), + div = dialog.div, + bodyDiv = K('.ke-plugin-filemanager-body', div), + moveupImg = K('[name="moveupImg"]', div), + moveupLink = K('[name="moveupLink"]', div), + viewServerBtn = K('[name="viewServer"]', div), + viewTypeBox = K('[name="viewType"]', div), + orderTypeBox = K('[name="orderType"]', div); + function reloadPage(path, order, func) { + var param = 'path=' + path + '&order=' + order + '&dir=' + dirName; + dialog.showLoading(self.lang('ajaxLoading')); + K.ajax(K.addParam(fileManagerJson, param + '&' + new Date().getTime()), function(data) { + dialog.hideLoading(); + func(data); + }); + } + var elList = []; + function bindEvent(el, result, data, createFunc) { + var fileUrl = K.formatUrl(result.current_url + data.filename, 'absolute'), + dirPath = encodeURIComponent(result.current_dir_path + data.filename + '/'); + if (data.is_dir) { + el.click(function(e) { + reloadPage(dirPath, orderTypeBox.val(), createFunc); + }); + } else if (data.is_photo) { + el.click(function(e) { + clickFn.call(this, fileUrl, data.filename); + }); + } else { + el.click(function(e) { + clickFn.call(this, fileUrl, data.filename); + }); + } + elList.push(el); + } + function createCommon(result, createFunc) { + // remove events + K.each(elList, function() { + this.unbind(); + }); + moveupLink.unbind(); + viewTypeBox.unbind(); + orderTypeBox.unbind(); + // add events + if (result.current_dir_path) { + moveupLink.click(function(e) { + reloadPage(result.moveup_dir_path, orderTypeBox.val(), createFunc); + }); + } + function changeFunc() { + if (viewTypeBox.val() == 'VIEW') { + reloadPage(result.current_dir_path, orderTypeBox.val(), createView); + } else { + reloadPage(result.current_dir_path, orderTypeBox.val(), createList); + } + } + viewTypeBox.change(changeFunc); + orderTypeBox.change(changeFunc); + bodyDiv.html(''); + } + function createList(result) { + createCommon(result, createList); + var table = document.createElement('table'); + table.className = 'ke-table'; + table.cellPadding = 0; + table.cellSpacing = 0; + table.border = 0; + bodyDiv.append(table); + var fileList = result.file_list; + for (var i = 0, len = fileList.length; i < len; i++) { + var data = fileList[i], row = K(table.insertRow(i)); + row.mouseover(function(e) { + K(this).addClass('ke-on'); + }) + .mouseout(function(e) { + K(this).removeClass('ke-on'); + }); + var iconUrl = imgPath + (data.is_dir ? 'folder-16.gif' : 'file-16.gif'), + img = K('' + data.filename + ''), + cell0 = K(row[0].insertCell(0)).addClass('ke-cell ke-name').append(img).append(document.createTextNode(' ' + data.filename)); + if (!data.is_dir || data.has_file) { + row.css('cursor', 'pointer'); + cell0.attr('title', data.filename); + bindEvent(cell0, result, data, createList); + } else { + cell0.attr('title', lang.emptyFolder); + } + K(row[0].insertCell(1)).addClass('ke-cell ke-size').html(data.is_dir ? '-' : Math.ceil(data.filesize / 1024) + 'KB'); + K(row[0].insertCell(2)).addClass('ke-cell ke-datetime').html(data.datetime); + } + } + function createView(result) { + createCommon(result, createView); + var fileList = result.file_list; + for (var i = 0, len = fileList.length; i < len; i++) { + var data = fileList[i], + div = K('
    '); + bodyDiv.append(div); + var photoDiv = K('
    ') + .mouseover(function(e) { + K(this).addClass('ke-on'); + }) + .mouseout(function(e) { + K(this).removeClass('ke-on'); + }); + div.append(photoDiv); + var fileUrl = result.current_url + data.filename, + iconUrl = data.is_dir ? imgPath + 'folder-64.gif' : (data.is_photo ? fileUrl : imgPath + 'file-64.gif'); + var img = K('' + data.filename + ''); + if (!data.is_dir || data.has_file) { + photoDiv.css('cursor', 'pointer'); + bindTitle(photoDiv, data); + bindEvent(photoDiv, result, data, createView); + } else { + photoDiv.attr('title', lang.emptyFolder); + } + photoDiv.append(img); + div.append('
    ' + data.filename + '
    '); + } + } + viewTypeBox.val(viewType); + reloadPage('', orderTypeBox.val(), viewType == 'VIEW' ? createView : createList); + return dialog; + } + +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('flash', function(K) { + var self = this, name = 'flash', lang = self.lang(name + '.'), + allowFlashUpload = K.undef(self.allowFlashUpload, true), + allowFileManager = K.undef(self.allowFileManager, false), + formatUploadUrl = K.undef(self.formatUploadUrl, true), + extraParams = K.undef(self.extraFileUploadParams, {}), + filePostName = K.undef(self.filePostName, 'imgFile'), + uploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'); + self.plugin.flash = { + edit : function() { + var html = [ + '
    ', + //url + '
    ', + '', + '  ', + '  ', + '', + '', + '', + '
    ', + //width + '
    ', + '', + ' ', + '
    ', + //height + '
    ', + '', + ' ', + '
    ', + '
    ' + ].join(''); + var dialog = self.createDialog({ + name : name, + width : 450, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var url = K.trim(urlBox.val()), + width = widthBox.val(), + height = heightBox.val(); + if (url == 'http://' || K.invalidUrl(url)) { + alert(self.lang('invalidUrl')); + urlBox[0].focus(); + return; + } + if (!/^\d*$/.test(width)) { + alert(self.lang('invalidWidth')); + widthBox[0].focus(); + return; + } + if (!/^\d*$/.test(height)) { + alert(self.lang('invalidHeight')); + heightBox[0].focus(); + return; + } + var html = K.mediaImg(self.themesPath + 'common/blank.gif', { + src : url, + type : K.mediaType('.swf'), + width : width, + height : height, + quality : 'high' + }); + self.insertHtml(html).hideDialog().focus(); + } + } + }), + div = dialog.div, + urlBox = K('[name="url"]', div), + viewServerBtn = K('[name="viewServer"]', div), + widthBox = K('[name="width"]', div), + heightBox = K('[name="height"]', div); + urlBox.val('http://'); + + if (allowFlashUpload) { + var uploadbutton = K.uploadbutton({ + button : K('.ke-upload-button', div)[0], + fieldName : filePostName, + extraParams : extraParams, + url : K.addParam(uploadJson, 'dir=flash'), + afterUpload : function(data) { + dialog.hideLoading(); + if (data.error === 0) { + var url = data.url; + if (formatUploadUrl) { + url = K.formatUrl(url, 'absolute'); + } + urlBox.val(url); + if (self.afterUpload) { + self.afterUpload.call(self, url, data, name); + } + alert(self.lang('uploadSuccess')); + } else { + alert(data.message); + } + }, + afterError : function(html) { + dialog.hideLoading(); + self.errorDialog(html); + } + }); + uploadbutton.fileBox.change(function(e) { + dialog.showLoading(self.lang('uploadLoading')); + uploadbutton.submit(); + }); + } else { + K('.ke-upload-button', div).hide(); + } + + if (allowFileManager) { + viewServerBtn.click(function(e) { + self.loadPlugin('filemanager', function() { + self.plugin.filemanagerDialog({ + viewType : 'LIST', + dirName : 'flash', + clickFn : function(url, title) { + if (self.dialogs.length > 1) { + K('[name="url"]', div).val(url); + if (self.afterSelectFile) { + self.afterSelectFile.call(self, url); + } + self.hideDialog(); + } + } + }); + }); + }); + } else { + viewServerBtn.hide(); + } + + var img = self.plugin.getSelectedFlash(); + if (img) { + var attrs = K.mediaAttrs(img.attr('data-ke-tag')); + urlBox.val(attrs.src); + widthBox.val(K.removeUnit(img.css('width')) || attrs.width || 0); + heightBox.val(K.removeUnit(img.css('height')) || attrs.height || 0); + } + urlBox[0].focus(); + urlBox[0].select(); + }, + 'delete' : function() { + self.plugin.getSelectedFlash().remove(); + // [IE] 删除图片后立即点击图片按钮出错 + self.addBookmark(); + } + }; + self.clickToolbar(name, self.plugin.flash.edit); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('image', function(K) { + var self = this, name = 'image', + allowImageUpload = K.undef(self.allowImageUpload, true), + allowImageRemote = K.undef(self.allowImageRemote, true), + formatUploadUrl = K.undef(self.formatUploadUrl, true), + allowFileManager = K.undef(self.allowFileManager, false), + uploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'), + imageTabIndex = K.undef(self.imageTabIndex, 0), + imgPath = self.pluginsPath + 'image/images/', + extraParams = K.undef(self.extraFileUploadParams, {}), + filePostName = K.undef(self.filePostName, 'imgFile'), + fillDescAfterUploadImage = K.undef(self.fillDescAfterUploadImage, false), + lang = self.lang(name + '.'); + + self.plugin.imageDialog = function(options) { + var imageUrl = options.imageUrl, + imageWidth = K.undef(options.imageWidth, ''), + imageHeight = K.undef(options.imageHeight, ''), + imageTitle = K.undef(options.imageTitle, ''), + imageAlign = K.undef(options.imageAlign, ''), + showRemote = K.undef(options.showRemote, true), + showLocal = K.undef(options.showLocal, true), + tabIndex = K.undef(options.tabIndex, 0), + clickFn = options.clickFn; + var target = 'kindeditor_upload_iframe_' + new Date().getTime(); + var hiddenElements = []; + for(var k in extraParams){ + hiddenElements.push(''); + } + var html = [ + '
    ', + //tabs + '
    ', + //remote image - start + '', + //remote image - end + //local upload - start + '', + //local upload - end + '
    ' + ].join(''); + var dialogWidth = showLocal || allowFileManager ? 450 : 400, + dialogHeight = showLocal && showRemote ? 300 : 250; + var dialog = self.createDialog({ + name : name, + width : dialogWidth, + height : dialogHeight, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + // Bugfix: http://code.google.com/p/kindeditor/issues/detail?id=319 + if (dialog.isLoading) { + return; + } + // insert local image + if (showLocal && showRemote && tabs && tabs.selectedIndex === 1 || !showRemote) { + if (uploadbutton.fileBox.val() == '') { + alert(self.lang('pleaseSelectFile')); + return; + } + dialog.showLoading(self.lang('uploadLoading')); + uploadbutton.submit(); + localUrlBox.val(''); + return; + } + // insert remote image + var url = K.trim(urlBox.val()), + width = widthBox.val(), + height = heightBox.val(), + title = titleBox.val(), + align = ''; + alignBox.each(function() { + if (this.checked) { + align = this.value; + return false; + } + }); + if (url == 'http://' || K.invalidUrl(url)) { + alert(self.lang('invalidUrl')); + urlBox[0].focus(); + return; + } + if (!/^\d*$/.test(width)) { + alert(self.lang('invalidWidth')); + widthBox[0].focus(); + return; + } + if (!/^\d*$/.test(height)) { + alert(self.lang('invalidHeight')); + heightBox[0].focus(); + return; + } + clickFn.call(self, url, title, width, height, 0, align); + } + }, + beforeRemove : function() { + viewServerBtn.unbind(); + widthBox.unbind(); + heightBox.unbind(); + refreshBtn.unbind(); + } + }), + div = dialog.div; + + var urlBox = K('[name="url"]', div), + localUrlBox = K('[name="localUrl"]', div), + viewServerBtn = K('[name="viewServer"]', div), + widthBox = K('.tab1 [name="width"]', div), + heightBox = K('.tab1 [name="height"]', div), + refreshBtn = K('.ke-refresh-btn', div), + titleBox = K('.tab1 [name="title"]', div), + alignBox = K('.tab1 [name="align"]', div); + + var tabs; + if (showRemote && showLocal) { + tabs = K.tabs({ + src : K('.tabs', div), + afterSelect : function(i) {} + }); + tabs.add({ + title : lang.remoteImage, + panel : K('.tab1', div) + }); + tabs.add({ + title : lang.localImage, + panel : K('.tab2', div) + }); + tabs.select(tabIndex); + } else if (showRemote) { + K('.tab1', div).show(); + } else if (showLocal) { + K('.tab2', div).show(); + } + + var uploadbutton = K.uploadbutton({ + button : K('.ke-upload-button', div)[0], + fieldName : filePostName, + form : K('.ke-form', div), + target : target, + width: 60, + afterUpload : function(data) { + dialog.hideLoading(); + if (data.error === 0) { + var url = data.url; + if (formatUploadUrl) { + url = K.formatUrl(url, 'absolute'); + } + if (self.afterUpload) { + self.afterUpload.call(self, url, data, name); + } + if (!fillDescAfterUploadImage) { + clickFn.call(self, url, data.title, data.width, data.height, data.border, data.align); + } else { + K(".ke-dialog-row #remoteUrl", div).val(url); + K(".ke-tabs-li", div)[0].click(); + K(".ke-refresh-btn", div).click(); + } + } else { + alert(data.message); + } + }, + afterError : function(html) { + dialog.hideLoading(); + self.errorDialog(html); + } + }); + uploadbutton.fileBox.change(function(e) { + localUrlBox.val(uploadbutton.fileBox.val()); + }); + if (allowFileManager) { + viewServerBtn.click(function(e) { + self.loadPlugin('filemanager', function() { + self.plugin.filemanagerDialog({ + viewType : 'VIEW', + dirName : 'image', + clickFn : function(url, title) { + if (self.dialogs.length > 1) { + K('[name="url"]', div).val(url); + if (self.afterSelectFile) { + self.afterSelectFile.call(self, url); + } + self.hideDialog(); + } + } + }); + }); + }); + } else { + viewServerBtn.hide(); + } + var originalWidth = 0, originalHeight = 0; + function setSize(width, height) { + widthBox.val(width); + heightBox.val(height); + originalWidth = width; + originalHeight = height; + } + refreshBtn.click(function(e) { + var tempImg = K('', document).css({ + position : 'absolute', + visibility : 'hidden', + top : 0, + left : '-1000px' + }); + tempImg.bind('load', function() { + setSize(tempImg.width(), tempImg.height()); + tempImg.remove(); + }); + K(document.body).append(tempImg); + }); + widthBox.change(function(e) { + if (originalWidth > 0) { + heightBox.val(Math.round(originalHeight / originalWidth * parseInt(this.value, 10))); + } + }); + heightBox.change(function(e) { + if (originalHeight > 0) { + widthBox.val(Math.round(originalWidth / originalHeight * parseInt(this.value, 10))); + } + }); + urlBox.val(options.imageUrl); + setSize(options.imageWidth, options.imageHeight); + titleBox.val(options.imageTitle); + alignBox.each(function() { + if (this.value === options.imageAlign) { + this.checked = true; + return false; + } + }); + if (showRemote && tabIndex === 0) { + urlBox[0].focus(); + urlBox[0].select(); + } + return dialog; + }; + self.plugin.image = { + edit : function() { + var img = self.plugin.getSelectedImage(); + self.plugin.imageDialog({ + imageUrl : img ? img.attr('data-ke-src') : 'http://', + imageWidth : img ? img.width() : '', + imageHeight : img ? img.height() : '', + imageTitle : img ? img.attr('title') : '', + imageAlign : img ? img.attr('align') : '', + showRemote : allowImageRemote, + showLocal : allowImageUpload, + tabIndex: img ? 0 : imageTabIndex, + clickFn : function(url, title, width, height, border, align) { + if (img) { + img.attr('src', url); + img.attr('data-ke-src', url); + img.attr('width', width); + img.attr('height', height); + img.attr('title', title); + img.attr('align', align); + img.attr('alt', title); + } else { + self.exec('insertimage', url, title, width, height, border, align); + } + // Bugfix: [Firefox] 上传图片后,总是出现正在加载的样式,需要延迟执行hideDialog + setTimeout(function() { + self.hideDialog().focus(); + }, 0); + } + }); + }, + 'delete' : function() { + var target = self.plugin.getSelectedImage(); + if (target.parent().name == 'a') { + target = target.parent(); + } + target.remove(); + // [IE] 删除图片后立即点击图片按钮出错 + self.addBookmark(); + } + }; + self.clickToolbar(name, self.plugin.image.edit); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('insertfile', function(K) { + var self = this, name = 'insertfile', + allowFileUpload = K.undef(self.allowFileUpload, true), + allowFileManager = K.undef(self.allowFileManager, false), + formatUploadUrl = K.undef(self.formatUploadUrl, true), + uploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'), + extraParams = K.undef(self.extraFileUploadParams, {}), + filePostName = K.undef(self.filePostName, 'imgFile'), + lang = self.lang(name + '.'); + self.plugin.fileDialog = function(options) { + var fileUrl = K.undef(options.fileUrl, 'http://'), + fileTitle = K.undef(options.fileTitle, ''), + clickFn = options.clickFn; + var html = [ + '
    ', + '
    ', + '', + '  ', + '  ', + '', + '', + '', + '
    ', + //title + '
    ', + '', + '
    ', + '
    ', + //form end + '', + '' + ].join(''); + var dialog = self.createDialog({ + name : name, + width : 450, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var url = K.trim(urlBox.val()), + title = titleBox.val(); + if (url == 'http://' || K.invalidUrl(url)) { + alert(self.lang('invalidUrl')); + urlBox[0].focus(); + return; + } + if (K.trim(title) === '') { + title = url; + } + clickFn.call(self, url, title); + } + } + }), + div = dialog.div; + + var urlBox = K('[name="url"]', div), + viewServerBtn = K('[name="viewServer"]', div), + titleBox = K('[name="title"]', div); + + if (allowFileUpload) { + var uploadbutton = K.uploadbutton({ + button : K('.ke-upload-button', div)[0], + fieldName : filePostName, + url : K.addParam(uploadJson, 'dir=file'), + extraParams : extraParams, + afterUpload : function(data) { + dialog.hideLoading(); + if (data.error === 0) { + var url = data.url; + if (formatUploadUrl) { + url = K.formatUrl(url, 'absolute'); + } + urlBox.val(url); + if (self.afterUpload) { + self.afterUpload.call(self, url, data, name); + } + alert(self.lang('uploadSuccess')); + } else { + alert(data.message); + } + }, + afterError : function(html) { + dialog.hideLoading(); + self.errorDialog(html); + } + }); + uploadbutton.fileBox.change(function(e) { + dialog.showLoading(self.lang('uploadLoading')); + uploadbutton.submit(); + }); + } else { + K('.ke-upload-button', div).hide(); + } + if (allowFileManager) { + viewServerBtn.click(function(e) { + self.loadPlugin('filemanager', function() { + self.plugin.filemanagerDialog({ + viewType : 'LIST', + dirName : 'file', + clickFn : function(url, title) { + if (self.dialogs.length > 1) { + K('[name="url"]', div).val(url); + if (self.afterSelectFile) { + self.afterSelectFile.call(self, url); + } + self.hideDialog(); + } + } + }); + }); + }); + } else { + viewServerBtn.hide(); + } + urlBox.val(fileUrl); + titleBox.val(fileTitle); + urlBox[0].focus(); + urlBox[0].select(); + }; + self.clickToolbar(name, function() { + self.plugin.fileDialog({ + clickFn : function(url, title) { + var html = '' + title + ''; + self.insertHtml(html).hideDialog().focus(); + } + }); + }); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('lineheight', function(K) { + var self = this, name = 'lineheight', lang = self.lang(name + '.'); + self.clickToolbar(name, function() { + var curVal = '', commonNode = self.cmd.commonNode({'*' : '.line-height'}); + if (commonNode) { + curVal = commonNode.css('line-height'); + } + var menu = self.createMenu({ + name : name, + width : 150 + }); + K.each(lang.lineHeight, function(i, row) { + K.each(row, function(key, val) { + menu.addItem({ + title : val, + checked : curVal === key, + click : function() { + self.cmd.toggle('', { + span : '.line-height=' + key + }); + self.updateState(); + self.addBookmark(); + self.hideMenu(); + } + }); + }); + }); + }); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('link', function(K) { + var self = this, name = 'link'; + self.plugin.link = { + edit : function() { + var lang = self.lang(name + '.'), + html = '
    ' + + //url + '
    ' + + '' + + '
    ' + + //type + '
    ' + + '' + + '' + + '
    ' + + '
    ', + dialog = self.createDialog({ + name : name, + width : 450, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var url = K.trim(urlBox.val()); + if (url == 'http://' || K.invalidUrl(url)) { + alert(self.lang('invalidUrl')); + urlBox[0].focus(); + return; + } + self.exec('createlink', url, typeBox.val()).hideDialog().focus(); + } + } + }), + div = dialog.div, + urlBox = K('input[name="url"]', div), + typeBox = K('select[name="type"]', div); + urlBox.val('http://'); + typeBox[0].options[0] = new Option(lang.newWindow, '_blank'); + typeBox[0].options[1] = new Option(lang.selfWindow, ''); + self.cmd.selection(); + var a = self.plugin.getSelectedLink(); + if (a) { + self.cmd.range.selectNode(a[0]); + self.cmd.select(); + urlBox.val(a.attr('data-ke-src')); + typeBox.val(a.attr('target')); + } + urlBox[0].focus(); + urlBox[0].select(); + }, + 'delete' : function() { + self.exec('unlink', null); + } + }; + self.clickToolbar(name, self.plugin.link.edit); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +// Google Maps: http://code.google.com/apis/maps/index.html + +KindEditor.plugin('map', function(K) { + var self = this, name = 'map', lang = self.lang(name + '.'); + self.clickToolbar(name, function() { + var html = ['
    ', + '
    ', + lang.address + ' ', + '', + '', + '', + '
    ', + '
    ', + '
    '].join(''); + var dialog = self.createDialog({ + name : name, + width : 600, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var geocoder = win.geocoder, + map = win.map, + center = map.getCenter().lat() + ',' + map.getCenter().lng(), + zoom = map.getZoom(), + maptype = map.getMapTypeId(), + url = 'http://maps.googleapis.com/maps/api/staticmap'; + url += '?center=' + encodeURIComponent(center); + url += '&zoom=' + encodeURIComponent(zoom); + url += '&size=558x360'; + url += '&maptype=' + encodeURIComponent(maptype); + url += '&markers=' + encodeURIComponent(center); + url += '&language=' + self.langType; + url += '&sensor=false'; + self.exec('insertimage', url).hideDialog().focus(); + } + }, + beforeRemove : function() { + searchBtn.remove(); + if (doc) { + doc.write(''); + } + iframe.remove(); + } + }); + var div = dialog.div, + addressBox = K('[name="address"]', div), + searchBtn = K('[name="searchBtn"]', div), + win, doc; + var iframeHtml = ['', + '', + '', + '', + '', + '', + '', + '
    ', + ''].join('\n'); + // TODO:用doc.write(iframeHtml)方式加载时,在IE6上第一次加载报错,暂时使用src方式 + var iframe = K(''); + function ready() { + win = iframe[0].contentWindow; + doc = K.iframeDoc(iframe); + //doc.open(); + //doc.write(iframeHtml); + //doc.close(); + } + iframe.bind('load', function() { + iframe.unbind('load'); + if (K.IE) { + ready(); + } else { + setTimeout(ready, 0); + } + }); + K('.ke-map', div).replaceWith(iframe); + // search map + searchBtn.click(function() { + win.search(addressBox.val()); + }); + }); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('media', function(K) { + var self = this, name = 'media', lang = self.lang(name + '.'), + allowMediaUpload = K.undef(self.allowMediaUpload, true), + allowFileManager = K.undef(self.allowFileManager, false), + formatUploadUrl = K.undef(self.formatUploadUrl, true), + extraParams = K.undef(self.extraFileUploadParams, {}), + filePostName = K.undef(self.filePostName, 'imgFile'), + uploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'); + self.plugin.media = { + edit : function() { + var html = [ + '
    ', + //url + '
    ', + '', + '  ', + '  ', + '', + '', + '', + '
    ', + //width + '
    ', + '', + '', + '
    ', + //height + '
    ', + '', + '', + '
    ', + //autostart + '
    ', + '', + ' ', + '
    ', + '
    ' + ].join(''); + var dialog = self.createDialog({ + name : name, + width : 450, + height : 230, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var url = K.trim(urlBox.val()), + width = widthBox.val(), + height = heightBox.val(); + if (url == 'http://' || K.invalidUrl(url)) { + alert(self.lang('invalidUrl')); + urlBox[0].focus(); + return; + } + if (!/^\d*$/.test(width)) { + alert(self.lang('invalidWidth')); + widthBox[0].focus(); + return; + } + if (!/^\d*$/.test(height)) { + alert(self.lang('invalidHeight')); + heightBox[0].focus(); + return; + } + var html = K.mediaImg(self.themesPath + 'common/blank.gif', { + src : url, + type : K.mediaType(url), + width : width, + height : height, + autostart : autostartBox[0].checked ? 'true' : 'false', + loop : 'true' + }); + self.insertHtml(html).hideDialog().focus(); + } + } + }), + div = dialog.div, + urlBox = K('[name="url"]', div), + viewServerBtn = K('[name="viewServer"]', div), + widthBox = K('[name="width"]', div), + heightBox = K('[name="height"]', div), + autostartBox = K('[name="autostart"]', div); + urlBox.val('http://'); + + if (allowMediaUpload) { + var uploadbutton = K.uploadbutton({ + button : K('.ke-upload-button', div)[0], + fieldName : filePostName, + extraParams : extraParams, + url : K.addParam(uploadJson, 'dir=media'), + afterUpload : function(data) { + dialog.hideLoading(); + if (data.error === 0) { + var url = data.url; + if (formatUploadUrl) { + url = K.formatUrl(url, 'absolute'); + } + urlBox.val(url); + if (self.afterUpload) { + self.afterUpload.call(self, url, data, name); + } + alert(self.lang('uploadSuccess')); + } else { + alert(data.message); + } + }, + afterError : function(html) { + dialog.hideLoading(); + self.errorDialog(html); + } + }); + uploadbutton.fileBox.change(function(e) { + dialog.showLoading(self.lang('uploadLoading')); + uploadbutton.submit(); + }); + } else { + K('.ke-upload-button', div).hide(); + } + + if (allowFileManager) { + viewServerBtn.click(function(e) { + self.loadPlugin('filemanager', function() { + self.plugin.filemanagerDialog({ + viewType : 'LIST', + dirName : 'media', + clickFn : function(url, title) { + if (self.dialogs.length > 1) { + K('[name="url"]', div).val(url); + if (self.afterSelectFile) { + self.afterSelectFile.call(self, url); + } + self.hideDialog(); + } + } + }); + }); + }); + } else { + viewServerBtn.hide(); + } + + var img = self.plugin.getSelectedMedia(); + if (img) { + var attrs = K.mediaAttrs(img.attr('data-ke-tag')); + urlBox.val(attrs.src); + widthBox.val(K.removeUnit(img.css('width')) || attrs.width || 0); + heightBox.val(K.removeUnit(img.css('height')) || attrs.height || 0); + autostartBox[0].checked = (attrs.autostart === 'true'); + } + urlBox[0].focus(); + urlBox[0].select(); + }, + 'delete' : function() { + self.plugin.getSelectedMedia().remove(); + // [IE] 删除图片后立即点击图片按钮出错 + self.addBookmark(); + } + }; + self.clickToolbar(name, self.plugin.media.edit); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + + +(function(K) { + +function KSWFUpload(options) { + this.init(options); +} +K.extend(KSWFUpload, { + init : function(options) { + var self = this; + options.afterError = options.afterError || function(str) { + alert(str); + }; + self.options = options; + self.progressbars = {}; + // template + self.div = K(options.container).html([ + '
    ', + '
    ', + '
    ', + '', + '
    ', + '
    ' + options.uploadDesc + '
    ', + '', + '', + '', + '
    ', + '
    ', + '
    ' + ].join('')); + self.bodyDiv = K('.ke-swfupload-body', self.div); + + function showError(itemDiv, msg) { + K('.ke-status > div', itemDiv).hide(); + K('.ke-message', itemDiv).addClass('ke-error').show().html(K.escape(msg)); + } + + var settings = { + debug : false, + upload_url : options.uploadUrl, + flash_url : options.flashUrl, + file_post_name : options.filePostName, + button_placeholder : K('.ke-swfupload-button > input', self.div)[0], + button_image_url: options.buttonImageUrl, + button_width: options.buttonWidth, + button_height: options.buttonHeight, + button_cursor : SWFUpload.CURSOR.HAND, + file_types : options.fileTypes, + file_types_description : options.fileTypesDesc, + file_upload_limit : options.fileUploadLimit, + file_size_limit : options.fileSizeLimit, + post_params : options.postParams, + file_queued_handler : function(file) { + file.url = self.options.fileIconUrl; + self.appendFile(file); + }, + file_queue_error_handler : function(file, errorCode, message) { + var errorName = ''; + switch (errorCode) { + case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED: + errorName = options.queueLimitExceeded; + break; + case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT: + errorName = options.fileExceedsSizeLimit; + break; + case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE: + errorName = options.zeroByteFile; + break; + case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE: + errorName = options.invalidFiletype; + break; + default: + errorName = options.unknownError; + break; + } + K.DEBUG && alert(errorName); + }, + upload_start_handler : function(file) { + var self = this; + var itemDiv = K('div[data-id="' + file.id + '"]', self.bodyDiv); + K('.ke-status > div', itemDiv).hide(); + K('.ke-progressbar', itemDiv).show(); + }, + upload_progress_handler : function(file, bytesLoaded, bytesTotal) { + var percent = Math.round(bytesLoaded * 100 / bytesTotal); + var progressbar = self.progressbars[file.id]; + progressbar.bar.css('width', Math.round(percent * 80 / 100) + 'px'); + progressbar.percent.html(percent + '%'); + }, + upload_error_handler : function(file, errorCode, message) { + if (file && file.filestatus == SWFUpload.FILE_STATUS.ERROR) { + var itemDiv = K('div[data-id="' + file.id + '"]', self.bodyDiv).eq(0); + showError(itemDiv, self.options.errorMessage); + } + }, + upload_success_handler : function(file, serverData) { + var itemDiv = K('div[data-id="' + file.id + '"]', self.bodyDiv).eq(0); + var data = {}; + try { + data = K.json(serverData); + } catch (e) { + self.options.afterError.call(this, '' + serverData + ''); + } + if (data.error !== 0) { + showError(itemDiv, K.DEBUG ? data.message : self.options.errorMessage); + return; + } + file.url = data.url; + K('.ke-img', itemDiv).attr('src', file.url).attr('data-status', file.filestatus).data('data', data); + K('.ke-status > div', itemDiv).hide(); + } + }; + self.swfu = new SWFUpload(settings); + + K('.ke-swfupload-startupload input', self.div).click(function() { + self.swfu.startUpload(); + }); + }, + getUrlList : function() { + var list = []; + K('.ke-img', self.bodyDiv).each(function() { + var img = K(this); + var status = img.attr('data-status'); + if (status == SWFUpload.FILE_STATUS.COMPLETE) { + list.push(img.data('data')); + } + }); + return list; + }, + removeFile : function(fileId) { + var self = this; + self.swfu.cancelUpload(fileId); + var itemDiv = K('div[data-id="' + fileId + '"]', self.bodyDiv); + K('.ke-photo', itemDiv).unbind(); + K('.ke-delete', itemDiv).unbind(); + itemDiv.remove(); + }, + removeFiles : function() { + var self = this; + K('.ke-item', self.bodyDiv).each(function() { + self.removeFile(K(this).attr('data-id')); + }); + }, + appendFile : function(file) { + var self = this; + var itemDiv = K('
    '); + self.bodyDiv.append(itemDiv); + var photoDiv = K('
    ') + .mouseover(function(e) { + K(this).addClass('ke-on'); + }) + .mouseout(function(e) { + K(this).removeClass('ke-on'); + }); + itemDiv.append(photoDiv); + + var img = K('' + file.name + ''); + photoDiv.append(img); + K('').appendTo(photoDiv).click(function() { + self.removeFile(file.id); + }); + var statusDiv = K('
    ').appendTo(photoDiv); + // progressbar + K(['
    ', + '
    ', + '
    0%
    '].join('')).hide().appendTo(statusDiv); + // message + K('
    ' + self.options.pendingMessage + '
    ').appendTo(statusDiv); + + itemDiv.append('
    ' + file.name + '
    '); + + self.progressbars[file.id] = { + bar : K('.ke-progressbar-bar-inner', photoDiv), + percent : K('.ke-progressbar-percent', photoDiv) + }; + }, + remove : function() { + this.removeFiles(); + this.swfu.destroy(); + this.div.html(''); + } +}); + +K.swfupload = function(element, options) { + return new KSWFUpload(element, options); +}; + +})(KindEditor); + +KindEditor.plugin('multiimage', function(K) { + var self = this, name = 'multiimage', + formatUploadUrl = K.undef(self.formatUploadUrl, true), + uploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'), + imgPath = self.pluginsPath + 'multiimage/images/', + imageSizeLimit = K.undef(self.imageSizeLimit, '1MB'), + imageFileTypes = K.undef(self.imageFileTypes, '*.jpg;*.gif;*.png'), + imageUploadLimit = K.undef(self.imageUploadLimit, 20), + filePostName = K.undef(self.filePostName, 'imgFile'), + lang = self.lang(name + '.'); + + self.plugin.multiImageDialog = function(options) { + var clickFn = options.clickFn, + uploadDesc = K.tmpl(lang.uploadDesc, {uploadLimit : imageUploadLimit, sizeLimit : imageSizeLimit}); + var html = [ + '
    ', + '
    ', + '
    ', + '
    ' + ].join(''); + var dialog = self.createDialog({ + name : name, + width : 650, + height : 510, + title : self.lang(name), + body : html, + previewBtn : { + name : lang.insertAll, + click : function(e) { + clickFn.call(self, swfupload.getUrlList()); + } + }, + yesBtn : { + name : lang.clearAll, + click : function(e) { + swfupload.removeFiles(); + } + }, + beforeRemove : function() { + // IE9 bugfix: https://github.com/kindsoft/kindeditor/issues/72 + if (!K.IE || K.V <= 8) { + swfupload.remove(); + } + } + }), + div = dialog.div; + + var swfupload = K.swfupload({ + container : K('.swfupload', div), + buttonImageUrl : imgPath + (self.langType == 'zh_CN' ? 'select-files-zh_CN.png' : 'select-files-en.png'), + buttonWidth : self.langType == 'zh_CN' ? 72 : 88, + buttonHeight : 23, + fileIconUrl : imgPath + 'image.png', + uploadDesc : uploadDesc, + startButtonValue : lang.startUpload, + uploadUrl : K.addParam(uploadJson, 'dir=image'), + flashUrl : imgPath + 'swfupload.swf', + filePostName : filePostName, + fileTypes : '*.jpg;*.jpeg;*.gif;*.png;*.bmp', + fileTypesDesc : 'Image Files', + fileUploadLimit : imageUploadLimit, + fileSizeLimit : imageSizeLimit, + postParams : K.undef(self.extraFileUploadParams, {}), + queueLimitExceeded : lang.queueLimitExceeded, + fileExceedsSizeLimit : lang.fileExceedsSizeLimit, + zeroByteFile : lang.zeroByteFile, + invalidFiletype : lang.invalidFiletype, + unknownError : lang.unknownError, + pendingMessage : lang.pending, + errorMessage : lang.uploadError, + afterError : function(html) { + self.errorDialog(html); + } + }); + + return dialog; + }; + self.clickToolbar(name, function() { + self.plugin.multiImageDialog({ + clickFn : function (urlList) { + if (urlList.length === 0) { + return; + } + K.each(urlList, function(i, data) { + if (self.afterUpload) { + self.afterUpload.call(self, data.url, data, 'multiimage'); + } + self.exec('insertimage', data.url, data.title, data.width, data.height, data.border, data.align); + }); + // Bugfix: [Firefox] 上传图片后,总是出现正在加载的样式,需要延迟执行hideDialog + setTimeout(function() { + self.hideDialog().focus(); + }, 0); + } + }); + }); +}); + + +/** + * SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com + * + * mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/, http://www.vinterwebb.se/ + * + * SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilz閚 and Mammon Media and is released under the MIT License: + * http://www.opensource.org/licenses/mit-license.php + * + * SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License: + * http://www.opensource.org/licenses/mit-license.php + * + */ + + +/* ******************* */ +/* Constructor & Init */ +/* ******************* */ + +(function() { + +window.SWFUpload = function (settings) { + this.initSWFUpload(settings); +}; + +SWFUpload.prototype.initSWFUpload = function (settings) { + try { + this.customSettings = {}; // A container where developers can place their own settings associated with this instance. + this.settings = settings; + this.eventQueue = []; + this.movieName = "KindEditor_SWFUpload_" + SWFUpload.movieCount++; + this.movieElement = null; + + + // Setup global control tracking + SWFUpload.instances[this.movieName] = this; + + // Load the settings. Load the Flash movie. + this.initSettings(); + this.loadFlash(); + this.displayDebugInfo(); + } catch (ex) { + delete SWFUpload.instances[this.movieName]; + throw ex; + } +}; + +/* *************** */ +/* Static Members */ +/* *************** */ +SWFUpload.instances = {}; +SWFUpload.movieCount = 0; +SWFUpload.version = "2.2.0 2009-03-25"; +SWFUpload.QUEUE_ERROR = { + QUEUE_LIMIT_EXCEEDED : -100, + FILE_EXCEEDS_SIZE_LIMIT : -110, + ZERO_BYTE_FILE : -120, + INVALID_FILETYPE : -130 +}; +SWFUpload.UPLOAD_ERROR = { + HTTP_ERROR : -200, + MISSING_UPLOAD_URL : -210, + IO_ERROR : -220, + SECURITY_ERROR : -230, + UPLOAD_LIMIT_EXCEEDED : -240, + UPLOAD_FAILED : -250, + SPECIFIED_FILE_ID_NOT_FOUND : -260, + FILE_VALIDATION_FAILED : -270, + FILE_CANCELLED : -280, + UPLOAD_STOPPED : -290 +}; +SWFUpload.FILE_STATUS = { + QUEUED : -1, + IN_PROGRESS : -2, + ERROR : -3, + COMPLETE : -4, + CANCELLED : -5 +}; +SWFUpload.BUTTON_ACTION = { + SELECT_FILE : -100, + SELECT_FILES : -110, + START_UPLOAD : -120 +}; +SWFUpload.CURSOR = { + ARROW : -1, + HAND : -2 +}; +SWFUpload.WINDOW_MODE = { + WINDOW : "window", + TRANSPARENT : "transparent", + OPAQUE : "opaque" +}; + +// Private: takes a URL, determines if it is relative and converts to an absolute URL +// using the current site. Only processes the URL if it can, otherwise returns the URL untouched +SWFUpload.completeURL = function(url) { + if (typeof(url) !== "string" || url.match(/^https?:\/\//i) || url.match(/^\//)) { + return url; + } + + var currentURL = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":" + window.location.port : ""); + + var indexSlash = window.location.pathname.lastIndexOf("/"); + if (indexSlash <= 0) { + path = "/"; + } else { + path = window.location.pathname.substr(0, indexSlash) + "/"; + } + + return /*currentURL +*/ path + url; + +}; + + +/* ******************** */ +/* Instance Members */ +/* ******************** */ + +// Private: initSettings ensures that all the +// settings are set, getting a default value if one was not assigned. +SWFUpload.prototype.initSettings = function () { + this.ensureDefault = function (settingName, defaultValue) { + this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName]; + }; + + // Upload backend settings + this.ensureDefault("upload_url", ""); + this.ensureDefault("preserve_relative_urls", false); + this.ensureDefault("file_post_name", "Filedata"); + this.ensureDefault("post_params", {}); + this.ensureDefault("use_query_string", false); + this.ensureDefault("requeue_on_error", false); + this.ensureDefault("http_success", []); + this.ensureDefault("assume_success_timeout", 0); + + // File Settings + this.ensureDefault("file_types", "*.*"); + this.ensureDefault("file_types_description", "All Files"); + this.ensureDefault("file_size_limit", 0); // Default zero means "unlimited" + this.ensureDefault("file_upload_limit", 0); + this.ensureDefault("file_queue_limit", 0); + + // Flash Settings + this.ensureDefault("flash_url", "swfupload.swf"); + this.ensureDefault("prevent_swf_caching", true); + + // Button Settings + this.ensureDefault("button_image_url", ""); + this.ensureDefault("button_width", 1); + this.ensureDefault("button_height", 1); + this.ensureDefault("button_text", ""); + this.ensureDefault("button_text_style", "color: #000000; font-size: 16pt;"); + this.ensureDefault("button_text_top_padding", 0); + this.ensureDefault("button_text_left_padding", 0); + this.ensureDefault("button_action", SWFUpload.BUTTON_ACTION.SELECT_FILES); + this.ensureDefault("button_disabled", false); + this.ensureDefault("button_placeholder_id", ""); + this.ensureDefault("button_placeholder", null); + this.ensureDefault("button_cursor", SWFUpload.CURSOR.ARROW); + this.ensureDefault("button_window_mode", SWFUpload.WINDOW_MODE.WINDOW); + + // Debug Settings + this.ensureDefault("debug", false); + this.settings.debug_enabled = this.settings.debug; // Here to maintain v2 API + + // Event Handlers + this.settings.return_upload_start_handler = this.returnUploadStart; + this.ensureDefault("swfupload_loaded_handler", null); + this.ensureDefault("file_dialog_start_handler", null); + this.ensureDefault("file_queued_handler", null); + this.ensureDefault("file_queue_error_handler", null); + this.ensureDefault("file_dialog_complete_handler", null); + + this.ensureDefault("upload_start_handler", null); + this.ensureDefault("upload_progress_handler", null); + this.ensureDefault("upload_error_handler", null); + this.ensureDefault("upload_success_handler", null); + this.ensureDefault("upload_complete_handler", null); + + this.ensureDefault("debug_handler", this.debugMessage); + + this.ensureDefault("custom_settings", {}); + + // Other settings + this.customSettings = this.settings.custom_settings; + + // Update the flash url if needed + if (!!this.settings.prevent_swf_caching) { + this.settings.flash_url = this.settings.flash_url + (this.settings.flash_url.indexOf("?") < 0 ? "?" : "&") + "preventswfcaching=" + new Date().getTime(); + } + + if (!this.settings.preserve_relative_urls) { + //this.settings.flash_url = SWFUpload.completeURL(this.settings.flash_url); // Don't need to do this one since flash doesn't look at it + this.settings.upload_url = SWFUpload.completeURL(this.settings.upload_url); + this.settings.button_image_url = SWFUpload.completeURL(this.settings.button_image_url); + } + + delete this.ensureDefault; +}; + +// Private: loadFlash replaces the button_placeholder element with the flash movie. +SWFUpload.prototype.loadFlash = function () { + var targetElement, tempParent; + + // Make sure an element with the ID we are going to use doesn't already exist + if (document.getElementById(this.movieName) !== null) { + throw "ID " + this.movieName + " is already in use. The Flash Object could not be added"; + } + + // Get the element where we will be placing the flash movie + targetElement = document.getElementById(this.settings.button_placeholder_id) || this.settings.button_placeholder; + + if (targetElement == undefined) { + throw "Could not find the placeholder element: " + this.settings.button_placeholder_id; + } + + // Append the container and load the flash + tempParent = document.createElement("div"); + tempParent.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers) + targetElement.parentNode.replaceChild(tempParent.firstChild, targetElement); + + // Fix IE Flash/Form bug + if (window[this.movieName] == undefined) { + window[this.movieName] = this.getMovieElement(); + } + +}; + +// Private: getFlashHTML generates the object tag needed to embed the flash in to the document +SWFUpload.prototype.getFlashHTML = function () { + // Flash Satay object syntax: http://www.alistapart.com/articles/flashsatay + // Fix bug for IE9 + // http://www.kindsoft.net/view.php?bbsid=7&postid=5825&pagenum=1 + var classid = ''; + if (KindEditor.IE && KindEditor.V > 8) { + classid = ' classid = "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"'; + } + return ['', + '', + '', + '', + '', + '', + '', + ''].join(""); +}; + +// Private: getFlashVars builds the parameter string that will be passed +// to flash in the flashvars param. +SWFUpload.prototype.getFlashVars = function () { + // Build a string from the post param object + var paramString = this.buildParamString(); + var httpSuccessString = this.settings.http_success.join(","); + + // Build the parameter string + return ["movieName=", encodeURIComponent(this.movieName), + "&uploadURL=", encodeURIComponent(this.settings.upload_url), + "&useQueryString=", encodeURIComponent(this.settings.use_query_string), + "&requeueOnError=", encodeURIComponent(this.settings.requeue_on_error), + "&httpSuccess=", encodeURIComponent(httpSuccessString), + "&assumeSuccessTimeout=", encodeURIComponent(this.settings.assume_success_timeout), + "&params=", encodeURIComponent(paramString), + "&filePostName=", encodeURIComponent(this.settings.file_post_name), + "&fileTypes=", encodeURIComponent(this.settings.file_types), + "&fileTypesDescription=", encodeURIComponent(this.settings.file_types_description), + "&fileSizeLimit=", encodeURIComponent(this.settings.file_size_limit), + "&fileUploadLimit=", encodeURIComponent(this.settings.file_upload_limit), + "&fileQueueLimit=", encodeURIComponent(this.settings.file_queue_limit), + "&debugEnabled=", encodeURIComponent(this.settings.debug_enabled), + "&buttonImageURL=", encodeURIComponent(this.settings.button_image_url), + "&buttonWidth=", encodeURIComponent(this.settings.button_width), + "&buttonHeight=", encodeURIComponent(this.settings.button_height), + "&buttonText=", encodeURIComponent(this.settings.button_text), + "&buttonTextTopPadding=", encodeURIComponent(this.settings.button_text_top_padding), + "&buttonTextLeftPadding=", encodeURIComponent(this.settings.button_text_left_padding), + "&buttonTextStyle=", encodeURIComponent(this.settings.button_text_style), + "&buttonAction=", encodeURIComponent(this.settings.button_action), + "&buttonDisabled=", encodeURIComponent(this.settings.button_disabled), + "&buttonCursor=", encodeURIComponent(this.settings.button_cursor) + ].join(""); +}; + +// Public: getMovieElement retrieves the DOM reference to the Flash element added by SWFUpload +// The element is cached after the first lookup +SWFUpload.prototype.getMovieElement = function () { + if (this.movieElement == undefined) { + this.movieElement = document.getElementById(this.movieName); + } + + if (this.movieElement === null) { + throw "Could not find Flash element"; + } + + return this.movieElement; +}; + +// Private: buildParamString takes the name/value pairs in the post_params setting object +// and joins them up in to a string formatted "name=value&name=value" +SWFUpload.prototype.buildParamString = function () { + var postParams = this.settings.post_params; + var paramStringPairs = []; + + if (typeof(postParams) === "object") { + for (var name in postParams) { + if (postParams.hasOwnProperty(name)) { + paramStringPairs.push(encodeURIComponent(name.toString()) + "=" + encodeURIComponent(postParams[name].toString())); + } + } + } + + return paramStringPairs.join("&"); +}; + +// Public: Used to remove a SWFUpload instance from the page. This method strives to remove +// all references to the SWF, and other objects so memory is properly freed. +// Returns true if everything was destroyed. Returns a false if a failure occurs leaving SWFUpload in an inconsistant state. +// Credits: Major improvements provided by steffen +SWFUpload.prototype.destroy = function () { + try { + // Make sure Flash is done before we try to remove it + this.cancelUpload(null, false); + + + // Remove the SWFUpload DOM nodes + var movieElement = null; + movieElement = this.getMovieElement(); + + if (movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE + // Loop through all the movie's properties and remove all function references (DOM/JS IE 6/7 memory leak workaround) + for (var i in movieElement) { + try { + if (typeof(movieElement[i]) === "function") { + movieElement[i] = null; + } + } catch (ex1) {} + } + + // Remove the Movie Element from the page + try { + movieElement.parentNode.removeChild(movieElement); + } catch (ex) {} + } + + // Remove IE form fix reference + window[this.movieName] = null; + + // Destroy other references + SWFUpload.instances[this.movieName] = null; + delete SWFUpload.instances[this.movieName]; + + this.movieElement = null; + this.settings = null; + this.customSettings = null; + this.eventQueue = null; + this.movieName = null; + + + return true; + } catch (ex2) { + return false; + } +}; + + +// Public: displayDebugInfo prints out settings and configuration +// information about this SWFUpload instance. +// This function (and any references to it) can be deleted when placing +// SWFUpload in production. +SWFUpload.prototype.displayDebugInfo = function () { + this.debug( + [ + "---SWFUpload Instance Info---\n", + "Version: ", SWFUpload.version, "\n", + "Movie Name: ", this.movieName, "\n", + "Settings:\n", + "\t", "upload_url: ", this.settings.upload_url, "\n", + "\t", "flash_url: ", this.settings.flash_url, "\n", + "\t", "use_query_string: ", this.settings.use_query_string.toString(), "\n", + "\t", "requeue_on_error: ", this.settings.requeue_on_error.toString(), "\n", + "\t", "http_success: ", this.settings.http_success.join(", "), "\n", + "\t", "assume_success_timeout: ", this.settings.assume_success_timeout, "\n", + "\t", "file_post_name: ", this.settings.file_post_name, "\n", + "\t", "post_params: ", this.settings.post_params.toString(), "\n", + "\t", "file_types: ", this.settings.file_types, "\n", + "\t", "file_types_description: ", this.settings.file_types_description, "\n", + "\t", "file_size_limit: ", this.settings.file_size_limit, "\n", + "\t", "file_upload_limit: ", this.settings.file_upload_limit, "\n", + "\t", "file_queue_limit: ", this.settings.file_queue_limit, "\n", + "\t", "debug: ", this.settings.debug.toString(), "\n", + + "\t", "prevent_swf_caching: ", this.settings.prevent_swf_caching.toString(), "\n", + + "\t", "button_placeholder_id: ", this.settings.button_placeholder_id.toString(), "\n", + "\t", "button_placeholder: ", (this.settings.button_placeholder ? "Set" : "Not Set"), "\n", + "\t", "button_image_url: ", this.settings.button_image_url.toString(), "\n", + "\t", "button_width: ", this.settings.button_width.toString(), "\n", + "\t", "button_height: ", this.settings.button_height.toString(), "\n", + "\t", "button_text: ", this.settings.button_text.toString(), "\n", + "\t", "button_text_style: ", this.settings.button_text_style.toString(), "\n", + "\t", "button_text_top_padding: ", this.settings.button_text_top_padding.toString(), "\n", + "\t", "button_text_left_padding: ", this.settings.button_text_left_padding.toString(), "\n", + "\t", "button_action: ", this.settings.button_action.toString(), "\n", + "\t", "button_disabled: ", this.settings.button_disabled.toString(), "\n", + + "\t", "custom_settings: ", this.settings.custom_settings.toString(), "\n", + "Event Handlers:\n", + "\t", "swfupload_loaded_handler assigned: ", (typeof this.settings.swfupload_loaded_handler === "function").toString(), "\n", + "\t", "file_dialog_start_handler assigned: ", (typeof this.settings.file_dialog_start_handler === "function").toString(), "\n", + "\t", "file_queued_handler assigned: ", (typeof this.settings.file_queued_handler === "function").toString(), "\n", + "\t", "file_queue_error_handler assigned: ", (typeof this.settings.file_queue_error_handler === "function").toString(), "\n", + "\t", "upload_start_handler assigned: ", (typeof this.settings.upload_start_handler === "function").toString(), "\n", + "\t", "upload_progress_handler assigned: ", (typeof this.settings.upload_progress_handler === "function").toString(), "\n", + "\t", "upload_error_handler assigned: ", (typeof this.settings.upload_error_handler === "function").toString(), "\n", + "\t", "upload_success_handler assigned: ", (typeof this.settings.upload_success_handler === "function").toString(), "\n", + "\t", "upload_complete_handler assigned: ", (typeof this.settings.upload_complete_handler === "function").toString(), "\n", + "\t", "debug_handler assigned: ", (typeof this.settings.debug_handler === "function").toString(), "\n" + ].join("") + ); +}; + +/* Note: addSetting and getSetting are no longer used by SWFUpload but are included + the maintain v2 API compatibility +*/ +// Public: (Deprecated) addSetting adds a setting value. If the value given is undefined or null then the default_value is used. +SWFUpload.prototype.addSetting = function (name, value, default_value) { + if (value == undefined) { + return (this.settings[name] = default_value); + } else { + return (this.settings[name] = value); + } +}; + +// Public: (Deprecated) getSetting gets a setting. Returns an empty string if the setting was not found. +SWFUpload.prototype.getSetting = function (name) { + if (this.settings[name] != undefined) { + return this.settings[name]; + } + + return ""; +}; + + + +// Private: callFlash handles function calls made to the Flash element. +// Calls are made with a setTimeout for some functions to work around +// bugs in the ExternalInterface library. +SWFUpload.prototype.callFlash = function (functionName, argumentArray) { + argumentArray = argumentArray || []; + + var movieElement = this.getMovieElement(); + var returnValue, returnString; + + // Flash's method if calling ExternalInterface methods (code adapted from MooTools). + try { + returnString = movieElement.CallFunction('' + __flash__argumentsToXML(argumentArray, 0) + ''); + returnValue = eval(returnString); + } catch (ex) { + throw "Call to " + functionName + " failed"; + } + + // Unescape file post param values + if (returnValue != undefined && typeof returnValue.post === "object") { + returnValue = this.unescapeFilePostParams(returnValue); + } + + return returnValue; +}; + +/* ***************************** + -- Flash control methods -- + Your UI should use these + to operate SWFUpload + ***************************** */ + +// WARNING: this function does not work in Flash Player 10 +// Public: selectFile causes a File Selection Dialog window to appear. This +// dialog only allows 1 file to be selected. +SWFUpload.prototype.selectFile = function () { + this.callFlash("SelectFile"); +}; + +// WARNING: this function does not work in Flash Player 10 +// Public: selectFiles causes a File Selection Dialog window to appear/ This +// dialog allows the user to select any number of files +// Flash Bug Warning: Flash limits the number of selectable files based on the combined length of the file names. +// If the selection name length is too long the dialog will fail in an unpredictable manner. There is no work-around +// for this bug. +SWFUpload.prototype.selectFiles = function () { + this.callFlash("SelectFiles"); +}; + + +// Public: startUpload starts uploading the first file in the queue unless +// the optional parameter 'fileID' specifies the ID +SWFUpload.prototype.startUpload = function (fileID) { + this.callFlash("StartUpload", [fileID]); +}; + +// Public: cancelUpload cancels any queued file. The fileID parameter may be the file ID or index. +// If you do not specify a fileID the current uploading file or first file in the queue is cancelled. +// If you do not want the uploadError event to trigger you can specify false for the triggerErrorEvent parameter. +SWFUpload.prototype.cancelUpload = function (fileID, triggerErrorEvent) { + if (triggerErrorEvent !== false) { + triggerErrorEvent = true; + } + this.callFlash("CancelUpload", [fileID, triggerErrorEvent]); +}; + +// Public: stopUpload stops the current upload and requeues the file at the beginning of the queue. +// If nothing is currently uploading then nothing happens. +SWFUpload.prototype.stopUpload = function () { + this.callFlash("StopUpload"); +}; + +/* ************************ + * Settings methods + * These methods change the SWFUpload settings. + * SWFUpload settings should not be changed directly on the settings object + * since many of the settings need to be passed to Flash in order to take + * effect. + * *********************** */ + +// Public: getStats gets the file statistics object. +SWFUpload.prototype.getStats = function () { + return this.callFlash("GetStats"); +}; + +// Public: setStats changes the SWFUpload statistics. You shouldn't need to +// change the statistics but you can. Changing the statistics does not +// affect SWFUpload accept for the successful_uploads count which is used +// by the upload_limit setting to determine how many files the user may upload. +SWFUpload.prototype.setStats = function (statsObject) { + this.callFlash("SetStats", [statsObject]); +}; + +// Public: getFile retrieves a File object by ID or Index. If the file is +// not found then 'null' is returned. +SWFUpload.prototype.getFile = function (fileID) { + if (typeof(fileID) === "number") { + return this.callFlash("GetFileByIndex", [fileID]); + } else { + return this.callFlash("GetFile", [fileID]); + } +}; + +// Public: addFileParam sets a name/value pair that will be posted with the +// file specified by the Files ID. If the name already exists then the +// exiting value will be overwritten. +SWFUpload.prototype.addFileParam = function (fileID, name, value) { + return this.callFlash("AddFileParam", [fileID, name, value]); +}; + +// Public: removeFileParam removes a previously set (by addFileParam) name/value +// pair from the specified file. +SWFUpload.prototype.removeFileParam = function (fileID, name) { + this.callFlash("RemoveFileParam", [fileID, name]); +}; + +// Public: setUploadUrl changes the upload_url setting. +SWFUpload.prototype.setUploadURL = function (url) { + this.settings.upload_url = url.toString(); + this.callFlash("SetUploadURL", [url]); +}; + +// Public: setPostParams changes the post_params setting +SWFUpload.prototype.setPostParams = function (paramsObject) { + this.settings.post_params = paramsObject; + this.callFlash("SetPostParams", [paramsObject]); +}; + +// Public: addPostParam adds post name/value pair. Each name can have only one value. +SWFUpload.prototype.addPostParam = function (name, value) { + this.settings.post_params[name] = value; + this.callFlash("SetPostParams", [this.settings.post_params]); +}; + +// Public: removePostParam deletes post name/value pair. +SWFUpload.prototype.removePostParam = function (name) { + delete this.settings.post_params[name]; + this.callFlash("SetPostParams", [this.settings.post_params]); +}; + +// Public: setFileTypes changes the file_types setting and the file_types_description setting +SWFUpload.prototype.setFileTypes = function (types, description) { + this.settings.file_types = types; + this.settings.file_types_description = description; + this.callFlash("SetFileTypes", [types, description]); +}; + +// Public: setFileSizeLimit changes the file_size_limit setting +SWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit) { + this.settings.file_size_limit = fileSizeLimit; + this.callFlash("SetFileSizeLimit", [fileSizeLimit]); +}; + +// Public: setFileUploadLimit changes the file_upload_limit setting +SWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit) { + this.settings.file_upload_limit = fileUploadLimit; + this.callFlash("SetFileUploadLimit", [fileUploadLimit]); +}; + +// Public: setFileQueueLimit changes the file_queue_limit setting +SWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit) { + this.settings.file_queue_limit = fileQueueLimit; + this.callFlash("SetFileQueueLimit", [fileQueueLimit]); +}; + +// Public: setFilePostName changes the file_post_name setting +SWFUpload.prototype.setFilePostName = function (filePostName) { + this.settings.file_post_name = filePostName; + this.callFlash("SetFilePostName", [filePostName]); +}; + +// Public: setUseQueryString changes the use_query_string setting +SWFUpload.prototype.setUseQueryString = function (useQueryString) { + this.settings.use_query_string = useQueryString; + this.callFlash("SetUseQueryString", [useQueryString]); +}; + +// Public: setRequeueOnError changes the requeue_on_error setting +SWFUpload.prototype.setRequeueOnError = function (requeueOnError) { + this.settings.requeue_on_error = requeueOnError; + this.callFlash("SetRequeueOnError", [requeueOnError]); +}; + +// Public: setHTTPSuccess changes the http_success setting +SWFUpload.prototype.setHTTPSuccess = function (http_status_codes) { + if (typeof http_status_codes === "string") { + http_status_codes = http_status_codes.replace(" ", "").split(","); + } + + this.settings.http_success = http_status_codes; + this.callFlash("SetHTTPSuccess", [http_status_codes]); +}; + +// Public: setHTTPSuccess changes the http_success setting +SWFUpload.prototype.setAssumeSuccessTimeout = function (timeout_seconds) { + this.settings.assume_success_timeout = timeout_seconds; + this.callFlash("SetAssumeSuccessTimeout", [timeout_seconds]); +}; + +// Public: setDebugEnabled changes the debug_enabled setting +SWFUpload.prototype.setDebugEnabled = function (debugEnabled) { + this.settings.debug_enabled = debugEnabled; + this.callFlash("SetDebugEnabled", [debugEnabled]); +}; + +// Public: setButtonImageURL loads a button image sprite +SWFUpload.prototype.setButtonImageURL = function (buttonImageURL) { + if (buttonImageURL == undefined) { + buttonImageURL = ""; + } + + this.settings.button_image_url = buttonImageURL; + this.callFlash("SetButtonImageURL", [buttonImageURL]); +}; + +// Public: setButtonDimensions resizes the Flash Movie and button +SWFUpload.prototype.setButtonDimensions = function (width, height) { + this.settings.button_width = width; + this.settings.button_height = height; + + var movie = this.getMovieElement(); + if (movie != undefined) { + movie.style.width = width + "px"; + movie.style.height = height + "px"; + } + + this.callFlash("SetButtonDimensions", [width, height]); +}; +// Public: setButtonText Changes the text overlaid on the button +SWFUpload.prototype.setButtonText = function (html) { + this.settings.button_text = html; + this.callFlash("SetButtonText", [html]); +}; +// Public: setButtonTextPadding changes the top and left padding of the text overlay +SWFUpload.prototype.setButtonTextPadding = function (left, top) { + this.settings.button_text_top_padding = top; + this.settings.button_text_left_padding = left; + this.callFlash("SetButtonTextPadding", [left, top]); +}; + +// Public: setButtonTextStyle changes the CSS used to style the HTML/Text overlaid on the button +SWFUpload.prototype.setButtonTextStyle = function (css) { + this.settings.button_text_style = css; + this.callFlash("SetButtonTextStyle", [css]); +}; +// Public: setButtonDisabled disables/enables the button +SWFUpload.prototype.setButtonDisabled = function (isDisabled) { + this.settings.button_disabled = isDisabled; + this.callFlash("SetButtonDisabled", [isDisabled]); +}; +// Public: setButtonAction sets the action that occurs when the button is clicked +SWFUpload.prototype.setButtonAction = function (buttonAction) { + this.settings.button_action = buttonAction; + this.callFlash("SetButtonAction", [buttonAction]); +}; + +// Public: setButtonCursor changes the mouse cursor displayed when hovering over the button +SWFUpload.prototype.setButtonCursor = function (cursor) { + this.settings.button_cursor = cursor; + this.callFlash("SetButtonCursor", [cursor]); +}; + +/* ******************************* + Flash Event Interfaces + These functions are used by Flash to trigger the various + events. + + All these functions a Private. + + Because the ExternalInterface library is buggy the event calls + are added to a queue and the queue then executed by a setTimeout. + This ensures that events are executed in a determinate order and that + the ExternalInterface bugs are avoided. +******************************* */ + +SWFUpload.prototype.queueEvent = function (handlerName, argumentArray) { + // Warning: Don't call this.debug inside here or you'll create an infinite loop + + if (argumentArray == undefined) { + argumentArray = []; + } else if (!(argumentArray instanceof Array)) { + argumentArray = [argumentArray]; + } + + var self = this; + if (typeof this.settings[handlerName] === "function") { + // Queue the event + this.eventQueue.push(function () { + this.settings[handlerName].apply(this, argumentArray); + }); + + // Execute the next queued event + setTimeout(function () { + self.executeNextEvent(); + }, 0); + + } else if (this.settings[handlerName] !== null) { + throw "Event handler " + handlerName + " is unknown or is not a function"; + } +}; + +// Private: Causes the next event in the queue to be executed. Since events are queued using a setTimeout +// we must queue them in order to garentee that they are executed in order. +SWFUpload.prototype.executeNextEvent = function () { + // Warning: Don't call this.debug inside here or you'll create an infinite loop + + var f = this.eventQueue ? this.eventQueue.shift() : null; + if (typeof(f) === "function") { + f.apply(this); + } +}; + +// Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterface cannot have +// properties that contain characters that are not valid for JavaScript identifiers. To work around this +// the Flash Component escapes the parameter names and we must unescape again before passing them along. +SWFUpload.prototype.unescapeFilePostParams = function (file) { + var reg = /[$]([0-9a-f]{4})/i; + var unescapedPost = {}; + var uk; + + if (file != undefined) { + for (var k in file.post) { + if (file.post.hasOwnProperty(k)) { + uk = k; + var match; + while ((match = reg.exec(uk)) !== null) { + uk = uk.replace(match[0], String.fromCharCode(parseInt("0x" + match[1], 16))); + } + unescapedPost[uk] = file.post[k]; + } + } + + file.post = unescapedPost; + } + + return file; +}; + +// Private: Called by Flash to see if JS can call in to Flash (test if External Interface is working) +SWFUpload.prototype.testExternalInterface = function () { + try { + return this.callFlash("TestExternalInterface"); + } catch (ex) { + return false; + } +}; + +// Private: This event is called by Flash when it has finished loading. Don't modify this. +// Use the swfupload_loaded_handler event setting to execute custom code when SWFUpload has loaded. +SWFUpload.prototype.flashReady = function () { + // Check that the movie element is loaded correctly with its ExternalInterface methods defined + var movieElement = this.getMovieElement(); + + if (!movieElement) { + this.debug("Flash called back ready but the flash movie can't be found."); + return; + } + + this.cleanUp(movieElement); + + this.queueEvent("swfupload_loaded_handler"); +}; + +// Private: removes Flash added fuctions to the DOM node to prevent memory leaks in IE. +// This function is called by Flash each time the ExternalInterface functions are created. +SWFUpload.prototype.cleanUp = function (movieElement) { + // Pro-actively unhook all the Flash functions + try { + if (this.movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE + this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)"); + for (var key in movieElement) { + try { + if (typeof(movieElement[key]) === "function") { + movieElement[key] = null; + } + } catch (ex) { + } + } + } + } catch (ex1) { + + } + + // Fix Flashes own cleanup code so if the SWFMovie was removed from the page + // it doesn't display errors. + window["__flash__removeCallback"] = function (instance, name) { + try { + if (instance) { + instance[name] = null; + } + } catch (flashEx) { + + } + }; + +}; + + +/* This is a chance to do something before the browse window opens */ +SWFUpload.prototype.fileDialogStart = function () { + this.queueEvent("file_dialog_start_handler"); +}; + + +/* Called when a file is successfully added to the queue. */ +SWFUpload.prototype.fileQueued = function (file) { + file = this.unescapeFilePostParams(file); + this.queueEvent("file_queued_handler", file); +}; + + +/* Handle errors that occur when an attempt to queue a file fails. */ +SWFUpload.prototype.fileQueueError = function (file, errorCode, message) { + file = this.unescapeFilePostParams(file); + this.queueEvent("file_queue_error_handler", [file, errorCode, message]); +}; + +/* Called after the file dialog has closed and the selected files have been queued. + You could call startUpload here if you want the queued files to begin uploading immediately. */ +SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued, numFilesInQueue) { + this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued, numFilesInQueue]); +}; + +SWFUpload.prototype.uploadStart = function (file) { + file = this.unescapeFilePostParams(file); + this.queueEvent("return_upload_start_handler", file); +}; + +SWFUpload.prototype.returnUploadStart = function (file) { + var returnValue; + if (typeof this.settings.upload_start_handler === "function") { + file = this.unescapeFilePostParams(file); + returnValue = this.settings.upload_start_handler.call(this, file); + } else if (this.settings.upload_start_handler != undefined) { + throw "upload_start_handler must be a function"; + } + + // Convert undefined to true so if nothing is returned from the upload_start_handler it is + // interpretted as 'true'. + if (returnValue === undefined) { + returnValue = true; + } + + returnValue = !!returnValue; + + this.callFlash("ReturnUploadStart", [returnValue]); +}; + + + +SWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_progress_handler", [file, bytesComplete, bytesTotal]); +}; + +SWFUpload.prototype.uploadError = function (file, errorCode, message) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_error_handler", [file, errorCode, message]); +}; + +SWFUpload.prototype.uploadSuccess = function (file, serverData, responseReceived) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_success_handler", [file, serverData, responseReceived]); +}; + +SWFUpload.prototype.uploadComplete = function (file) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_complete_handler", file); +}; + +/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the + internal debug console. You can override this event and have messages written where you want. */ +SWFUpload.prototype.debug = function (message) { + this.queueEvent("debug_handler", message); +}; + + +/* ********************************** + Debug Console + The debug console is a self contained, in page location + for debug message to be sent. The Debug Console adds + itself to the body if necessary. + + The console is automatically scrolled as messages appear. + + If you are using your own debug handler or when you deploy to production and + have debug disabled you can remove these functions to reduce the file size + and complexity. +********************************** */ + +// Private: debugMessage is the default debug_handler. If you want to print debug messages +// call the debug() function. When overriding the function your own function should +// check to see if the debug setting is true before outputting debug information. +SWFUpload.prototype.debugMessage = function (message) { + if (this.settings.debug) { + var exceptionMessage, exceptionValues = []; + + // Check for an exception object and print it nicely + if (typeof message === "object" && typeof message.name === "string" && typeof message.message === "string") { + for (var key in message) { + if (message.hasOwnProperty(key)) { + exceptionValues.push(key + ": " + message[key]); + } + } + exceptionMessage = exceptionValues.join("\n") || ""; + exceptionValues = exceptionMessage.split("\n"); + exceptionMessage = "EXCEPTION: " + exceptionValues.join("\nEXCEPTION: "); + SWFUpload.Console.writeLine(exceptionMessage); + } else { + SWFUpload.Console.writeLine(message); + } + } +}; + +SWFUpload.Console = {}; +SWFUpload.Console.writeLine = function (message) { + var console, documentForm; + + try { + console = document.getElementById("SWFUpload_Console"); + + if (!console) { + documentForm = document.createElement("form"); + document.getElementsByTagName("body")[0].appendChild(documentForm); + + console = document.createElement("textarea"); + console.id = "SWFUpload_Console"; + console.style.fontFamily = "monospace"; + console.setAttribute("wrap", "off"); + console.wrap = "off"; + console.style.overflow = "auto"; + console.style.width = "700px"; + console.style.height = "350px"; + console.style.margin = "5px"; + documentForm.appendChild(console); + } + + console.value += message + "\n"; + + console.scrollTop = console.scrollHeight - console.clientHeight; + } catch (ex) { + alert("Exception: " + ex.name + " Message: " + ex.message); + } +}; + +})(); + +(function() { +/* + Queue Plug-in + + Features: + *Adds a cancelQueue() method for cancelling the entire queue. + *All queued files are uploaded when startUpload() is called. + *If false is returned from uploadComplete then the queue upload is stopped. + If false is not returned (strict comparison) then the queue upload is continued. + *Adds a QueueComplete event that is fired when all the queued files have finished uploading. + Set the event handler with the queue_complete_handler setting. + + */ + +if (typeof(SWFUpload) === "function") { + SWFUpload.queue = {}; + + SWFUpload.prototype.initSettings = (function (oldInitSettings) { + return function () { + if (typeof(oldInitSettings) === "function") { + oldInitSettings.call(this); + } + + this.queueSettings = {}; + + this.queueSettings.queue_cancelled_flag = false; + this.queueSettings.queue_upload_count = 0; + + this.queueSettings.user_upload_complete_handler = this.settings.upload_complete_handler; + this.queueSettings.user_upload_start_handler = this.settings.upload_start_handler; + this.settings.upload_complete_handler = SWFUpload.queue.uploadCompleteHandler; + this.settings.upload_start_handler = SWFUpload.queue.uploadStartHandler; + + this.settings.queue_complete_handler = this.settings.queue_complete_handler || null; + }; + })(SWFUpload.prototype.initSettings); + + SWFUpload.prototype.startUpload = function (fileID) { + this.queueSettings.queue_cancelled_flag = false; + this.callFlash("StartUpload", [fileID]); + }; + + SWFUpload.prototype.cancelQueue = function () { + this.queueSettings.queue_cancelled_flag = true; + this.stopUpload(); + + var stats = this.getStats(); + while (stats.files_queued > 0) { + this.cancelUpload(); + stats = this.getStats(); + } + }; + + SWFUpload.queue.uploadStartHandler = function (file) { + var returnValue; + if (typeof(this.queueSettings.user_upload_start_handler) === "function") { + returnValue = this.queueSettings.user_upload_start_handler.call(this, file); + } + + // To prevent upload a real "FALSE" value must be returned, otherwise default to a real "TRUE" value. + returnValue = (returnValue === false) ? false : true; + + this.queueSettings.queue_cancelled_flag = !returnValue; + + return returnValue; + }; + + SWFUpload.queue.uploadCompleteHandler = function (file) { + var user_upload_complete_handler = this.queueSettings.user_upload_complete_handler; + var continueUpload; + + if (file.filestatus === SWFUpload.FILE_STATUS.COMPLETE) { + this.queueSettings.queue_upload_count++; + } + + if (typeof(user_upload_complete_handler) === "function") { + continueUpload = (user_upload_complete_handler.call(this, file) === false) ? false : true; + } else if (file.filestatus === SWFUpload.FILE_STATUS.QUEUED) { + // If the file was stopped and re-queued don't restart the upload + continueUpload = false; + } else { + continueUpload = true; + } + + if (continueUpload) { + var stats = this.getStats(); + if (stats.files_queued > 0 && this.queueSettings.queue_cancelled_flag === false) { + this.startUpload(); + } else if (this.queueSettings.queue_cancelled_flag === false) { + this.queueEvent("queue_complete_handler", [this.queueSettings.queue_upload_count]); + this.queueSettings.queue_upload_count = 0; + } else { + this.queueSettings.queue_cancelled_flag = false; + this.queueSettings.queue_upload_count = 0; + } + } + }; +} + +})(); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('pagebreak', function(K) { + var self = this; + var name = 'pagebreak'; + var pagebreakHtml = K.undef(self.pagebreakHtml, '
    '); + + self.clickToolbar(name, function() { + var cmd = self.cmd, range = cmd.range; + self.focus(); + var tail = self.newlineTag == 'br' || K.WEBKIT ? '' : ''; + self.insertHtml(pagebreakHtml + tail); + if (tail !== '') { + var p = K('#__kindeditor_tail_tag__', self.edit.doc); + range.selectNodeContents(p[0]); + p.removeAttr('id'); + cmd.select(); + } + }); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('plainpaste', function(K) { + var self = this, name = 'plainpaste'; + self.clickToolbar(name, function() { + var lang = self.lang(name + '.'), + html = '
    ' + + '
    ' + lang.comment + '
    ' + + '' + + '
    ', + dialog = self.createDialog({ + name : name, + width : 450, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var html = textarea.val(); + html = K.escape(html); + html = html.replace(/ {2}/g, '  '); + if (self.newlineTag == 'p') { + html = html.replace(/^/, '

    ').replace(/$/, '

    ').replace(/\n/g, '

    '); + } else { + html = html.replace(/\n/g, '
    $&'); + } + self.insertHtml(html).hideDialog().focus(); + } + } + }), + textarea = K('textarea', dialog.div); + textarea[0].focus(); + }); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('preview', function(K) { + var self = this, name = 'preview', undefined; + self.clickToolbar(name, function() { + var lang = self.lang(name + '.'), + html = '

    ' + + '' + + '
    ', + dialog = self.createDialog({ + name : name, + width : 750, + title : self.lang(name), + body : html + }), + iframe = K('iframe', dialog.div), + doc = K.iframeDoc(iframe); + doc.open(); + doc.write(self.fullHtml()); + doc.close(); + K(doc.body).css('background-color', '#FFF'); + iframe[0].contentWindow.focus(); + }); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('quickformat', function(K) { + var self = this, name = 'quickformat', + blockMap = K.toMap('blockquote,center,div,h1,h2,h3,h4,h5,h6,p'); + function getFirstChild(knode) { + var child = knode.first(); + while (child && child.first()) { + child = child.first(); + } + return child; + } + self.clickToolbar(name, function() { + self.focus(); + var doc = self.edit.doc, + range = self.cmd.range, + child = K(doc.body).first(), next, + nodeList = [], subList = [], + bookmark = range.createBookmark(true); + while(child) { + next = child.next(); + var firstChild = getFirstChild(child); + if (!firstChild || firstChild.name != 'img') { + if (blockMap[child.name]) { + child.html(child.html().replace(/^(\s| | )+/ig, '')); + child.css('text-indent', '2em'); + } else { + subList.push(child); + } + if (!next || (blockMap[next.name] || blockMap[child.name] && !blockMap[next.name])) { + if (subList.length > 0) { + nodeList.push(subList); + } + subList = []; + } + } + child = next; + } + K.each(nodeList, function(i, subList) { + var wrapper = K('

    ', doc); + subList[0].before(wrapper); + K.each(subList, function(i, knode) { + wrapper.append(knode); + }); + }); + range.moveToBookmark(bookmark); + self.addBookmark(); + }); +}); + +/** +-------------------------- +abcd
    +1234
    + +to + +

    + abcd
    + 1234
    +

    + +-------------------------- + +  abcd1233 +

    1234

    + +to + +

    abcd1233

    +

    1234

    + +-------------------------- +*//******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('table', function(K) { + var self = this, name = 'table', lang = self.lang(name + '.'), zeroborder = 'ke-zeroborder'; + // 设置颜色 + function _setColor(box, color) { + color = color.toUpperCase(); + box.css('background-color', color); + box.css('color', color === '#000000' ? '#FFFFFF' : '#000000'); + box.html(color); + } + // 初始化取色器 + var pickerList = []; + function _initColorPicker(dialogDiv, colorBox) { + colorBox.bind('click,mousedown', function(e){ + e.stopPropagation(); + }); + function removePicker() { + K.each(pickerList, function() { + this.remove(); + }); + pickerList = []; + K(document).unbind('click,mousedown', removePicker); + dialogDiv.unbind('click,mousedown', removePicker); + } + colorBox.click(function(e) { + removePicker(); + var box = K(this), + pos = box.pos(); + var picker = K.colorpicker({ + x : pos.x, + y : pos.y + box.height(), + z : 811214, + selectedColor : K(this).html(), + colors : self.colorTable, + noColor : self.lang('noColor'), + shadowMode : self.shadowMode, + click : function(color) { + _setColor(box, color); + removePicker(); + } + }); + pickerList.push(picker); + K(document).bind('click,mousedown', removePicker); + dialogDiv.bind('click,mousedown', removePicker); + }); + } + // 取得下一行cell的index + function _getCellIndex(table, row, cell) { + var rowSpanCount = 0; + for (var i = 0, len = row.cells.length; i < len; i++) { + if (row.cells[i] == cell) { + break; + } + rowSpanCount += row.cells[i].rowSpan - 1; + } + return cell.cellIndex - rowSpanCount; + } + self.plugin.table = { + //insert or modify table + prop : function(isInsert) { + var html = [ + '
    ', + //rows, cols + '
    ', + '', + lang.rows + '   ', + lang.cols + ' ', + '
    ', + //width, height + '
    ', + '', + lang.width + '   ', + '   ', + lang.height + '   ', + '', + '
    ', + //space, padding + '
    ', + '', + lang.padding + '   ', + lang.spacing + ' ', + '
    ', + //align + '
    ', + '', + '', + '
    ', + //border + '
    ', + '', + lang.borderWidth + '   ', + lang.borderColor + ' ', + '
    ', + //background color + '
    ', + '', + '', + '
    ', + '
    ' + ].join(''); + var bookmark = self.cmd.range.createBookmark(); + var dialog = self.createDialog({ + name : name, + width : 500, + title : self.lang(name), + body : html, + beforeRemove : function() { + colorBox.unbind(); + }, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var rows = rowsBox.val(), + cols = colsBox.val(), + width = widthBox.val(), + height = heightBox.val(), + widthType = widthTypeBox.val(), + heightType = heightTypeBox.val(), + padding = paddingBox.val(), + spacing = spacingBox.val(), + align = alignBox.val(), + border = borderBox.val(), + borderColor = K(colorBox[0]).html() || '', + bgColor = K(colorBox[1]).html() || ''; + if (rows == 0 || !/^\d+$/.test(rows)) { + alert(self.lang('invalidRows')); + rowsBox[0].focus(); + return; + } + if (cols == 0 || !/^\d+$/.test(cols)) { + alert(self.lang('invalidRows')); + colsBox[0].focus(); + return; + } + if (!/^\d*$/.test(width)) { + alert(self.lang('invalidWidth')); + widthBox[0].focus(); + return; + } + if (!/^\d*$/.test(height)) { + alert(self.lang('invalidHeight')); + heightBox[0].focus(); + return; + } + if (!/^\d*$/.test(padding)) { + alert(self.lang('invalidPadding')); + paddingBox[0].focus(); + return; + } + if (!/^\d*$/.test(spacing)) { + alert(self.lang('invalidSpacing')); + spacingBox[0].focus(); + return; + } + if (!/^\d*$/.test(border)) { + alert(self.lang('invalidBorder')); + borderBox[0].focus(); + return; + } + //modify table + if (table) { + if (width !== '') { + table.width(width + widthType); + } else { + table.css('width', ''); + } + if (table[0].width !== undefined) { + table.removeAttr('width'); + } + if (height !== '') { + table.height(height + heightType); + } else { + table.css('height', ''); + } + if (table[0].height !== undefined) { + table.removeAttr('height'); + } + table.css('background-color', bgColor); + if (table[0].bgColor !== undefined) { + table.removeAttr('bgColor'); + } + if (padding !== '') { + table[0].cellPadding = padding; + } else { + table.removeAttr('cellPadding'); + } + if (spacing !== '') { + table[0].cellSpacing = spacing; + } else { + table.removeAttr('cellSpacing'); + } + if (align !== '') { + table[0].align = align; + } else { + table.removeAttr('align'); + } + if (border !== '') { + table.attr('border', border); + } else { + table.removeAttr('border'); + } + if (border === '' || border === '0') { + table.addClass(zeroborder); + } else { + table.removeClass(zeroborder); + } + if (borderColor !== '') { + table.attr('borderColor', borderColor); + } else { + table.removeAttr('borderColor'); + } + self.hideDialog().focus(); + self.cmd.range.moveToBookmark(bookmark); + self.cmd.select(); + self.addBookmark(); + return; + } + //insert new table + var style = ''; + if (width !== '') { + style += 'width:' + width + widthType + ';'; + } + if (height !== '') { + style += 'height:' + height + heightType + ';'; + } + if (bgColor !== '') { + style += 'background-color:' + bgColor + ';'; + } + var html = '') + ''; + } + html += ''; + } + html += ''; + if (!K.IE) { + html += '
    '; + } + self.insertHtml(html); + self.select().hideDialog().focus(); + self.addBookmark(); + } + } + }), + div = dialog.div, + rowsBox = K('[name="rows"]', div).val(3), + colsBox = K('[name="cols"]', div).val(2), + widthBox = K('[name="width"]', div).val(100), + heightBox = K('[name="height"]', div), + widthTypeBox = K('[name="widthType"]', div), + heightTypeBox = K('[name="heightType"]', div), + paddingBox = K('[name="padding"]', div).val(2), + spacingBox = K('[name="spacing"]', div).val(0), + alignBox = K('[name="align"]', div), + borderBox = K('[name="border"]', div).val(1), + colorBox = K('.ke-input-color', div); + _initColorPicker(div, colorBox.eq(0)); + _initColorPicker(div, colorBox.eq(1)); + _setColor(colorBox.eq(0), '#000000'); + _setColor(colorBox.eq(1), ''); + // foucs and select + rowsBox[0].focus(); + rowsBox[0].select(); + var table; + if (isInsert) { + return; + } + //get selected table node + table = self.plugin.getSelectedTable(); + if (table) { + rowsBox.val(table[0].rows.length); + colsBox.val(table[0].rows.length > 0 ? table[0].rows[0].cells.length : 0); + rowsBox.attr('disabled', true); + colsBox.attr('disabled', true); + var match, + tableWidth = table[0].style.width || table[0].width, + tableHeight = table[0].style.height || table[0].height; + if (tableWidth !== undefined && (match = /^(\d+)((?:px|%)*)$/.exec(tableWidth))) { + widthBox.val(match[1]); + widthTypeBox.val(match[2]); + } else { + widthBox.val(''); + } + if (tableHeight !== undefined && (match = /^(\d+)((?:px|%)*)$/.exec(tableHeight))) { + heightBox.val(match[1]); + heightTypeBox.val(match[2]); + } + paddingBox.val(table[0].cellPadding || ''); + spacingBox.val(table[0].cellSpacing || ''); + alignBox.val(table[0].align || ''); + borderBox.val(table[0].border === undefined ? '' : table[0].border); + _setColor(colorBox.eq(0), K.toHex(table.attr('borderColor') || '')); + _setColor(colorBox.eq(1), K.toHex(table[0].style.backgroundColor || table[0].bgColor || '')); + widthBox[0].focus(); + widthBox[0].select(); + } + }, + //modify cell + cellprop : function() { + var html = [ + '
    ', + //width, height + '
    ', + '', + lang.width + '   ', + '   ', + lang.height + '   ', + '', + '
    ', + //align + '
    ', + '', + lang.textAlign + ' ', + lang.verticalAlign + ' ', + '
    ', + //border + '
    ', + '', + lang.borderWidth + '   ', + lang.borderColor + ' ', + '
    ', + //background color + '
    ', + '', + '', + '
    ', + '
    ' + ].join(''); + var bookmark = self.cmd.range.createBookmark(); + var dialog = self.createDialog({ + name : name, + width : 500, + title : self.lang('tablecell'), + body : html, + beforeRemove : function() { + colorBox.unbind(); + }, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var width = widthBox.val(), + height = heightBox.val(), + widthType = widthTypeBox.val(), + heightType = heightTypeBox.val(), + padding = paddingBox.val(), + spacing = spacingBox.val(), + textAlign = textAlignBox.val(), + verticalAlign = verticalAlignBox.val(), + border = borderBox.val(), + borderColor = K(colorBox[0]).html() || '', + bgColor = K(colorBox[1]).html() || ''; + if (!/^\d*$/.test(width)) { + alert(self.lang('invalidWidth')); + widthBox[0].focus(); + return; + } + if (!/^\d*$/.test(height)) { + alert(self.lang('invalidHeight')); + heightBox[0].focus(); + return; + } + if (!/^\d*$/.test(border)) { + alert(self.lang('invalidBorder')); + borderBox[0].focus(); + return; + } + cell.css({ + width : width !== '' ? (width + widthType) : '', + height : height !== '' ? (height + heightType) : '', + 'background-color' : bgColor, + 'text-align' : textAlign, + 'vertical-align' : verticalAlign, + 'border-width' : border, + 'border-style' : border !== '' ? 'solid' : '', + 'border-color' : borderColor + }); + self.hideDialog().focus(); + self.cmd.range.moveToBookmark(bookmark); + self.cmd.select(); + self.addBookmark(); + } + } + }), + div = dialog.div, + widthBox = K('[name="width"]', div).val(100), + heightBox = K('[name="height"]', div), + widthTypeBox = K('[name="widthType"]', div), + heightTypeBox = K('[name="heightType"]', div), + paddingBox = K('[name="padding"]', div).val(2), + spacingBox = K('[name="spacing"]', div).val(0), + textAlignBox = K('[name="textAlign"]', div), + verticalAlignBox = K('[name="verticalAlign"]', div), + borderBox = K('[name="border"]', div).val(1), + colorBox = K('.ke-input-color', div); + _initColorPicker(div, colorBox.eq(0)); + _initColorPicker(div, colorBox.eq(1)); + _setColor(colorBox.eq(0), '#000000'); + _setColor(colorBox.eq(1), ''); + // foucs and select + widthBox[0].focus(); + widthBox[0].select(); + // get selected cell + var cell = self.plugin.getSelectedCell(); + var match, + cellWidth = cell[0].style.width || cell[0].width || '', + cellHeight = cell[0].style.height || cell[0].height || ''; + if ((match = /^(\d+)((?:px|%)*)$/.exec(cellWidth))) { + widthBox.val(match[1]); + widthTypeBox.val(match[2]); + } else { + widthBox.val(''); + } + if ((match = /^(\d+)((?:px|%)*)$/.exec(cellHeight))) { + heightBox.val(match[1]); + heightTypeBox.val(match[2]); + } + textAlignBox.val(cell[0].style.textAlign || ''); + verticalAlignBox.val(cell[0].style.verticalAlign || ''); + var border = cell[0].style.borderWidth || ''; + if (border) { + border = parseInt(border); + } + borderBox.val(border); + _setColor(colorBox.eq(0), K.toHex(cell[0].style.borderColor || '')); + _setColor(colorBox.eq(1), K.toHex(cell[0].style.backgroundColor || '')); + widthBox[0].focus(); + widthBox[0].select(); + }, + insert : function() { + this.prop(true); + }, + 'delete' : function() { + var table = self.plugin.getSelectedTable(); + self.cmd.range.setStartBefore(table[0]).collapse(true); + self.cmd.select(); + table.remove(); + self.addBookmark(); + }, + colinsert : function(offset) { + var table = self.plugin.getSelectedTable()[0], + row = self.plugin.getSelectedRow()[0], + cell = self.plugin.getSelectedCell()[0], + index = cell.cellIndex + offset; + // 取得第一行的index + index += table.rows[0].cells.length - row.cells.length; + + for (var i = 0, len = table.rows.length; i < len; i++) { + var newRow = table.rows[i], + newCell = newRow.insertCell(index); + newCell.innerHTML = K.IE ? '' : '
    '; + // 调整下一行的单元格index + index = _getCellIndex(table, newRow, newCell); + } + self.cmd.range.selectNodeContents(cell).collapse(true); + self.cmd.select(); + self.addBookmark(); + }, + colinsertleft : function() { + this.colinsert(0); + }, + colinsertright : function() { + this.colinsert(1); + }, + rowinsert : function(offset) { + var table = self.plugin.getSelectedTable()[0], + row = self.plugin.getSelectedRow()[0], + cell = self.plugin.getSelectedCell()[0]; + var rowIndex = row.rowIndex; + if (offset === 1) { + rowIndex = row.rowIndex + (cell.rowSpan - 1) + offset; + } + var newRow = table.insertRow(rowIndex); + + for (var i = 0, len = row.cells.length; i < len; i++) { + // 调整cell个数 + if (row.cells[i].rowSpan > 1) { + len -= row.cells[i].rowSpan - 1; + } + var newCell = newRow.insertCell(i); + // copy colspan + if (offset === 1 && row.cells[i].colSpan > 1) { + newCell.colSpan = row.cells[i].colSpan; + } + newCell.innerHTML = K.IE ? '' : '
    '; + } + // 调整rowspan + for (var j = rowIndex; j >= 0; j--) { + var cells = table.rows[j].cells; + if (cells.length > i) { + for (var k = cell.cellIndex; k >= 0; k--) { + if (cells[k].rowSpan > 1) { + cells[k].rowSpan += 1; + } + } + break; + } + } + self.cmd.range.selectNodeContents(cell).collapse(true); + self.cmd.select(); + self.addBookmark(); + }, + rowinsertabove : function() { + this.rowinsert(0); + }, + rowinsertbelow : function() { + this.rowinsert(1); + }, + rowmerge : function() { + var table = self.plugin.getSelectedTable()[0], + row = self.plugin.getSelectedRow()[0], + cell = self.plugin.getSelectedCell()[0], + rowIndex = row.rowIndex, // 当前行的index + nextRowIndex = rowIndex + cell.rowSpan, // 下一行的index + nextRow = table.rows[nextRowIndex]; // 下一行 + // 最后一行不能合并 + if (table.rows.length <= nextRowIndex) { + return; + } + var cellIndex = cell.cellIndex; // 下一行单元格的index + if (nextRow.cells.length <= cellIndex) { + return; + } + var nextCell = nextRow.cells[cellIndex]; // 下一行单元格 + // 上下行的colspan不一致时不能合并 + if (cell.colSpan !== nextCell.colSpan) { + return; + } + cell.rowSpan += nextCell.rowSpan; + nextRow.deleteCell(cellIndex); + self.cmd.range.selectNodeContents(cell).collapse(true); + self.cmd.select(); + self.addBookmark(); + }, + colmerge : function() { + var table = self.plugin.getSelectedTable()[0], + row = self.plugin.getSelectedRow()[0], + cell = self.plugin.getSelectedCell()[0], + rowIndex = row.rowIndex, // 当前行的index + cellIndex = cell.cellIndex, + nextCellIndex = cellIndex + 1; + // 最后一列不能合并 + if (row.cells.length <= nextCellIndex) { + return; + } + var nextCell = row.cells[nextCellIndex]; + // 左右列的rowspan不一致时不能合并 + if (cell.rowSpan !== nextCell.rowSpan) { + return; + } + cell.colSpan += nextCell.colSpan; + row.deleteCell(nextCellIndex); + self.cmd.range.selectNodeContents(cell).collapse(true); + self.cmd.select(); + self.addBookmark(); + }, + rowsplit : function() { + var table = self.plugin.getSelectedTable()[0], + row = self.plugin.getSelectedRow()[0], + cell = self.plugin.getSelectedCell()[0], + rowIndex = row.rowIndex; + // 不是可分割单元格 + if (cell.rowSpan === 1) { + return; + } + var cellIndex = _getCellIndex(table, row, cell); + for (var i = 1, len = cell.rowSpan; i < len; i++) { + var newRow = table.rows[rowIndex + i], + newCell = newRow.insertCell(cellIndex); + if (cell.colSpan > 1) { + newCell.colSpan = cell.colSpan; + } + newCell.innerHTML = K.IE ? '' : '
    '; + // 调整下一行的单元格index + cellIndex = _getCellIndex(table, newRow, newCell); + } + K(cell).removeAttr('rowSpan'); + self.cmd.range.selectNodeContents(cell).collapse(true); + self.cmd.select(); + self.addBookmark(); + }, + colsplit : function() { + var table = self.plugin.getSelectedTable()[0], + row = self.plugin.getSelectedRow()[0], + cell = self.plugin.getSelectedCell()[0], + cellIndex = cell.cellIndex; + // 不是可分割单元格 + if (cell.colSpan === 1) { + return; + } + for (var i = 1, len = cell.colSpan; i < len; i++) { + var newCell = row.insertCell(cellIndex + i); + if (cell.rowSpan > 1) { + newCell.rowSpan = cell.rowSpan; + } + newCell.innerHTML = K.IE ? '' : '
    '; + } + K(cell).removeAttr('colSpan'); + self.cmd.range.selectNodeContents(cell).collapse(true); + self.cmd.select(); + self.addBookmark(); + }, + coldelete : function() { + var table = self.plugin.getSelectedTable()[0], + row = self.plugin.getSelectedRow()[0], + cell = self.plugin.getSelectedCell()[0], + index = cell.cellIndex; + for (var i = 0, len = table.rows.length; i < len; i++) { + var newRow = table.rows[i], + newCell = newRow.cells[index]; + if (newCell.colSpan > 1) { + newCell.colSpan -= 1; + if (newCell.colSpan === 1) { + K(newCell).removeAttr('colSpan'); + } + } else { + newRow.deleteCell(index); + } + // 跳过不需要删除的行 + if (newCell.rowSpan > 1) { + i += newCell.rowSpan - 1; + } + } + if (row.cells.length === 0) { + self.cmd.range.setStartBefore(table).collapse(true); + self.cmd.select(); + K(table).remove(); + } else { + self.cmd.selection(true); + } + self.addBookmark(); + }, + rowdelete : function() { + var table = self.plugin.getSelectedTable()[0], + row = self.plugin.getSelectedRow()[0], + cell = self.plugin.getSelectedCell()[0], + rowIndex = row.rowIndex; + // 从下到上删除 + for (var i = cell.rowSpan - 1; i >= 0; i--) { + table.deleteRow(rowIndex + i); + } + if (table.rows.length === 0) { + self.cmd.range.setStartBefore(table).collapse(true); + self.cmd.select(); + K(table).remove(); + } else { + self.cmd.selection(true); + } + self.addBookmark(); + } + }; + self.clickToolbar(name, self.plugin.table.prop); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('template', function(K) { + var self = this, name = 'template', lang = self.lang(name + '.'), + htmlPath = self.pluginsPath + name + '/html/'; + function getFilePath(fileName) { + return htmlPath + fileName + '?ver=' + encodeURIComponent(K.DEBUG ? K.TIME : K.VERSION); + } + self.clickToolbar(name, function() { + var lang = self.lang(name + '.'), + arr = ['
    ', + '
    ', + // left start + '
    ', + lang. selectTemplate + '
    ', + // right start + '
    ', + ' ', + '
    ', + '
    ', + '
    ', + '', + '
    '].join(''); + var dialog = self.createDialog({ + name : name, + width : 500, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var doc = K.iframeDoc(iframe); + self[checkbox[0].checked ? 'html' : 'insertHtml'](doc.body.innerHTML).hideDialog().focus(); + } + } + }); + var selectBox = K('select', dialog.div), + checkbox = K('[name="replaceFlag"]', dialog.div), + iframe = K('iframe', dialog.div); + checkbox[0].checked = true; + iframe.attr('src', getFilePath(selectBox.val())); + selectBox.change(function() { + iframe.attr('src', getFilePath(this.value)); + }); + }); +}); +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('wordpaste', function(K) { + var self = this, name = 'wordpaste'; + self.clickToolbar(name, function() { + var lang = self.lang(name + '.'), + html = '
    ' + + '
    ' + lang.comment + '
    ' + + '' + + '
    ', + dialog = self.createDialog({ + name : name, + width : 450, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var str = doc.body.innerHTML; + str = K.clearMsWord(str, self.filterMode ? self.htmlTags : K.options.htmlTags); + self.insertHtml(str).hideDialog().focus(); + } + } + }), + div = dialog.div, + iframe = K('iframe', div), + doc = K.iframeDoc(iframe); + if (!K.IE) { + doc.designMode = 'on'; + } + doc.open(); + doc.write('WordPaste'); + doc.write(''); + if (!K.IE) { + doc.write('
    '); + } + doc.write(''); + doc.close(); + if (K.IE) { + doc.body.contentEditable = 'true'; + } + iframe[0].contentWindow.focus(); + }); +}); diff --git a/src/main/webapp/assets/admin/script/modules/libs/kindeditor/kindeditor-min.js b/src/main/webapp/assets/admin/script/modules/libs/kindeditor/kindeditor-min.js new file mode 100644 index 0000000..a5126a6 --- /dev/null +++ b/src/main/webapp/assets/admin/script/modules/libs/kindeditor/kindeditor-min.js @@ -0,0 +1,182 @@ +/* KindEditor 4.1.10 (2013-11-23), Copyright (C) kindsoft.net, Licence: http://www.kindsoft.net/license.php */(function(w,i){function Z(a){if(!a)return!1;return Object.prototype.toString.call(a)==="[object Array]"}function wa(a){if(!a)return!1;return Object.prototype.toString.call(a)==="[object Function]"}function J(a,b){for(var c=0,d=b.length;c=0}function s(a,b){b=b||"px";return a&&/^\d+$/.test(a)?a+b:a}function t(a){var b;return a&&(b=/(\d+)/.exec(a))?parseInt(b[1],10):0}function C(a){return a.replace(/&/g,"&").replace(//g,">").replace(/"/g,""")}function fa(a){return a.replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/&/g,"&")}function ga(a){var b=a.split("-"),a="";m(b,function(b,d){a+=b>0?d.charAt(0).toUpperCase()+ +d.substr(1):d});return a}function ya(a){function b(a){a=parseInt(a,10).toString(16).toUpperCase();return a.length>1?a:"0"+a}return a.replace(/rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/ig,function(a,d,e,g){return"#"+b(d)+b(e)+b(g)})}function u(a,b){var b=b===i?",":b,c={},d=Z(a)?a:a.split(b),e;m(d,function(a,b){if(e=/^(\d+)\.\.(\d+)$/.exec(b))for(var d=parseInt(e[1],10);d<=parseInt(e[2],10);d++)c[d.toString()]=!0;else c[b]=!0});return c}function Ja(a,b){return Array.prototype.slice.call(a,b||0)} +function l(a,b){return a===i?b:a}function E(a,b,c){c||(c=b,b=null);var d;if(b){var e=function(){};e.prototype=b.prototype;d=new e;m(c,function(a,b){d[a]=b})}else d=c;d.constructor=a;a.prototype=d;a.parent=b?b.prototype:null}function eb(a){var b;if(b=/\{[\s\S]*\}|\[[\s\S]*\]/.exec(a))a=b[0];b=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;b.lastIndex=0;b.test(a)&&(a=a.replace(b,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})); +if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return eval("("+a+")");throw"JSON parse error";}function Rb(a,b,c){a.addEventListener?a.addEventListener(b,c,fb):a.attachEvent&&a.attachEvent("on"+b,c)}function za(a,b,c){a.removeEventListener?a.removeEventListener(b,c,fb):a.detachEvent&&a.detachEvent("on"+b,c)}function gb(a,b){this.init(a,b)}function hb(a){try{delete a[$]}catch(b){a.removeAttribute&& +a.removeAttribute($)}}function aa(a,b,c){if(b.indexOf(",")>=0)m(b.split(","),function(){aa(a,this,c)});else{var d=a[$]||null;d||(a[$]=++ib,d=ib);v[d]===i&&(v[d]={});var e=v[d][b];e&&e.length>0?za(a,b,e[0]):(v[d][b]=[],v[d].el=a);e=v[d][b];e.length===0&&(e[0]=function(b){var c=b?new gb(a,b):i;m(e,function(b,d){b>0&&d&&d.call(a,c)})});J(c,e)<0&&e.push(c);Rb(a,b,e[0])}}function ha(a,b,c){if(b&&b.indexOf(",")>=0)m(b.split(","),function(){ha(a,this,c)});else{var d=a[$]||null;if(d)if(b===i)d in v&&(m(v[d], +function(b,c){b!="el"&&c.length>0&&za(a,b,c[0])}),delete v[d],hb(a));else if(v[d]){var e=v[d][b];if(e&&e.length>0){c===i?(za(a,b,e[0]),delete v[d][b]):(m(e,function(a,b){a>0&&b===c&&e.splice(a,1)}),e.length==1&&(za(a,b,e[0]),delete v[d][b]));var g=0;m(v[d],function(){g++});g<2&&(delete v[d],hb(a))}}}}function jb(a,b){if(b.indexOf(",")>=0)m(b.split(","),function(){jb(a,this)});else{var c=a[$]||null;if(c){var d=v[c][b];if(v[c]&&d&&d.length>0)d[0]()}}}function Ka(a,b,c){b=/^\d{2,}$/.test(b)?b:b.toUpperCase().charCodeAt(0); +aa(a,"keydown",function(d){d.ctrlKey&&d.which==b&&!d.shiftKey&&!d.altKey&&(c.call(a),d.stop())})}function ba(a){for(var b={},c=/\s*([\w\-]+)\s*:([^;]*)(;|$)/g,d;d=c.exec(a);){var e=B(d[1].toLowerCase());d=B(ya(d[2]));b[e]=d}return b}function I(a){for(var b={},c=/\s+(?:([\w\-:]+)|(?:([\w\-:]+)=([^\s"'<>]+))|(?:([\w\-:"]+)="([^"]*)")|(?:([\w\-:"]+)='([^']*)'))(?=(?:\s|\/|>)+)/g,d;d=c.exec(a);){var e=(d[1]||d[2]||d[4]||d[6]).toLowerCase();b[e]=(d[2]?d[3]:d[4]?d[5]:d[7])||""}return b}function Sb(a,b){return a= +/\s+class\s*=/.test(a)?a.replace(/(\s+class=["']?)([^"']*)(["']?[\s>])/,function(a,d,e,g){return(" "+e+" ").indexOf(" "+b+" ")<0?e===""?d+b+g:d+e+" "+b+g:a}):a.substr(0,a.length-1)+' class="'+b+'">'}function Tb(a){var b="";m(ba(a),function(a,d){b+=a+":"+d+";"});return b}function ia(a,b,c,d){function e(a){for(var a=a.split("/"),b=[],c=0,d=a.length;c0&&b.pop():e!==""&&e!="."&&b.push(e)}return"/"+b.join("/")}function g(b,c){if(a.substr(0,b.length)===b){for(var e=[], +h=0;h0&&(h+="/"+e.join("/"));d=="/"&&(h+="/");return h+a.substr(b.length)}else if(f=/^(.*)\//.exec(b))return g(f[1],++c)}b=l(b,"").toLowerCase();a.substr(0,5)!="data:"&&(a=a.replace(/([^:])\/\//g,"$1/"));if(J(b,["absolute","relative","domain"])<0)return a;c=c||location.protocol+"//"+location.host;if(d===i)var h=location.pathname.match(/^(\/.*)\//),d=h?h[1]:"";var f;if(f=/^(\w+:\/\/[^\/]*)/.exec(a)){if(f[1]!==c)return a}else if(/^\w+:/.test(a))return a;/^\//.test(a)? +a=c+e(a.substr(1)):/^\w+:\/\//.test(a)||(a=c+e(d+"/"+a));b==="relative"?a=g(c+d,0).substr(2):b==="absolute"&&a.substr(0,c.length)===c&&(a=a.substr(c.length));return a}function U(a,b,c,d,e){a==null&&(a="");var c=c||"",d=l(d,!1),e=l(e,"\t"),g="xx-small,x-small,small,medium,large,x-large,xx-large".split(","),a=a.replace(/(<(?:pre|pre\s[^>]*)>)([\s\S]*?)(<\/pre>)/ig,function(a,b,c,d){return b+c.replace(/<(?:br|br\s[^>]*)>/ig,"\n")+d}),a=a.replace(/<(?:br|br\s[^>]*)\s*\/?>\s*<\/p>/ig,"

    "),a=a.replace(/(<(?:p|p\s[^>]*)>)\s*(<\/p>)/ig, +"$1
    $2"),a=a.replace(/\u200B/g,""),a=a.replace(/\u00A9/g,"©"),a=a.replace(/\u00AE/g,"®"),a=a.replace(/<[^>]+/g,function(a){return a.replace(/\s+/g," ")}),h={};b&&(m(b,function(a,b){for(var c=a.split(","),d=0,e=c.length;d]*)>)([\s\S]*?)(<\/script>)/ig,"")),h.style||(a=a.replace(/(<(?:style|style\s[^>]*)>)([\s\S]*?)(<\/style>)/ig,"")));var f=[],a=a.replace(/(\s*)<(\/)?([\w\-:]+)((?:\s+|(?:\s+[\w\-:]+)|(?:\s+[\w\-:]+=[^\s"'<>]+)|(?:\s+[\w\-:"]+="[^"]*")|(?:\s+[\w\-:"]+='[^']*'))*)(\/)?>(\s*)/g, +function(a,n,q,r,K,ja,i){var n=n||"",q=q||"",l=r.toLowerCase(),o=K||"",r=ja?" "+ja:"",i=i||"";if(b&&!h[l])return"";r===""&&kb[l]&&(r=" /");lb[l]&&(n&&(n=" "),i&&(i=" "));La[l]&&(q?i="\n":n="\n");d&&l=="br"&&(i="\n");if(mb[l]&&!La[l])if(d){q&&f.length>0&&f[f.length-1]===l?f.pop():f.push(l);i=n="\n";K=0;for(ja=q?f.length:f.length-1;K=0&&(z[a]=ia(d,c));(b&&a!=="style"&&!h[l]["*"]&&!h[l][a]||l==="body"&&a==="contenteditable"||/^kindeditor_\d+$/.test(a))&&delete z[a];if(a==="style"&&d!==""){var e=ba(d);m(e,function(a){b&&!h[l].style&&!h[l]["."+a]&&delete e[a]}); +var g="";m(e,function(a,b){g+=a+":"+b+";"});z.style=g}});o="";m(z,function(a,b){a==="style"&&b===""||(b=b.replace(/"/g,"""),o+=" "+a+'="'+b+'"')})}l==="font"&&(l="span");return n+"<"+q+l+o+r+">"+i}),a=a.replace(/(<(?:pre|pre\s[^>]*)>)([\s\S]*?)(<\/pre>)/ig,function(a,b,c,d){return b+c.replace(/\n/g,'\n')+d}),a=a.replace(/\n\s*\n/g,"\n"),a=a.replace(/\n/g,"\n");return B(a)}function nb(a,b){a=a.replace(//ig, +"").replace(//ig,"").replace(/]*>[\s\S]*?<\/style>/ig,"").replace(/]*>[\s\S]*?<\/script>/ig,"").replace(/]+>[\s\S]*?<\/w:[^>]+>/ig,"").replace(/]+>[\s\S]*?<\/o:[^>]+>/ig,"").replace(/[\s\S]*?<\/xml>/ig,"").replace(/<(?:table|td)[^>]*>/ig,function(a){return a.replace(/border-bottom:([#\w\s]+)/ig,"border:$1")});return U(a,b)}function ob(a){if(/\.(rm|rmvb)(\?|$)/i.test(a))return"audio/x-pn-realaudio-plugin";if(/\.(swf|flv)(\?|$)/i.test(a))return"application/x-shockwave-flash"; +return"video/x-ms-asf-plugin"}function pb(a){return I(unescape(a))}function Ma(a){var b="0&&(h+="width:"+c+"px;");/\D/.test(d)?h+="height:"+d+";":d>0&&(h+="height:"+d+"px;");c=/realaudio/i.test(e)?"ke-rm":/flash/i.test(e)?"ke-flash":"ke-media";c='';return c}function Aa(a,b){if(a.nodeType==9&&b.nodeType!=9)return!0;for(;b=b.parentNode;)if(b==a)return!0;return!1}function Ba(a,b){var b=b.toLowerCase(),c=null;if(!Vb&&a.nodeName.toLowerCase()!="script"){var d=a.ownerDocument.createElement("div");d.appendChild(a.cloneNode(!1));d=I(fa(d.innerHTML));b in d&&(c=d[b])}else try{c=a.getAttribute(b,2)}catch(e){c=a.getAttribute(b,1)}b==="style"&&c!==null&&(c=Tb(c));return c}function Ca(a,b){function c(a){if(typeof a!="string")return a;return a.replace(/([^\w\-])/g, +"\\$1")}function d(a,b){return a==="*"||a.toLowerCase()===c(b.toLowerCase())}function e(a,b,c){var e=[];(a=(c.ownerDocument||c).getElementById(a.replace(/\\/g,"")))&&d(b,a.nodeName)&&Aa(c,a)&&e.push(a);return e}function g(a,b,c){var e=c.ownerDocument||c,g=[],h,f,j;if(c.getElementsByClassName){e=c.getElementsByClassName(a.replace(/\\/g,""));h=0;for(f=e.length;h-1&&g.push(j)}return g}function h(a,b,d,e){for(var g=[],d=e.getElementsByTagName(d),h=0,f=d.length;h])+)/.exec(a))?j[1]:"*";if(j=/#((?:[\w\-]|\\.)+)$/.exec(a))c= +e(j[1],k,b);else if(j=/\.((?:[\w\-]|\\.)+)$/.exec(a))c=g(j[1],k,b);else if(j=/\[((?:[\w\-]|\\.)+)\]/.exec(a))c=h(j[1].toLowerCase(),null,k,b);else if(j=/\[((?:[\w\-]|\\.)+)\s*=\s*['"]?((?:\\.|[^'"]+)+)['"]?\]/.exec(a)){c=j[1].toLowerCase();j=j[2];if(c==="id")k=e(j,k,b);else if(c==="class")k=g(j,k,b);else if(c==="name"){c=[];j=(b.ownerDocument||b).getElementsByName(j.replace(/\\/g,""));for(var n,r=0,q=j.length;r1){var n=[];m(k,function(){m(Ca(this,b),function(){J(this,n)<0&&n.push(this)})});return n}for(var b=b||document,k=[],q,r=/((?:\\.|[^\s>])+|[\s>])/g;q=r.exec(a);)q[1]!==" "&&k.push(q[1]);q=[];if(k.length==1)return f(k[0],b);var r=!1,K,l,i,o,p,z,L,F,s,t;z=0;for(lenth=k.length;z")r=!0;else{if(z>0){l=[];L=0;for(s=q.length;L