tianbj %!s(int64=6) %!d(string=hai) anos
pai
achega
d46aff177d
Modificáronse 29 ficheiros con 5074 adicións e 48 borrados
  1. 18 16
      pom.xml
  2. 631 0
      src/main/java/net/mingsoft/cms/action/ArticleAction.java
  3. 22 0
      src/main/java/net/mingsoft/cms/action/BaseAction.java
  4. 317 0
      src/main/java/net/mingsoft/cms/action/ColumnAction.java
  5. 263 0
      src/main/java/net/mingsoft/cms/action/GeneraterAction.java
  6. 233 0
      src/main/java/net/mingsoft/cms/action/web/ArticleAction.java
  7. 128 0
      src/main/java/net/mingsoft/cms/action/web/FieldAction.java
  8. 305 0
      src/main/java/net/mingsoft/cms/action/web/MCmsAction.java
  9. 426 0
      src/main/java/net/mingsoft/cms/action/web/SearchAction.java
  10. 45 0
      src/main/java/net/mingsoft/cms/bean/ColumnArticleIdBean.java
  11. 191 0
      src/main/java/net/mingsoft/cms/biz/IArticleBiz.java
  12. 222 0
      src/main/java/net/mingsoft/cms/biz/impl/ArticleBizImpl.java
  13. 14 0
      src/main/java/net/mingsoft/cms/constant/Const.java
  14. 115 0
      src/main/java/net/mingsoft/cms/constant/ModelCode.java
  15. 59 0
      src/main/java/net/mingsoft/cms/constant/e/ColumnTypeEnum.java
  16. 169 0
      src/main/java/net/mingsoft/cms/dao/IArticleDao.java
  17. 624 0
      src/main/java/net/mingsoft/cms/dao/IArticleDao.xml
  18. 293 0
      src/main/java/net/mingsoft/cms/entity/ArticleEntity.java
  19. 6 0
      src/main/java/net/mingsoft/cms/resources/resources_zh_CN.properties
  20. 289 0
      src/main/java/net/mingsoft/cms/util/CmsParserUtil.java
  21. 41 26
      src/main/java/net/mingsoft/config/WebConfig.java
  22. 16 6
      src/main/resources/application.yml
  23. 231 0
      src/main/webapp/WEB-INF/manager/cms/article/article_form.ftl
  24. 163 0
      src/main/webapp/WEB-INF/manager/cms/article/article_main.ftl
  25. 57 0
      src/main/webapp/WEB-INF/manager/cms/article/index.ftl
  26. 2 0
      src/main/webapp/WEB-INF/manager/cms/column/shiro-button.ftl
  27. 7 0
      src/main/webapp/WEB-INF/manager/cms/column/shiro-update.ftl
  28. 161 0
      src/main/webapp/WEB-INF/manager/cms/generate/index.ftl
  29. 26 0
      src/main/webapp/WEB-INF/manager/main.ftl

+ 18 - 16
pom.xml

@@ -1,11 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://maven.apache.org/POM/4.0.0"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>net.mingsoft</groupId>
-	<artifactId>wb-mcms</artifactId>
-	<version>4.7.1</version>
+	<artifactId>mcms</artifactId>
+	<version>4.7.2</version>
 	<name>ms-mcms</name>
 	<properties>
 		<java.version>1.8</java.version>
@@ -37,12 +37,23 @@
 	<dependencies>
 		<dependency>
 			<groupId>net.mingsoft</groupId>
-			<artifactId>ms-mcms</artifactId>
-			<version>4.7.1</version>
+			<artifactId>ms-basic</artifactId>
+			<version>1.0.16</version>
+		</dependency>
+		<dependency>
+			<groupId>net.mingsoft</groupId>
+			<artifactId>ms-mpeople</artifactId>
+			<version>1.0.11</version>
+		</dependency>
+		<!-- 此部分是铭飞平台MStroe的客户端(MStore不在铭飞开源产品范围),如果不需要使用MStore可以删除掉 -->
+		<dependency>
+			<groupId>net.mingsoft</groupId>
+			<artifactId>ms-upgrader</artifactId>
+			<version>1.0.13</version>
 		</dependency>
 	</dependencies>
 	<build>
-		<finalName>wb-mcms</finalName>
+		<finalName>ms-mcms</finalName>
 		<plugins>
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
@@ -67,15 +78,6 @@
 					<fork>true</fork>
 				</configuration>
 			</plugin>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-war-plugin</artifactId>
-				<configuration>
-					<failOnMissingWebXml>false</failOnMissingWebXml>
-					<!-- 打包时候需需要启用,注意避免快照依赖的冗余jar包 -->
-					<!-- outputFileNameMapping>@{artifactId}@- @{baseVersion}@. @{extension}@</outputFileNameMapping -->
-				</configuration>
-			</plugin>
 		</plugins>
 		<resources>
 			<resource>

+ 631 - 0
src/main/java/net/mingsoft/cms/action/ArticleAction.java

@@ -0,0 +1,631 @@
+/**
+The MIT License (MIT) * Copyright (c) 2016 铭飞科技(mingsoft.net)
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package net.mingsoft.cms.action;
+
+import java.io.File;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import com.alibaba.fastjson.JSONArray;
+
+import net.mingsoft.base.entity.BaseEntity;
+import net.mingsoft.base.filter.DateValueFilter;
+import net.mingsoft.base.filter.DoubleValueFilter;
+import net.mingsoft.basic.action.BaseAction;
+import net.mingsoft.basic.bean.EUListBean;
+import net.mingsoft.basic.biz.IColumnBiz;
+import net.mingsoft.basic.entity.ColumnEntity;
+import net.mingsoft.basic.util.ArrysUtil;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.basic.util.FileUtil;
+import net.mingsoft.basic.util.StringUtil;
+import net.mingsoft.cms.biz.IArticleBiz;
+import net.mingsoft.cms.constant.ModelCode;
+import net.mingsoft.cms.constant.e.ColumnTypeEnum;
+import net.mingsoft.cms.entity.ArticleEntity;
+import net.mingsoft.mdiy.biz.IContentModelBiz;
+import net.mingsoft.mdiy.biz.IContentModelFieldBiz;
+import net.mingsoft.mdiy.entity.ContentModelEntity;
+import net.mingsoft.mdiy.entity.ContentModelFieldEntity;
+import net.mingsoft.mdiy.util.DictUtil;
+import net.mingsoft.mdiy.util.ParserUtil;
+
+/**
+ * @ClassName:  ArticleAction   
+ * @Description:TODO 文章管理   
+ * @author: 铭飞开发团队
+ * @date:   2018年1月31日 下午2:51:39   
+ *     
+ * @Copyright: 2018 www.mingsoft.net Inc. All rights reserved.
+ */
+@Controller
+@RequestMapping("/${ms.manager.path}/cms/article")
+public class ArticleAction extends BaseAction {
+	
+	/**
+	 * 上传路径
+	 */
+	@Value("${ms.upload.path}")
+	private String uploadFloderPath;
+	
+	/**
+	 * 业务层的注入
+	 */
+	@Autowired
+	private IColumnBiz columnBiz;
+
+	/**
+	 * 文章管理业务处理层
+	 */
+	@Autowired
+	private IArticleBiz articleBiz;
+
+	/**
+	 * 字段管理业务层
+	 */
+	@Autowired
+	private IContentModelFieldBiz fieldBiz;
+
+	/**
+	 * 内容管理业务层
+	 */
+	@Autowired
+	private IContentModelBiz contentBiz;
+
+	/**
+	 * 判断是否为checkbox类型
+	 */
+	private static final int checkBox = 11;
+
+
+	/**
+	 * 加载页面显示所有文章信息
+	 * 
+	 * @param request
+	 * @return 返回文章页面显示地址
+	 */
+	@SuppressWarnings("static-access")
+	@RequestMapping("/index")
+	public String index(HttpServletRequest request, ModelMap mode, HttpServletResponse response) {
+		// 获取站点id
+		int appId = BasicUtil.getAppId();
+		List<ColumnEntity> list = columnBiz.queryAll(appId, this.getModelCodeId(request, ModelCode.CMS_COLUMN));
+		request.setAttribute("listColumn", JSONArray.toJSONString(list));
+		// 返回路径
+		return "/cms/article/index"; // 这里表示显示/manager/cms/article/article_list.ftl
+	}
+
+	/**
+	 * 返回一个文章列表框架和一些基础数据
+	 * @param article
+	 * @param request
+	 * @param mode
+	 * @param response
+	 * @param categoryId
+	 * @return 返回一个文章列表界面
+	 */
+	@RequestMapping("/{categoryId}/main")
+	public String main(@ModelAttribute ArticleEntity article, HttpServletRequest request, ModelMap mode,
+			HttpServletResponse response, @PathVariable int categoryId) {
+		String articleType = request.getParameter("articleType");
+		String isParent = BasicUtil.getString("isParent", "false");
+		mode.addAttribute("isParent", isParent);
+		//使用糊涂工具排序使全部属性排在第一个
+		mode.addAttribute("articleTypeList", DictUtil.list("文章属性"));
+		mode.addAttribute("articleType", articleType);
+ 		mode.addAttribute("categoryId", categoryId);
+		//返回文章页面显示地址
+		return "/cms/article/article_main";
+	}
+	
+	/**
+	 * 加载页面显示所有文章信息
+	 * 
+	 * @param request
+	 * @return 返回文章页面显示数据
+	 */
+	@RequestMapping("/{categoryId}/list")
+	public void list(@ModelAttribute ArticleEntity article, HttpServletRequest request, ModelMap mode,
+			HttpServletResponse response, @PathVariable int categoryId) {
+		int[] basicCategoryIds = null;
+		String articleType = article.getArticleType();
+		if(StringUtils.isEmpty(articleType)){
+			articleType = BasicUtil.getString("articleTypeStr");
+		}
+		if(!StringUtils.isEmpty(articleType) && articleType.equals("a")){
+			articleType = null;
+		}
+		if(categoryId > 0){
+			 basicCategoryIds = columnBiz.queryChildrenCategoryIds(categoryId, BasicUtil.getAppId(),
+					BasicUtil.getModelCodeId(ModelCode.CMS_COLUMN));
+		}
+		int appId = BasicUtil.getAppId();
+		BasicUtil.startPage();
+		article.setBasicDisplay(-1);
+		//查询文章列表
+		List<ArticleEntity> articleList = articleBiz.query(appId, basicCategoryIds, articleType, null, null, true, null, null, article);
+		EUListBean _list = new EUListBean(articleList, (int) BasicUtil.endPage(articleList).getTotal());
+		//将数据以json数据的形式返回
+		this.outJson(response, net.mingsoft.base.util.JSONArray.toJSONString(_list, new DoubleValueFilter(),new DateValueFilter("yyyy-MM-dd")));
+		
+	}
+
+	/**
+	 * 添加文章页面
+	 * 
+	 * @return 保存文章的页面地址
+	 */
+	@SuppressWarnings("static-access")
+	@RequestMapping("/add")
+	public String add(ModelMap mode, HttpServletRequest request) {
+		int categoryId = BasicUtil.getInt("categoryId", 0);
+		String categoryTitle = request.getParameter("categoryTitle");
+		// 文章属性
+		mode.addAttribute("articleType", DictUtil.list("文章属性"));
+		// 站点ID
+		int appId = BasicUtil.getAppId();
+		List<ColumnEntity> list = columnBiz.queryAll(appId, this.getModelCodeId(request, ModelCode.CMS_COLUMN));
+		mode.addAttribute("appId", appId);
+		mode.addAttribute("listColumn", JSONArray.toJSONString(list));
+		boolean isEditCategory = false; // 新增,不是单篇
+		int columnType=1;//新增,不是单篇
+		if(categoryId != 0){
+			// 获取栏目id
+			ColumnEntity column = (ColumnEntity) columnBiz.getEntity(categoryId);
+			columnType = column.getColumnType();
+			// 判断栏目是否为"",如果是"",就重新赋值
+			if (StringUtils.isBlank(categoryTitle)) {
+				categoryTitle = column.getCategoryTitle();
+			}
+			// 判断栏目是否是单篇
+			if (column != null && column.getColumnType() == ColumnTypeEnum.COLUMN_TYPE_COVER.toInt()) {
+				isEditCategory = true; // 是单页
+				columnType = column.getColumnType();;
+			}
+		}
+		mode.addAttribute("categoryTitle", categoryTitle);
+		mode.addAttribute("isEditCategory", isEditCategory); // 新增状态
+		mode.addAttribute("columnType", columnType);
+		mode.addAttribute("categoryId", categoryId);
+		mode.addAttribute("articleImagesUrl", uploadFloderPath+net.mingsoft.base.constant.Const.SEPARATOR
+				+BasicUtil.getAppId()+net.mingsoft.base.constant.Const.SEPARATOR);
+		// 添加一个空的article实体
+		ArticleEntity article = new ArticleEntity();
+		mode.addAttribute("article", article);
+		mode.addAttribute("action", "save");
+		// 返回路径
+		return "/cms/article/article_form"; // 这里表示显示/manager/cms/article/article_save.ftl
+	}
+
+	/**
+	 * 获取表单信息进行保存
+	 * 
+	 * @param article
+	 *            文章对象
+	 */
+	@RequestMapping("/save")
+	@RequiresPermissions("article:save")
+	public void save(@ModelAttribute ArticleEntity article, HttpServletRequest request, HttpServletResponse response) {
+		// 获取站点id
+		int appId = BasicUtil.getAppId();
+		// 验证文章,文章自由排序,栏目id
+		if (!validateForm(article, response)) {
+			this.outJson(response, ModelCode.CMS_ARTICLE, false);
+
+		}
+		 
+		article.setBasicUpdateTime(new Timestamp(System.currentTimeMillis()));
+		// 文章类型
+		String langtyp[] = request.getParameterValues("articleType");
+		if (langtyp != null) {
+			StringBuffer sb = new StringBuffer();
+			for (int j = 0; j < langtyp.length; j++) {
+				sb.append(langtyp[j] + ",");
+			}
+		}
+		String checkboxType = BasicUtil.getString("checkboxType");
+		//如果选择一个属性不做排序操作
+		if(!StringUtils.isEmpty(checkboxType) && checkboxType.length()>2){
+			// 文章类型排序
+			article.setArticleType(ArrysUtil.sort(checkboxType, ",")+",");
+		}else{
+			article.setArticleType(checkboxType);
+		}
+		ColumnEntity column = (ColumnEntity) columnBiz.getEntity(article.getBasicCategoryId());
+		article.setColumn(column);
+		
+		// 添加文章所属的站点id
+		article.setArticleWebId(appId);
+		// 绑定模块编号
+		article.setBasicModelId(BasicUtil.getInt("modelId"));
+		// 保存文章实体
+
+		articleBiz.saveBasic(article);
+		if (column.getColumnType() == ColumnTypeEnum.COLUMN_TYPE_LIST.toInt()) {// 列表
+			article.setArticleUrl(column.getColumnPath() + File.separator + article.getBasicId() + ParserUtil.HTML_SUFFIX);
+		} else if (column.getColumnType() == ColumnTypeEnum.COLUMN_TYPE_COVER.toInt()) {// 单篇
+			article.setArticleUrl(column.getColumnPath() + File.separator + ParserUtil.INDEX+ParserUtil.HTML_SUFFIX);
+		}
+		articleBiz.updateBasic(article);
+
+		// 判断栏目是否存在新增字段
+		if (column.getColumnContentModelId() != 0) {
+			// 保存所有的字段信息
+			List<ContentModelFieldEntity> listField = fieldBiz.queryListByCmid(column.getColumnContentModelId());
+			// 获取内容模型实体
+			ContentModelEntity contentModel = (ContentModelEntity) contentBiz
+					.getEntity(column.getColumnContentModelId());
+			if (contentModel != null) {
+				// 保存新增字段的信息
+				Map<String, Object> param = this.checkField(listField, request, article.getBasicId());
+				fieldBiz.insertBySQL(contentModel.getCmTableName(), param);
+			}
+
+		}
+
+		//
+
+		if (article.getColumn().getColumnType() == ColumnTypeEnum.COLUMN_TYPE_COVER.toInt()) {
+			this.outJson(response, ModelCode.CMS_ARTICLE, true, "" + article.getColumn().getCategoryId(), article.getBasicId());
+		} else {
+			this.outJson(response, ModelCode.CMS_ARTICLE, true, article.getColumn().getCategoryId()+"", "");
+		}
+	}
+
+	/**
+	 * 验证表单
+	 * 
+	 * @param article
+	 * @param response
+	 * @return 返回Boolean类型 true:通过,false:有错
+	 */
+	public boolean validateForm(ArticleEntity article, HttpServletResponse response) {
+		// 对表单数据进行再次验证
+		// 验证文章标题是否为空
+		if (StringUtils.isBlank(article.getBasicTitle())) {
+			this.outJson(response, ModelCode.CMS_ARTICLE, false,
+					getResString("err.empty", this.getResString("basicTitle")));
+			return false;
+		}
+		// 验证文章所属是否为0
+		if (article.getBasicCategoryId() == 0) {
+			this.outJson(response, ModelCode.CMS_ARTICLE, false,
+					getResString("err.empty", this.getResString("basicCategoryId")));
+			return false;
+		}
+		// 验证文章标题长度,若超过定义长度则截取
+		if (!StringUtil.checkLength(article.getBasicTitle(), 1, 300)) {
+			this.outJson(response, ModelCode.CMS_ARTICLE, false,
+					getResString("err.length", this.getResString("basicTitle"), "1", "300"));
+			return false;
+		}
+		// 验证文章来源长度,若超过定义长度则截取
+		if (!StringUtils.isBlank(article.getArticleSource())
+				&& !StringUtil.checkLength(article.getArticleSource(), 1, 300)) {
+			this.outJson(response, ModelCode.CMS_ARTICLE, false,
+					getResString("err.length", this.getResString("articleSource"), "1", "300"));
+			return false;
+		}
+		// 验证文章作者长度,若超过定义长度则截取
+		if (!StringUtils.isBlank(article.getArticleAuthor())
+				&& !StringUtil.checkLength(article.getArticleAuthor(), 1, 12)) {
+			this.outJson(response, ModelCode.CMS_ARTICLE, false,
+					getResString("err.length", this.getResString("articleAuthor"), "1", "12"));
+			return false;
+		}
+		// 验证文章描述长度,若超过定义长度则截取
+		if (!StringUtils.isBlank(article.getBasicDescription())
+				&& !StringUtil.checkLength(article.getBasicDescription(), 1, 400)) {
+			this.outJson(response, ModelCode.CMS_ARTICLE, false,
+					getResString("err.length", this.getResString("basicDescription"), "1", "400"));
+			return false;
+		}
+		// 验证文章关键字长度,若超过定义长度则截取
+		if (!StringUtils.isBlank(article.getArticleKeyword())
+				&& !StringUtil.checkLength(article.getArticleKeyword(), 1, 155)) {
+			this.outJson(response, ModelCode.CMS_ARTICLE, false,
+					getResString("err.length", this.getResString("articleKeyword"), "1", "155"));
+			return false;
+		}
+		return true;
+	}
+
+	/**
+	 * 更新文章
+	 * 
+	 * @param basicId
+	 *            文章id
+	 * @param article
+	 *            文章实体
+	 * @param request
+	 * @param response
+	 */
+	@RequestMapping("/{basicId}/update")
+	@RequiresPermissions("article:update")
+	public void update(@PathVariable int basicId, @ModelAttribute ArticleEntity article, HttpServletRequest request,
+			HttpServletResponse response) {
+		// 获取站点id
+		int appId = BasicUtil.getAppId();
+		article.setBasicUpdateTime(new Timestamp(System.currentTimeMillis()));
+		// 文章类型
+		String checkboxType = BasicUtil.getString("checkboxType");
+		//如果选择一个属性不做排序操作
+		if(!StringUtils.isEmpty(checkboxType) && checkboxType.length()>2){
+			// 文章类型排序
+			article.setArticleType(ArrysUtil.sort(checkboxType, ",")+",");
+		}else{
+			article.setArticleType(checkboxType);
+		}
+		// 获取更改前的文章实体
+		ArticleEntity oldArticle = (ArticleEntity) articleBiz.getEntity(basicId);
+		// 获取栏目实体
+		ColumnEntity column = (ColumnEntity) columnBiz.getEntity(article.getBasicCategoryId());
+		if (oldArticle != null) {
+			// 获取更改前的文章所属栏目实体
+			ColumnEntity oldColumn = (ColumnEntity) columnBiz.getEntity(oldArticle.getBasicCategoryId());
+
+			// 通过表单类型id判断是否更改了表单类型,如果更改则先删除记录
+			if (oldColumn.getColumnContentModelId() != column.getColumnContentModelId()) {
+				// 获取旧的内容模型id
+				ContentModelEntity contentModel = (ContentModelEntity) contentBiz
+						.getEntity(oldColumn.getColumnContentModelId());
+				// 删除旧的内容模型中保存的值
+				Map<String, Integer> wheres = new HashMap<String, Integer>();
+				wheres.put("basicId", article.getBasicId());
+				if (contentModel != null) {
+					fieldBiz.deleteBySQL(contentModel.getCmTableName(), wheres);
+				}
+				// 判断栏目是否存在新增字段
+				if (column.getColumnContentModelId() != 0) {
+					// 保存所有的字段信息
+					List<ContentModelFieldEntity> listField = fieldBiz.queryListByCmid(column.getColumnContentModelId());
+					ContentModelEntity newContentModel = (ContentModelEntity) contentBiz
+							.getEntity(column.getColumnContentModelId());
+					if (newContentModel != null) {
+						Map<String, Object> param = this.checkField(listField, request, article.getBasicId());
+						fieldBiz.insertBySQL(newContentModel.getCmTableName(), param);
+					}
+				}
+			}
+		}
+		//判断是否修改了所属栏目
+		if(oldArticle.getBasicCategoryId()!=article.getBasicCategoryId()){
+			//拼接栏目路径和文章编号及文件后缀
+			article.setArticleUrl(column.getColumnPath() + File.separator + article.getBasicId() + ParserUtil.HTML_SUFFIX);
+		}
+		// 添加文章所属的站点id
+		article.setArticleWebId(appId);
+		// 设置文章所属的栏目实体
+		article.setColumn(column);
+
+		article.setBasicUpdateTime(new Date());
+
+		String articleType = request.getParameter("articleTypeJson");
+		articleBiz.updateBasic(article);
+
+		// 判断该文章是否存在新增字段
+		if (column.getColumnContentModelId() != 0) {
+			// 保存所有的字段信息
+			List<ContentModelFieldEntity> listField = fieldBiz.queryListByCmid(column.getColumnContentModelId());
+			// // update中的where条件
+			Map<String, Integer> where = new HashMap<String, Integer>();
+			// 压入默认的basicId字段
+			where.put("basicId", article.getBasicId());
+			// 遍历字段的信息
+			Map<String, Object> param = this.checkField(listField, request, article.getBasicId());
+			ContentModelEntity contentModel = (ContentModelEntity) contentBiz
+					.getEntity(column.getColumnContentModelId());
+			if (contentModel != null) {
+				// 遍历所有的字段实体,得到字段名列表信息
+				List<String> listFieldName = new ArrayList<String>();
+				listFieldName.add("basicId");
+				// 查询新增字段的信息
+				List fieldLists = fieldBiz.queryBySQL(contentModel.getCmTableName(), listFieldName, where);
+
+				// 判断新增字段表中是否存在该文章,不存在则保存,否则更新
+				if (fieldLists == null || fieldLists.size() == 0) {
+					fieldBiz.insertBySQL(contentModel.getCmTableName(), param);
+				} else {
+					fieldBiz.updateBySQL(contentModel.getCmTableName(), param, where);
+				}
+
+			}
+		}
+
+		switch (column.getColumnType()) {
+		case ColumnEntity.COLUMN_TYPE_COVER:
+			this.outJson(response, ModelCode.CMS_ARTICLE, true, column.getCategoryId() + "", "");
+			break;
+		case ColumnEntity.COLUMN_TYPE_LIST:
+			this.outJson(response, ModelCode.CMS_ARTICLE, true, column.getCategoryId() + "",
+					this.redirectBack(request, false));
+		}
+
+	}
+
+	/**
+	 * 显示更新内容
+	 * 
+	 * @param request
+	 * @return 修改文章的页面地址
+	 */
+	@RequestMapping("/{id}/edit")
+	public String edit(@PathVariable int id, ModelMap model, HttpServletRequest request) {
+
+		// 如果_categoryId大于0表示是编辑封面栏目,应该先查询分类下面的唯一一篇文章
+		String categoryTitle = request.getParameter("categoryTitle");
+		// 板块id
+		int categoryId = BasicUtil.getInt("categoryId", 0);
+		ArticleEntity articleEntity = null;
+		int appId = BasicUtil.getAppId();
+		model.addAttribute("appId", appId);
+		model.addAttribute("articleImagesUrl", "/upload/"+BasicUtil.getAppId()+"/");
+		model.addAttribute("action", "update");
+
+		if (categoryId > 0) { // 分类获取文章
+			articleEntity = articleBiz.getByCategoryId(categoryId);
+			ColumnEntity column = articleEntity.getColumn();
+			int columnType = column.getColumnType();
+			model.addAttribute("article", articleEntity);
+			// 文章属性
+			model.addAttribute("articleType", DictUtil.list("文章属性"));
+			model.addAttribute("categoryTitle", categoryTitle);
+			model.addAttribute("categoryId", categoryId);// 编辑封面
+			model.addAttribute("isEditCategory", true);// 编辑封面
+			model.addAttribute("columnType", columnType);
+			return "/cms/article/article_form";
+		} else if (id > 0) { // 文章id获取
+			// 允许编辑文章时更改分类
+			List<ColumnEntity> list = columnBiz.queryAll(appId, this.getModelCodeId(request, ModelCode.CMS_COLUMN));
+			@SuppressWarnings("static-access")
+			String listJsonString = JSONArray.toJSONString(list);
+			request.setAttribute("listColumn", listJsonString);
+			// 文章属性
+			model.addAttribute("articleType", DictUtil.list("文章属性"));
+
+			articleEntity = (ArticleEntity) articleBiz.getEntity(id);
+			model.addAttribute("article", articleEntity);
+			// 判断是否是封面类型的栏目,如果是封面类型的栏目有些信息需要屏蔽,例如分类
+			ColumnEntity column = articleEntity.getColumn();
+			int columnType = column.getColumnType();
+			if (column.getColumnType() == ColumnEntity.ColumnTypeEnum.COLUMN_TYPE_COVER.toInt()) {
+				model.addAttribute("categoryTitle", categoryTitle);
+				model.addAttribute("categoryId", column.getCategoryId());// 编辑封面
+				model.addAttribute("isEditCategory", true);// 编辑封面
+			} else {
+				model.addAttribute("categoryTitle", articleEntity.getColumn().getCategoryTitle());
+				model.addAttribute("isEditCategory", false);// 编辑文章
+			}
+			model.addAttribute("columnType", columnType);
+			model.addAttribute("categoryId", column.getCategoryId());// 编辑封面
+			model.addAttribute("websiteId", BasicUtil.getAppId());
+			return "/cms/article/article_form";
+		} else {// 非法
+			// return "/cms/article/article_form");
+			return this.redirectBack(request, true);
+		}
+	}
+
+	/**
+	 * 删除文章
+	 * 
+	 * @param request
+	 * @param response
+	 * @return
+	 */
+	@RequestMapping("/delete")
+	@RequiresPermissions("article:del")
+	public void delete(@RequestBody List<ArticleEntity> articles, HttpServletRequest request, HttpServletResponse response) {
+		int appId = BasicUtil.getAppId();
+		int[] ids = new int[articles.size()];
+		//循环获取id数据
+		for(int i=0;i<articles.size();i++){
+			ids[i] = articles.get(i).getArticleID();
+		}
+		
+		if (ids.length == 0 || ids == null) {
+			this.outJson(response, ModelCode.CMS_ARTICLE, false, "", this.redirectBack(request, false));
+			return;
+		}
+		// 删除多个帖子
+		articleBiz.deleteBasic(ids);
+		FileUtil.del(articles);
+		this.outJson(response, ModelCode.CMS_ARTICLE, true, "", this.redirectBack(request, false));
+	}
+
+	/**
+	 * 遍历出所有文章新增字段的信息
+	 * 
+	 * @param listField
+	 *            :字段列表
+	 * @param request
+	 * @param articleId
+	 *            文章id
+	 * @return 字段信息
+	 */
+	private Map checkField(List<ContentModelFieldEntity> listField, HttpServletRequest request, int articleId) {
+		Map<String, Object> mapParams = new HashMap();
+		// 压入默认的basicId字段
+		mapParams.put("basicId", articleId);
+		// 遍历字段名
+		for (int i = 0; i < listField.size(); i++) {
+			ContentModelFieldEntity field = (ContentModelFieldEntity) listField.get(i);
+			String fieldName = field.getFieldFieldName();
+			// 判断字段类型是否为checkbox类型
+			if (field.getFieldType() == checkBox) {
+				String langtyp[] = request.getParameterValues(field.getFieldFieldName());
+				if (langtyp != null) {
+					StringBuffer sb = new StringBuffer();
+					for (int j = 0; j < langtyp.length; j++) {
+						sb.append(langtyp[j] + ",");
+					}
+					mapParams.put(field.getFieldFieldName(), sb.toString());
+				} else {
+					mapParams.put(field.getFieldFieldName(), langtyp);
+				}
+			} else {
+				if (StringUtils.isBlank(request.getParameter(field.getFieldFieldName()))) {
+					mapParams.put(field.getFieldFieldName(), null);
+				} else {
+					mapParams.put(field.getFieldFieldName(), request.getParameter(field.getFieldFieldName()));
+				}
+			}
+		}
+		return mapParams;
+	}
+
+	/**
+	 * 查询单页栏目是否绑定了文章
+	 * 
+	 * @param article
+	 *            文章对象
+	 */
+	@RequestMapping("/{id}/queryColumnArticle")
+	public void queryColumnArticle(@PathVariable int id, HttpServletResponse response) {
+		List articls = articleBiz.queryListByColumnId(id);
+		if (articls == null || articls.size() == 0) {
+			this.outJson(response, ModelCode.CMS_ARTICLE, true, null);
+		} else {
+			this.outJson(response, ModelCode.CMS_ARTICLE, false, null);
+		}
+	}
+
+	
+}

+ 22 - 0
src/main/java/net/mingsoft/cms/action/BaseAction.java

@@ -0,0 +1,22 @@
+package net.mingsoft.cms.action;
+
+import java.util.MissingResourceException;
+
+/**
+ * @Author: 铭飞开源团队--huise
+ * @Date: 2019/8/9 20:47
+ */
+public class BaseAction extends net.mingsoft.mdiy.action.BaseAction{
+    @Override
+    protected String getResString(String key) {
+        // TODO Auto-generated method stub
+        String str = "";
+        try {
+            str = super.getResString(key);
+        } catch (MissingResourceException e) {
+            str = net.mingsoft.cms.constant.Const.RESOURCES.getString(key);
+        }
+
+        return str;
+    }
+}

+ 317 - 0
src/main/java/net/mingsoft/cms/action/ColumnAction.java

@@ -0,0 +1,317 @@
+package net.mingsoft.cms.action;
+
+
+import java.io.File;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import net.mingsoft.basic.util.ArrysUtil;
+import net.mingsoft.mdiy.util.DictUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.alibaba.fastjson.JSONArray;
+
+import net.mingsoft.basic.action.BaseAction;
+import net.mingsoft.basic.bean.EUListBean;
+import net.mingsoft.basic.biz.ICategoryBiz;
+import net.mingsoft.basic.biz.IColumnBiz;
+import net.mingsoft.basic.biz.IModelBiz;
+import net.mingsoft.basic.constant.Const;
+import net.mingsoft.basic.constant.ModelCode;
+import net.mingsoft.basic.constant.e.SessionConstEnum;
+import net.mingsoft.basic.entity.ColumnEntity;
+import net.mingsoft.basic.entity.ManagerEntity;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.basic.util.FileUtil;
+import net.mingsoft.basic.util.StringUtil;
+import net.mingsoft.mdiy.util.ParserUtil;
+
+
+
+/**
+ * 铭飞MS平台,通用栏目分类,为了区分文章栏目与其他栏目的权限,该类是从basic模块复制过来
+ * @author 铭飞开发团队
+ * @version
+ * 版本号:100-000-000<br/>
+ * 创建日期:2017年8月9日<br/>
+ * 历史修订:<br/>
+ */
+@Controller("articleColumnAction")
+@RequestMapping("/${ms.manager.path}/cms/column")
+public class ColumnAction extends BaseAction{
+
+
+	/**
+	 * 栏目业务层
+	 */
+	@Autowired
+	private IColumnBiz columnBiz;
+	@Autowired
+	private ICategoryBiz categoryBiz;
+
+	/**
+	 * 模块业务层注入
+	 */
+	@Autowired
+	private IModelBiz modelBiz;
+	/**
+	 * 返回主界面index
+	 */
+	@RequestMapping("/index")
+	@RequiresPermissions("cms:column:view")
+	public String index(HttpServletResponse response,HttpServletRequest request,ModelMap model){
+		model.addAttribute("model", "cms");
+		return "/basic/column/index";
+	}
+	/**
+	 * 栏目添加跳转页面
+	 *
+	 * @return
+	 */
+	@RequestMapping("/add")
+	public String add(HttpServletRequest request,ModelMap model) {
+		// 站点ID
+		int appId =BasicUtil.getAppId();
+		List<ColumnEntity> list = columnBiz.queryAll(appId, BasicUtil.getModelCodeId(net.mingsoft.cms.constant.ModelCode.CMS_COLUMN.toString()));
+		ColumnEntity columnSuper = new ColumnEntity();
+		// 栏目属性
+		model.addAttribute("columnFlag", DictUtil.list("栏目属性"));
+		model.addAttribute("appId",appId);
+		model.addAttribute("columnSuper", columnSuper);
+		model.addAttribute("column",new ColumnEntity());
+		model.addAttribute("listColumn", JSONArray.toJSONString(list));
+		model.addAttribute("model", "cms");
+		model.addAttribute("websiteId", appId);
+
+		return "/basic/column/form";
+	}
+
+	/**
+	 * 后台验证填写的栏目信息是否合法
+	 * @param column  栏目信息
+	 * @param response
+	 * @return false:不合法 true:合法
+	 */
+	private boolean checkForm(ColumnEntity column, HttpServletResponse response){
+		//栏目标题空值验证
+		if(StringUtils.isBlank(column.getCategoryTitle())){
+			this.outJson( response, ModelCode.COLUMN, false, getResString("err.empty", this.getResString("categoryTitle")));
+			return false;
+		}
+		//栏目标题长度验证
+		if(!StringUtil.checkLength(column.getCategoryTitle(), 1, 31)){
+			this.outJson( response, ModelCode.COLUMN, false, getResString("err.length", this.getResString("categoryTitle"), "1", "30"));
+			return false;
+		}
+		//栏目属性空值验证
+		if(StringUtils.isBlank(column.getColumnType()+"")){
+			this.outJson( response, ModelCode.COLUMN, false, getResString("err.empty", this.getResString("columnType")));
+			return false;
+		}
+
+		return true;
+	}
+
+	/**
+	 * 组织栏目链接地址
+	 * @param request
+	 * @param column 栏目实体
+	 */
+	private void columnPath(HttpServletRequest request,ColumnEntity column){
+		StringBuffer columnPath = new StringBuffer();
+		String file = BasicUtil.getRealPath("")+ParserUtil.HTML+File.separator+ column.getAppId();
+		String delFile = "";
+		//修改栏目路径时,删除已存在的文件夹
+		column = (ColumnEntity) columnBiz.getEntity(column.getCategoryId());
+		delFile = file + column.getColumnPath();
+		if(!StringUtils.isBlank(delFile)){
+			File delFileName = new File(delFile);
+			delFileName.delete();
+		}
+		//若为顶级栏目,则路径为:/+栏目ID
+		if(column.getCategoryCategoryId() == 0){
+			column.setColumnPath(File.separator+column.getCategoryId());
+			file = file + File.separator + column.getCategoryId();
+		} else {
+			List<ColumnEntity> list = columnBiz.queryParentColumnByColumnId(column.getCategoryId());
+			if(list != null){
+				StringBuffer temp = new StringBuffer();
+				for(int i = list.size()-1; i>=0; i--){
+					ColumnEntity entity = list.get(i);
+					columnPath.append(File.separator).append(entity.getCategoryId());
+					temp.append(File.separator).append(entity.getCategoryId());
+				}
+				column.setColumnPath(columnPath.append(File.separator).append(column.getCategoryId()).toString());
+				file = file + temp.toString() + File.separator + column.getCategoryId();
+			}
+		}
+		columnBiz.updateEntity(column);
+		//生成文件夹
+		File fileName = new File(file);
+		fileName.mkdir();
+	}
+
+	/**
+	 * @param column 栏目表实体
+	 * <i>column参数包含字段信息参考:</i><br/>
+	 * columnCategoryid:多个columnCategoryid直接用逗号隔开,例如columnCategoryid=1,2,3,4
+	 * 批量删除栏目表
+	 *            <dt><span class="strong">返回</span></dt><br/>
+	 *            <dd>{code:"错误编码",<br/>
+	 *            result:"true|false",<br/>
+	 *            resultMsg:"错误信息"<br/>
+	 *            }</dd>
+	 */
+	@RequestMapping("/delete")
+	@ResponseBody
+	public void delete(HttpServletResponse response, HttpServletRequest request) {
+		int[] ids = BasicUtil.getInts("ids", ",");
+		ColumnEntity column =new ColumnEntity();
+		for(int i=0;i<ids.length;i++){
+			column = (ColumnEntity) columnBiz.getEntity(ids[i]);
+			columnBiz.deleteCategory(ids[i]);
+			FileUtil.del(column);
+		};
+		this.outJson(response, true);
+	}
+
+	/**
+	 * 栏目更新页面跳转
+	 * @param columnId 栏目ID
+	 * @param request
+	 * @param model
+	 * @return 编辑栏目页
+	 */
+	@RequestMapping("/{columnId}/edit")
+	public String edit(@PathVariable int columnId, HttpServletRequest request,ModelMap model) {
+		// 获取管理实体
+		ManagerEntity managerSession = (ManagerEntity) BasicUtil.getSession( SessionConstEnum.MANAGER_SESSION);
+		// 站点ID
+		int appId = BasicUtil.getAppId();
+		List<ColumnEntity> list = new ArrayList<ColumnEntity>();
+		// 判断管理员权限,查询其管理的栏目集合
+		list = columnBiz.queryAll(appId, BasicUtil.getModelCodeId(net.mingsoft.cms.constant.ModelCode.CMS_COLUMN.toString()));
+		//查询当前栏目实体
+		ColumnEntity column = (ColumnEntity) columnBiz.getEntity(columnId);
+		// 栏目属性
+		model.addAttribute("columnFlag", DictUtil.list("栏目属性"));
+		model.addAttribute("appId",appId);
+		model.addAttribute("column", column);
+		model.addAttribute("columnc", column.getCategoryId());
+		ColumnEntity columnSuper = new ColumnEntity();
+		// 获取父栏目对象
+		if (column.getCategoryCategoryId() != Const.COLUMN_TOP_CATEGORY_ID) {
+			columnSuper = (ColumnEntity) columnBiz.getEntity(column.getCategoryCategoryId());
+		}
+		model.addAttribute("columnSuper", columnSuper);
+		model.addAttribute("listColumn", JSONArray.toJSONString(list));
+		model.addAttribute("model", "cms");
+		model.addAttribute("websiteId", appId);
+		return "/basic/column/form";
+	}
+
+	/**
+	 * 栏目首页面列表显示
+	 */
+	@SuppressWarnings("deprecation")
+	@RequestMapping("/list")
+	public void list(@ModelAttribute ColumnEntity column,HttpServletResponse response, HttpServletRequest request,ModelMap model) {
+
+		// 站点ID有session获取
+		int websiteId = BasicUtil.getAppId();
+		// 需要打开的栏目节点树的栏目ID
+		List list = columnBiz.queryAll(websiteId, BasicUtil.getModelCodeId(net.mingsoft.cms.constant.ModelCode.CMS_COLUMN.toString()));
+		EUListBean _list = new EUListBean(list, list.size());
+		this.outJson(response, net.mingsoft.base.util.JSONArray.toJSONString(_list));
+	}
+
+	/**
+	 * 栏目添加
+	 *
+	 * @param column
+	 *            栏目对象
+	 * @return 返回页面跳转
+	 */
+	@RequestMapping("/save")
+	public void save(@ModelAttribute ColumnEntity column,HttpServletRequest request,HttpServletResponse response) {
+		if(!checkForm(column,response)){
+			return;
+		}
+		column.setCategoryAppId( BasicUtil.getAppId());
+		column.setAppId(BasicUtil.getAppId());
+		column.setCategoryManagerId(getManagerBySession(request).getManagerId());
+		column.setCategoryDateTime(new Timestamp(System.currentTimeMillis()));
+		column.setCategoryModelId(BasicUtil.getModelCodeId(net.mingsoft.cms.constant.ModelCode.CMS_COLUMN.toString()));
+		String checkboxType = BasicUtil.getString("checkboxType");
+		//如果选择一个属性不做排序操作
+		if(!StringUtils.isEmpty(checkboxType) && checkboxType.length()>2){
+			column.setColumnFlag(ArrysUtil.sort(checkboxType, ",")+",");
+		}else{
+			column.setColumnFlag(checkboxType);
+		}
+		if(column.getColumnType()==ColumnEntity.ColumnTypeEnum.COLUMN_TYPE_COVER.toInt()){
+			column.setColumnListUrl(null);
+		}
+		columnBiz.saveCategory(column);
+		this.columnPath(request,column);
+		this.outJson(response, ModelCode.COLUMN, true,null,JSONArray.toJSONString(column.getCategoryId()));
+	}
+
+	/**
+	 * 更新栏目
+	 * @param column 栏目实体
+	 * @param request
+	 * @param response
+	 */
+	@RequestMapping("/update")
+	@ResponseBody
+	public void update(@ModelAttribute ColumnEntity column,HttpServletRequest request,HttpServletResponse response) {
+		//获取站点ID
+		int websiteId = BasicUtil.getAppId();
+		//检测栏目信息是否合法
+		if(!checkForm(column,response)){
+			return;
+		}
+		//若栏目管理属性为单页,则栏目的列表模板地址设为Null
+		if(column.getColumnType()==ColumnEntity.ColumnTypeEnum.COLUMN_TYPE_COVER.toInt()){
+			column.setColumnListUrl(null);
+		}
+		column.setCategoryManagerId(getManagerBySession(request).getManagerId());
+		column.setAppId(websiteId);
+		String checkboxType = BasicUtil.getString("checkboxType");
+		//如果选择一个属性不做排序操作
+		if(!StringUtils.isEmpty(checkboxType) && checkboxType.length()>2){
+			column.setColumnFlag(ArrysUtil.sort(checkboxType, ",")+",");
+		}else{
+			column.setColumnFlag(checkboxType);
+		}
+		columnBiz.updateCategory(column);
+		this.columnPath(request,column);
+		//查询当前栏目是否有子栏目,
+		List<ColumnEntity> childList = columnBiz.queryChild(column.getCategoryId(), websiteId,BasicUtil.getModelCodeId(net.mingsoft.cms.constant.ModelCode.CMS_COLUMN.toString()),null);
+		if(childList != null && childList.size()>0){
+			//改变子栏目的顶级栏目ID为当前栏目的父级栏目ID
+			for(int i=0;i<childList.size();i++){
+				childList.get(i).setCategoryCategoryId(column.getCategoryId());
+				childList.get(i).setCategoryManagerId(getManagerBySession(request).getManagerId());
+				childList.get(i).setAppId(websiteId);
+				columnBiz.updateCategory(childList.get(i));
+				//组织子栏目链接地址
+				this.columnPath(request, childList.get(i));
+			}
+		}
+		this.outJson(response, ModelCode.COLUMN, true,null,JSONArray.toJSONString(column.getCategoryId()));
+	}
+}

+ 263 - 0
src/main/java/net/mingsoft/cms/action/GeneraterAction.java

@@ -0,0 +1,263 @@
+/**
+The MIT License (MIT) * Copyright (c) 2016 铭飞科技(mingsoft.net)
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package net.mingsoft.cms.action;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.bean.copier.CopyOptions;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.alibaba.fastjson.JSONArray;
+import net.mingsoft.basic.action.BaseAction;
+import net.mingsoft.basic.biz.IColumnBiz;
+import net.mingsoft.basic.biz.IModelBiz;
+import net.mingsoft.basic.entity.AppEntity;
+import net.mingsoft.basic.entity.CategoryEntity;
+import net.mingsoft.basic.entity.ColumnEntity;
+import net.mingsoft.cms.bean.ColumnArticleIdBean;
+import net.mingsoft.cms.biz.IArticleBiz;
+import net.mingsoft.cms.constant.ModelCode;
+import net.mingsoft.cms.util.CmsParserUtil;
+import net.mingsoft.mdiy.biz.IContentModelBiz;
+import net.mingsoft.mdiy.biz.IContentModelFieldBiz;
+
+import cn.hutool.core.io.FileUtil;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.mdiy.util.ParserUtil;
+
+/**
+ * 
+ * @ClassName: GeneraterAction
+ * @Description:TODO 生成器
+ * @author: 铭飞开发团队
+ * @date: 2018年1月31日 下午2:52:07
+ * 
+ * @Copyright: 2018 www.mingsoft.net Inc. All rights reserved.
+ */
+@Controller("cmsGenerater")
+@RequestMapping("/${ms.manager.path}/cms/generate")
+@Scope("request")
+public class GeneraterAction extends BaseAction {
+
+	/**
+	 * 文章管理业务层
+	 */
+	@Autowired
+	private IArticleBiz articleBiz;
+
+	/**
+	 * 栏目管理业务层
+	 */
+	@Autowired
+	private IColumnBiz columnBiz;
+
+	/**
+	 * 模块管理业务层
+	 */
+	@Autowired
+	private IModelBiz modelBiz;
+
+	@Value("${ms.manager.path}")
+	private String managerPath;
+
+	/**
+	 * 新增字段业务层
+	 */
+	@Autowired
+	protected IContentModelFieldBiz fieldBiz;
+
+	/**
+	 * 自定义模型业务层
+	 */
+	@Autowired
+	protected IContentModelBiz contentBiz;
+
+	/**
+	 * 更新主页
+	 * 
+	 * @return
+	 */
+	@RequestMapping("/index")
+	public String index(HttpServletRequest request, ModelMap model) {
+		// 该站点ID有session提供
+		int websiteId = BasicUtil.getAppId();
+		Integer modelId = modelBiz.getEntityByModelCode(ModelCode.CMS_COLUMN).getModelId(); // 查询当前模块编号
+		// 获取所有的内容管理栏目
+		List<ColumnEntity> list = columnBiz.queryAll(websiteId, modelId);
+		model.addAttribute("list", JSONArray.toJSONString(list));
+		model.addAttribute("now", new Date());
+		return "/cms/generate/index";
+	}
+
+	/**
+	 * 生成主页
+	 * 
+	 * @param request
+	 * @param response
+	 */
+	@RequestMapping("/generateIndex")
+	@RequiresPermissions("cms:generate:index")
+	@ResponseBody
+	public void generateIndex(HttpServletRequest request, HttpServletResponse response) {
+		// 模版文件名称
+		String tmpFileName = request.getParameter("url");
+		// 生成后的文件名称
+		String generateFileName = request.getParameter("position");
+		
+		// 获取文件所在路径 首先判断用户输入的模版文件是否存在
+		if (!FileUtil.exist(ParserUtil.buildTempletPath())) {
+			this.outJson(response, false, getResString("templet.file"));
+		} else {
+			try {
+				CmsParserUtil.generate(tmpFileName, generateFileName);
+				this.outJson(response, true);
+			} catch (IOException e) {
+				e.printStackTrace();
+				this.outJson(response, false);
+			}
+		}
+	}
+	
+
+
+	/**
+	 * 生成列表的静态页面
+	 * 
+	 * @param request
+	 * @param response
+	 * @param columnId
+	 */
+	@RequestMapping("/{columnId}/genernateColumn")
+	@RequiresPermissions("cms:generate:column")
+	@ResponseBody
+	public void genernateColumn(HttpServletRequest request, HttpServletResponse response, @PathVariable int columnId) {
+		// 获取站点id
+		AppEntity app = BasicUtil.getApp();
+		List<ColumnEntity> columns = new ArrayList<ColumnEntity>();
+		// 如果栏目id小于0则更新所有的栏目,否则只更新选中的栏目
+		int modelId = BasicUtil.getModelCodeId(ModelCode.CMS_COLUMN); // 查询当前模块编号
+		if (columnId > 0) {
+			List<CategoryEntity> categorys = columnBiz.queryChildrenCategory(columnId, app.getAppId(), modelId);
+			for (CategoryEntity c : categorys) {
+				columns.add((ColumnEntity) columnBiz.getEntity(c.getCategoryId()));
+			}
+		} else {
+			// 获取所有的内容管理栏目
+			columns = columnBiz.queryAll(app.getAppId(), modelId);
+		}
+		List<ColumnArticleIdBean> articleIdList = null;
+		try {
+			// 1、设置模板文件夹路径
+			// 获取栏目列表模版
+			for (ColumnEntity column : columns) {
+				// 判断模板文件是否存在
+				if (!FileUtil.exist(ParserUtil.buildTempletPath(column.getColumnUrl()))) {
+					continue;
+				}
+				articleIdList = articleBiz.queryIdsByCategoryIdForParser(column.getCategoryId(), null, null);
+				// 判断列表类型
+				switch (column.getColumnType()) {
+				case ColumnEntity.COLUMN_TYPE_LIST: // 列表
+					CmsParserUtil.generateList(column, articleIdList.size());
+					break;
+				case ColumnEntity.COLUMN_TYPE_COVER:// 单页
+					if(articleIdList.size()==0){
+						ColumnArticleIdBean columnArticleIdBean=new ColumnArticleIdBean();
+						CopyOptions copyOptions=CopyOptions.create();
+						copyOptions.setIgnoreError(true);
+						BeanUtil.copyProperties(column,columnArticleIdBean,copyOptions);
+						articleIdList.add(columnArticleIdBean);
+					}
+					CmsParserUtil.generateBasic(articleIdList);
+					break;
+					default:
+						throw new IllegalStateException("Unexpected value: " + column.getColumnType());
+				}
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+			this.outJson(response, false);
+		}
+		this.outJson(response, true);
+	}
+
+	/**
+	 * 根据栏目id更新所有的文章
+	 * 
+	 * @param request
+	 * @param response
+	 * @param columnId
+	 */
+	@RequestMapping("/{columnId}/generateArticle")
+	@RequiresPermissions("cms:generate:article")
+	@ResponseBody
+	public void generateArticle(HttpServletRequest request, HttpServletResponse response, @PathVariable int columnId) {
+		String dateTime = request.getParameter("dateTime");
+		// 网站风格物理路径
+		List<ColumnArticleIdBean> articleIdList = null;
+		try {
+			// 查出所有文章(根据选择栏目)包括子栏目
+			articleIdList = articleBiz.queryIdsByCategoryIdForParser(columnId, dateTime, null);
+			// 有符合条件的新闻就更新
+			if (articleIdList.size() > 0) {
+				CmsParserUtil.generateBasic(articleIdList);
+			}
+			this.outJson(response, true);
+		} catch (IOException e) {
+			e.printStackTrace();
+			this.outJson(response, false);
+		}
+	}
+	
+
+
+	/**
+	 * 用户预览主页
+	 * 
+	 * @param request
+	 * @return
+	 */
+	@RequestMapping("/{position}/viewIndex")
+	public String viewIndex(HttpServletRequest request, @PathVariable String position, HttpServletResponse response) {
+		AppEntity app = BasicUtil.getApp();
+		// 组织主页预览地址
+		String indexPosition = app.getAppHostUrl() + File.separator + ParserUtil.HTML + File.separator + app.getAppId()
+				+ File.separator + position + ParserUtil.HTML_SUFFIX;
+		return "redirect:" + indexPosition;
+	}
+}

+ 233 - 0
src/main/java/net/mingsoft/cms/action/web/ArticleAction.java

@@ -0,0 +1,233 @@
+/**
+The MIT License (MIT) * Copyright (c) 2016 铭飞科技(mingsoft.net)
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package net.mingsoft.cms.action.web;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+
+import io.swagger.annotations.ApiOperation;
+import net.mingsoft.base.filter.DateValueFilter;
+import net.mingsoft.basic.action.BaseAction;
+import net.mingsoft.basic.bean.ListBean;
+import net.mingsoft.basic.biz.IColumnBiz;
+import net.mingsoft.basic.entity.ColumnEntity;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.cms.biz.IArticleBiz;
+import net.mingsoft.cms.entity.ArticleEntity;
+import net.mingsoft.mdiy.biz.IContentModelBiz;
+import net.mingsoft.mdiy.biz.IContentModelFieldBiz;
+import net.mingsoft.mdiy.entity.ContentModelEntity;
+import springfox.documentation.annotations.ApiIgnore;
+
+/**
+ * 
+ * @ClassName:  ArticleAction   
+ * @Description:TODO 前段文章控制,如果标签不能满足可以使用这个控制来满足用户的查询文章需求,主要是通过ajax返回json数据格式   
+ * @author: 铭飞开发团队
+ * @date:   2018年1月31日 下午2:52:44   
+ *     
+ * @Copyright: 2018 www.mingsoft.net Inc. All rights reserved.
+ */
+@Controller("jsonApiArticle")
+@RequestMapping("/mcms/article")
+public class ArticleAction extends BaseAction {
+
+	/**
+	 * 文章管理业务处理层
+	 */
+	@Autowired
+	private IArticleBiz articleBiz;
+
+	/**
+	 * 栏目管理业务处理层
+	 */
+	@Autowired
+	private IColumnBiz columnBiz;
+
+	/**
+	 * 内容模型管理业务处理层
+	 */
+	@Autowired
+	private IContentModelBiz contentModelBiz;
+
+	/**
+	 * 自定义字段管理业务处理层
+	 */
+	@Autowired
+	private IContentModelFieldBiz fieldBiz;
+
+	/**
+	 * 文章信息
+	 * 
+	 * @param basicId
+	 *            文章编号
+	 *            <dt><span class="strong">返回</span></dt><br/>
+	 *            {"basicCategoryId":分类编号,basicTitle
+	 *            :"标题",basicDescription:"描述",basicThumbnails:"缩略图",
+	 *            basicDateTime:"发布时间",basicUpdateTime:"更新时间","basicHit":点击数,
+	 *            "basicId":编号 articleContent:"文章内容","basicSort":排序,[自定义模型字段]}
+	 */
+	@GetMapping("/{basicId}/detail")
+	@ResponseBody
+	public void detail(@PathVariable int basicId, HttpServletRequest request, HttpServletResponse response) {
+		ArticleEntity article = articleBiz.getById(basicId);
+		if (article == null) {
+			this.outJson(response, "");
+			return;
+		}
+		// 获取文章栏目id获取栏目实体
+		ColumnEntity column = (ColumnEntity) columnBiz.getEntity(article.getBasicCategoryId());
+		ContentModelEntity contentModel = (ContentModelEntity) contentModelBiz
+				.getEntity(column.getColumnContentModelId());
+
+		// 判断内容模型的值
+		if (contentModel != null) {
+			Map where = new HashMap();
+			// 压入basicId字段的值
+			where.put("basicId", basicId);
+			// 遍历所有的字段实体,得到字段名列表信息
+			List<String> listFieldName = new ArrayList<String>();
+			listFieldName.add("basicId");
+			// 查询新增字段的信息
+			List fieldLists = fieldBiz.queryBySQL(contentModel.getCmTableName(), listFieldName, where);
+			if (fieldLists.size() > 0) {
+				Map map = (Map) fieldLists.get(0);
+				article.setExtendsFields(map);
+			}
+		}
+
+		this.outJson(response, JSONObject.toJSONStringWithDateFormat(article, "yyyy-MM-dd hh:mm:ss"));
+	}
+
+
+	/**
+	 * 文章列表信息
+	 * 
+	 * @param pageSize
+	 *            一页显示数量
+	 * @param pageNum
+	 *            当前页码
+	 * @param basicCategoryId
+	 *            分类编号
+	 *            <dt><span class="strong">返回</span></dt><br/>
+	 *            {"list":"[{
+	 *            "basicTitle":"标题",
+	 *            "basicDescription":"描述",
+	 *            "basicThumbnails":"缩略图",
+	 *            "basicDateTime":"发布时间",
+	 *            "basicUpdateTime":"更新时间",
+	 *            "basicHit":点击数,
+	 *            "basicId":编号,
+	 *            "articleContent":文章内容,
+	 *            "articleAuthor":文章作者
+	 *      	  "articleType":文章属性,
+	 *      	  "articleSource":文章的来源,
+	 *      	  "articleUrl":文章跳转链接地址,
+	 *      	  "articleKeyword":文章关键字,
+	 *      	  "articleCategoryId":文章所属的分类Id,
+	 *      	  "articleTypeLinkURL":文章分类url地址,主要是用户生成html使用,
+	 *            "order":"排序方式",
+	 *            "orderBy":"排序字段     
+	 *            }],
+	 *             "page":{"endRow": 2,  当前页面最后一个元素在数据库中的行号
+	 * 				"firstPage": 1, 第一页页码
+	 * 				"hasNextPage": true存在下一页false不存在, 
+	 * 				"hasPreviousPage": true存在上一页false不存在, 
+	 * 				"isFirstPage": true是第一页false不是第一页, 
+	 * 				"isLastPage": true是最后一页false不是最后一页, 
+	 * 				"lastPage": 最后一页的页码, 
+	 * 				"navigatePages": 导航数量,实现 1...5.6.7....10效果, 
+	 * 				"navigatepageNums": []导航页码集合, 
+	 * 				"nextPage": 下一页, 
+	 * 				"pageNum": 当前页码, 
+	 * 				"pageSize": 一页显示数量, 
+	 * 				"pages": 总页数, 
+	 * 				"prePage": 上一页, 
+	 * 				"size": 总记录, 
+	 * 				"startRow":当前页面第一个元素在数据库中的行号, 
+	 * 				"total":总记录数量
+	 * 				}
+	 */
+	@RequestMapping(value = "/list",method= RequestMethod.GET)
+	@ApiOperation(value="文章列表信息")
+	@ResponseBody
+	public void list(@ModelAttribute @ApiIgnore ArticleEntity article, HttpServletRequest request, HttpServletResponse response) {
+		int appId = BasicUtil.getAppId();
+		int[] ids = null;
+		if (article.getBasicCategoryId()>0) {
+			 ids = new int[]{article.getBasicCategoryId()};
+		}
+		//默认为desc排序
+		boolean isOrder = true;
+		if(!StringUtils.isBlank(article.getOrder())){
+			String	basicOrder = article.getOrder();
+			if(basicOrder.equalsIgnoreCase("asc")){
+				isOrder = false;
+			}
+		}
+		BasicUtil.startPage();
+		List<ArticleEntity> list = articleBiz.query(appId, ids, null, null, article.getOrderBy(), isOrder, null, null, article);
+		
+		for(ArticleEntity _article : list){
+			// 获取文章栏目id获取栏目实体
+			ColumnEntity column = (ColumnEntity) columnBiz.getEntity(_article.getBasicCategoryId());
+			ContentModelEntity contentModel = (ContentModelEntity) contentModelBiz
+					.getEntity(column.getColumnContentModelId());
+
+			// 判断内容模型的值
+			if (contentModel != null) {
+				Map where = new HashMap();
+				// 压入basicId字段的值
+				where.put("basicId", _article.getBasicId());
+				// 遍历所有的字段实体,得到字段名列表信息
+				List<String> listFieldName = new ArrayList<String>();
+				listFieldName.add("basicId");
+				// 查询新增字段的信息
+				List fieldLists = fieldBiz.queryBySQL(contentModel.getCmTableName(), listFieldName, where);
+				if (fieldLists.size() > 0) {
+					Map map = (Map) fieldLists.get(0);
+					_article.setExtendsFields(map);
+				}
+			}
+		}
+		this.outJson(response, JSONArray.toJSONString(new ListBean(list, BasicUtil.endPage(list)),new DateValueFilter("yyyy-MM-dd HH:mm:ss")));
+	}
+
+}

+ 128 - 0
src/main/java/net/mingsoft/cms/action/web/FieldAction.java

@@ -0,0 +1,128 @@
+/**
+The MIT License (MIT) * Copyright (c) 2016 铭飞科技(mingsoft.net)
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package net.mingsoft.cms.action.web;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.alibaba.fastjson.JSONObject;
+import net.mingsoft.basic.biz.IColumnBiz;
+import net.mingsoft.mdiy.biz.IContentModelBiz;
+import net.mingsoft.mdiy.biz.IContentModelFieldBiz;
+import net.mingsoft.basic.entity.ColumnEntity;
+import net.mingsoft.mdiy.entity.ContentModelEntity;
+import net.mingsoft.mdiy.entity.ContentModelFieldEntity;
+
+import net.mingsoft.base.action.BaseAction;
+import net.mingsoft.basic.util.BasicUtil;
+
+/**
+ * 
+ * 
+ * 
+ * <p>
+ * <b>铭飞科技</b>
+ * </p>
+ * 
+ * <p>
+ * Copyright: Copyright (c) 2014 - 2015
+ * </p>
+ *
+ * @author 史爱华
+ *
+ * <p>
+ * Comments: 供前端页面获取自定义模型中字段实体信息
+ * </p>
+ *
+ * <p>
+ * Create Date:2015-07-11
+ * </p>
+ *
+ * <p>
+ * Modification history:
+ * </p>
+ */
+@Controller("webField")
+@RequestMapping("/field")
+public class FieldAction extends BaseAction{
+	
+	/**
+	 * 栏目业务层
+	 */
+	@Autowired
+	private IColumnBiz columnBiz;
+	
+	/**
+	 * 内容模型业务层
+	 */
+	@Autowired
+	private IContentModelBiz contentModelBiz;
+	
+	/**
+	 * 字段管理业务层
+	 */
+	@Autowired
+	private IContentModelFieldBiz fieldBiz;
+	
+	/**
+	 * 
+	 * 根据当前栏目id和字段名称获取自定义模型中的字段实体信息
+	 * @param request
+	 * @param response
+	 */
+	@RequestMapping("/{columId}/getEntity")
+	@ResponseBody
+	public void getEntity(@PathVariable int columId,HttpServletRequest request, HttpServletResponse response) {
+		System.out.println("111");
+		BasicUtil.setSession("xxx", "888");
+		System.err.println("session:"+BasicUtil.getSession("xxx"));
+		//获取字段名称
+		String fieldFieldName = request.getParameter("fieldFieldName");
+		//根据栏目id获取栏目实体
+		ColumnEntity column = (ColumnEntity) this.columnBiz.getEntity(columId);
+		if(column==null){
+			this.outJson(response, this.getResString("err"));
+			return;
+		}else{
+			//判断该栏目下是存在内容模型
+			if(column.getColumnContentModelId()>0){
+				//获取当前栏目对应的内容模型
+				ContentModelEntity contentModel = (ContentModelEntity) this.contentModelBiz.getEntity(column.getColumnContentModelId());
+				if(contentModel==null){
+					this.outJson(response, this.getResString("err"));
+					return;
+				}
+				//获取字段实体
+				ContentModelFieldEntity field = fieldBiz.getEntityByCmId(column.getColumnContentModelId(), fieldFieldName);
+				//返回字段实体
+				this.outJson(response, JSONObject.toJSONString(field));
+			}
+		}
+		
+	}
+}

+ 305 - 0
src/main/java/net/mingsoft/cms/action/web/MCmsAction.java

@@ -0,0 +1,305 @@
+/**
+ The MIT License (MIT) * Copyright (c) 2016 铭飞科技(mingsoft.net)
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package net.mingsoft.cms.action.web;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import cn.hutool.core.io.FileUtil;
+import com.github.pagehelper.PageHelper;
+import net.mingsoft.base.constant.Const;
+import net.mingsoft.basic.util.SpringUtil;
+import net.mingsoft.cms.constant.e.ColumnTypeEnum;
+import net.mingsoft.mdiy.biz.IContentModelBiz;
+import net.mingsoft.mdiy.entity.ContentModelEntity;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.PageUtil;
+import freemarker.core.ParseException;
+import freemarker.template.MalformedTemplateNameException;
+import freemarker.template.TemplateNotFoundException;
+import net.mingsoft.basic.biz.IColumnBiz;
+import net.mingsoft.basic.entity.ColumnEntity;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.cms.bean.ColumnArticleIdBean;
+import net.mingsoft.cms.biz.IArticleBiz;
+import net.mingsoft.cms.entity.ArticleEntity;
+import net.mingsoft.cms.util.CmsParserUtil;
+import net.mingsoft.mdiy.bean.PageBean;
+import net.mingsoft.mdiy.biz.IPageBiz;
+import net.mingsoft.mdiy.entity.PageEntity;
+import net.mingsoft.mdiy.util.ParserUtil;
+
+/**
+ * 动态生成页面,需要后台配置自定义页数据
+ *
+ * @author 铭飞开源团队
+ * @date 2018年12月17日
+ */
+@Controller("dynamicPageAction")
+@RequestMapping("/mcms")
+public class MCmsAction extends net.mingsoft.cms.action.BaseAction {
+
+	/**
+	 * 自定义页面业务层
+	 */
+	@Autowired
+	private IPageBiz pageBiz;
+
+	/**
+	 * 文章管理业务处理层
+	 */
+	@Autowired
+	private IArticleBiz articleBiz;
+
+	/**
+	 * 栏目业务层
+	 */
+	@Autowired
+	private IColumnBiz columnBiz;
+
+
+	// 如商城就为:/mall/{key}.do
+	/**
+	 * 前段会员中心所有页面都可以使用该方法 请求地址例如: /{diy}.do,例如登陆界面,与注册界面都可以使用
+	 *
+	 * @param key
+	 */
+	@RequestMapping("/{diy}.do")
+	@ExceptionHandler(java.lang.NullPointerException.class)
+	public void diy(@PathVariable(value = "diy") String diy, HttpServletRequest req, HttpServletResponse resp) {
+		Map map = BasicUtil.assemblyRequestMap();
+		map.put(ParserUtil.URL, BasicUtil.getUrl());
+		//动态解析
+		map.put(ParserUtil.IS_DO,true);
+		//设置动态请求的模块路径
+		map.put(ParserUtil.MODEL_NAME, "mcms");
+		//解析后的内容
+		String content = "";
+		PageEntity page = new PageEntity();
+		page.setPageKey(diy);
+		//根据请求路径查询模版文件
+		PageEntity _page = (PageEntity) pageBiz.getEntity(page);
+		try {
+			content = CmsParserUtil.generate(_page.getPagePath(), map, isMobileDevice(req));
+		} catch (TemplateNotFoundException e) {
+			e.printStackTrace();
+		} catch (MalformedTemplateNameException e) {
+			e.printStackTrace();
+		} catch (ParseException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		this.outString(resp, content);
+	}
+
+	/**
+	 * 动态列表页
+	 */
+	@GetMapping("/index.do")
+	public void index(HttpServletRequest req, HttpServletResponse resp) {
+		Map map = BasicUtil.assemblyRequestMap();
+		map.put(ParserUtil.URL, BasicUtil.getUrl());
+		//动态解析
+		map.put(ParserUtil.IS_DO,true);
+		//设置动态请求的模块路径
+		map.put(ParserUtil.MODEL_NAME, "mcms");
+		//解析后的内容
+		String content = "";
+		try {
+			//根据模板路径,参数生成
+			content = CmsParserUtil.generate(ParserUtil.INDEX+ParserUtil.HTM_SUFFIX, map, isMobileDevice(req));
+		} catch (TemplateNotFoundException e) {
+			e.printStackTrace();
+		} catch (MalformedTemplateNameException e) {
+			e.printStackTrace();
+		} catch (ParseException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		this.outString(resp, content);
+	}
+
+	/**
+	 * 动态列表页
+	 * @param req
+	 * @param resp
+	 * @param pageNumber 设置列表当前页
+	 * @param typeid 栏目编号
+	 * @param size 显示条数
+	 */
+	@GetMapping("/list.do")
+	public void list(HttpServletRequest req, HttpServletResponse resp) {
+		Map map = BasicUtil.assemblyRequestMap();
+		//获取栏目编号
+		int typeId = BasicUtil.getInt(ParserUtil.TYPE_ID,0);
+		int size = BasicUtil.getInt(ParserUtil.SIZE,10);
+
+		//获取文章总数
+		List<ColumnArticleIdBean> columnArticles = articleBiz.queryIdsByCategoryIdForParser(typeId, null, null);
+		//判断栏目下是否有文章
+		if(columnArticles.size()==0){
+			this.outJson(resp, false);
+		}
+		//设置分页类
+		PageBean page = new PageBean();
+		int total = PageUtil.totalPage(columnArticles.size(), size);
+		map.put(ParserUtil.COLUMN, columnArticles.get(0));
+		//获取总数
+		page.setTotal(total);
+		//设置栏目编号
+		map.put(ParserUtil.TYPE_ID, typeId);
+		//设置列表当前页
+		map.put(ParserUtil.PAGE_NO, BasicUtil.getInt(ParserUtil.PAGE_NO,1));
+
+		map.put(ParserUtil.URL, BasicUtil.getUrl());
+		map.put(ParserUtil.PAGE, page);
+		//动态解析
+		map.put(ParserUtil.IS_DO,true);
+		//设置动态请求的模块路径
+		map.put(ParserUtil.MODEL_NAME, "mcms");
+		//解析后的内容
+		String content = "";
+		try {
+			//根据模板路径,参数生成
+			content = CmsParserUtil.generate(columnArticles.get(0).getColumnListUrl(),map, isMobileDevice(req));
+		} catch (TemplateNotFoundException e) {
+			e.printStackTrace();
+		} catch (MalformedTemplateNameException e) {
+			e.printStackTrace();
+		} catch (ParseException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		this.outString(resp, content);
+	}
+
+	/**
+	 * 动态详情页
+	 * @param id 文章编号
+	 */
+	@GetMapping("/view.do")
+	public void view(String orderby,String order,HttpServletRequest req, HttpServletResponse resp) {
+		//参数文章编号
+		ArticleEntity article = (ArticleEntity) articleBiz.getEntity(BasicUtil.getInt(ParserUtil.ID));
+		if(ObjectUtil.isNull(article)){
+			this.outJson(resp, null,false,getResString("err.empty", this.getResString("id")));
+			return;
+		}
+		if(StringUtils.isNotBlank(order)){
+			//防注入
+			if(!order.toLowerCase().equals("asc")&&!order.toLowerCase().equals("desc")){
+				this.outJson(resp, null,false,getResString("err.error", this.getResString("order")));
+				return;
+			}
+		}
+		PageBean page = new PageBean();
+		//根据文章编号查询栏目详情模版
+		ColumnEntity column = (ColumnEntity) columnBiz.getEntity(article.getBasicCategoryId());
+		//解析后的内容
+		String content = "";
+		Map map = BasicUtil.assemblyRequestMap();
+		//动态解析
+		map.put(ParserUtil.IS_DO,true);
+		//设置动态请求的模块路径
+		map.put(ParserUtil.MODEL_NAME, "mcms");
+		map.put(ParserUtil.URL, BasicUtil.getUrl());
+		map.put(ParserUtil.PAGE, page);
+		map.put(ParserUtil.ID, article.getArticleID());
+		List<ColumnArticleIdBean> articleIdList = articleBiz.queryIdsByCategoryIdForParser(column.getCategoryCategoryId(), null, null,orderby,order);
+		Map<Object, Object> contentModelMap = new HashMap<Object, Object>();
+		ContentModelEntity contentModel = null;
+		for (int artId = 0; artId < articleIdList.size();) {
+			//如果不是当前文章则跳过
+			if(articleIdList.get(artId).getArticleId() != article.getArticleID()){
+				artId++;
+				continue;
+			}
+			// 文章的栏目路径
+			String articleColumnPath = articleIdList.get(artId).getColumnPath();
+			// 文章的栏目模型编号
+			int columnContentModelId = articleIdList.get(artId).getColumnContentModelId();
+			Map<String, Object> parserParams = new HashMap<String, Object>();
+			parserParams.put(ParserUtil.COLUMN, articleIdList.get(artId));
+			// 判断当前栏目是否有自定义模型
+			if (columnContentModelId > 0) {
+				// 通过当前栏目的模型编号获取,自定义模型表名
+				if (contentModelMap.containsKey(columnContentModelId)) {
+					parserParams.put(ParserUtil.TABLE_NAME, contentModel.getCmTableName());
+				} else {
+					// 通过栏目模型编号获取自定义模型实体
+					contentModel = (ContentModelEntity) SpringUtil.getBean(IContentModelBiz.class)
+							.getEntity(columnContentModelId);
+					// 将自定义模型编号设置为key值
+					contentModelMap.put(columnContentModelId, contentModel.getCmTableName());
+					parserParams.put(ParserUtil.TABLE_NAME, contentModel.getCmTableName());
+				}
+			}
+			// 第一篇文章没有上一篇
+			if (artId > 0) {
+				ColumnArticleIdBean preCaBean = articleIdList.get(artId - 1);
+				//判断当前文档是否与上一页文章在同一栏目下,并且不能使用父栏目字符串,因为父栏目中没有所属栏目编号
+				if(articleColumnPath.contains(preCaBean.getCategoryId()+"")){
+					page.setPreId(preCaBean.getArticleId());
+				}
+			}
+			// 最后一篇文章没有下一篇
+			if (artId + 1 < articleIdList.size()) {
+				ColumnArticleIdBean nextCaBean = articleIdList.get(artId + 1);
+				//判断当前文档是否与下一页文章在同一栏目下并且不能使用父栏目字符串,因为父栏目中没有所属栏目编号
+				if(articleColumnPath.contains(nextCaBean.getCategoryId()+"")){
+					page.setNextId(nextCaBean.getArticleId());
+				}
+			}
+			break;
+		}
+		try {
+			//根据模板路径,参数生成
+			content = CmsParserUtil.generate(column.getColumnUrl(), map, isMobileDevice(req));
+		} catch (TemplateNotFoundException e) {
+			e.printStackTrace();
+		} catch (MalformedTemplateNameException e) {
+			e.printStackTrace();
+		} catch (ParseException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		this.outString(resp, content);
+	}
+}

+ 426 - 0
src/main/java/net/mingsoft/cms/action/web/SearchAction.java

@@ -0,0 +1,426 @@
+/**
+The MIT License (MIT) * Copyright (c) 2016 铭飞科技(mingsoft.net)
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package net.mingsoft.cms.action.web;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.PageUtil;
+import freemarker.core.ParseException;
+import freemarker.template.MalformedTemplateNameException;
+import freemarker.template.TemplateNotFoundException;
+import net.mingsoft.base.constant.Const;
+import net.mingsoft.basic.action.BaseAction;
+import net.mingsoft.basic.biz.ICategoryBiz;
+import net.mingsoft.basic.biz.IColumnBiz;
+import net.mingsoft.basic.biz.IModelBiz;
+import net.mingsoft.basic.entity.ColumnEntity;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.basic.util.StringUtil;
+import net.mingsoft.cms.biz.IArticleBiz;
+import net.mingsoft.cms.util.CmsParserUtil;
+import net.mingsoft.mdiy.bean.PageBean;
+import net.mingsoft.mdiy.biz.IContentModelBiz;
+import net.mingsoft.mdiy.biz.IContentModelFieldBiz;
+import net.mingsoft.mdiy.biz.ISearchBiz;
+import net.mingsoft.mdiy.entity.ContentModelEntity;
+import net.mingsoft.mdiy.entity.ContentModelFieldEntity;
+import net.mingsoft.mdiy.entity.SearchEntity;
+import net.mingsoft.mdiy.parser.TagParser;
+import net.mingsoft.mdiy.util.ParserUtil;
+
+/**
+ * 根据搜索结果动态解析模版内容
+ * @author 铭飞开源团队-Administrator  
+ * @date 2018年12月18日
+ */
+@Controller(value = "webSearchAction")
+@RequestMapping("/cms")
+public class SearchAction extends BaseAction {
+
+	/**
+	 * 搜索标签;
+	 */
+	public static final String SEARCH = "search";
+	
+	/**
+	 * 搜索的标题;
+	 */
+	public static final String BASIC_TITLE = "basic_title";
+	
+	/**
+	 * 注入文章业务层
+	 */
+	@Autowired
+	private IArticleBiz articleBiz;
+
+	/**
+	 * 注入搜索业务层
+	 */
+	@Autowired
+	private ISearchBiz searchBiz;
+
+	/**
+	 * 注入栏目业务层
+	 */
+	@Autowired
+	private IColumnBiz columnBiz;
+	
+	/**
+	 * 内容模型业务层
+	 */
+	@Autowired
+	private IContentModelBiz contentModelBiz;
+	
+	/**
+	 * 内容字段业务层
+	 */
+	@Autowired
+	private IContentModelFieldBiz fieldBiz;
+	
+
+	/**
+	 * 注入分类业务层
+	 */
+	@Autowired
+	private ICategoryBiz categoryBiz;
+
+
+	/**
+	 * 模块管理biz
+	 */
+	@Autowired
+	private IModelBiz modelBiz;
+	
+	/**
+	 * 实现前端页面的文章搜索
+	 * 
+	 * @param request
+	 * @param searchId
+	 *            搜索id
+	 * @param response
+	 */
+	@RequestMapping(value = "/{searchId}/search")
+	@ResponseBody
+	public void search(HttpServletRequest request, @PathVariable int searchId, HttpServletResponse response) {
+		SearchEntity _search = new SearchEntity();
+		_search.setAppId(BasicUtil.getAppId());
+		_search.setSearchId(searchId);
+		// 获取对应搜索模型
+		SearchEntity search = (SearchEntity) searchBiz.getEntity(_search); 
+		//判断当前搜索是否有模板文件
+		if (ObjectUtil.isNull(search)) {
+			this.outJson(response, false);
+		}
+		Map<String, Object> map = new HashMap<>();
+		// 读取请求字段
+		Map<String, String[]> field =  request.getParameterMap(); 
+		Map<String, String> basicField = getMapByProperties(net.mingsoft.mdiy.constant.Const.BASIC_FIELD);
+		// 文章字段集合
+		Map<String, Object> articleFieldName = new HashMap<String, Object>();
+		// 自定义字段集合
+		Map<String, String> diyFieldName = new HashMap<String, String>();
+		ColumnEntity column = null; // 当前栏目
+		ContentModelEntity contentModel = null; // 栏目对应模型
+		List<ContentModelFieldEntity> fieldList = new ArrayList<ContentModelFieldEntity>(); // 栏目对应字段
+		List<DiyModelMap> fieldValueList = new ArrayList<DiyModelMap>(); // 栏目对应字段的值
+		int typeId = 0;
+		String categoryIds = BasicUtil.getString("categoryId");
+		//当传递了栏目编号,但不是栏目集合
+		if(!StringUtil.isBlank(categoryIds) && !categoryIds.contains(",")){
+			typeId = Integer.parseInt(categoryIds);
+		}
+		//记录自定义模型字段名
+		List filedStr = new ArrayList<>();
+		//根据栏目确定自定义模型
+		if(typeId>0){
+			column = (ColumnEntity) columnBiz.getEntity(Integer.parseInt(typeId+""));
+			// 获取表单类型的id
+			if (column != null) {
+				contentModel = (ContentModelEntity) contentModelBiz.getEntity(column.getColumnContentModelId());
+				if (contentModel != null) {
+					fieldList = fieldBiz.queryListByCmid(contentModel.getCmId());
+					for (ContentModelFieldEntity cmField : fieldList) {
+						filedStr.add(cmField.getFieldFieldName());
+					}
+					map.put(ParserUtil.TABLE_NAME, contentModel.getCmTableName());
+				}
+			}
+			map.put(ParserUtil.COLUMN, column);
+			//设置栏目编号
+//			map.put(ParserUtil.TYPE_ID, typeId);
+		}
+		
+		// 遍历取字段集合
+		if (field != null) {
+			for (Entry<String, String[]> entry : field.entrySet()) {
+				if (entry != null) {
+					String value = entry.getValue()[0]; // 处理由get方法请求中文乱码问题
+					if (ObjectUtil.isNull(value)) {
+						continue;
+					}
+					if (request.getMethod().equals(RequestMethod.GET)) { // 如果是get方法需要将请求地址参数转吗
+						try {
+							value = new String(value.getBytes("ISO-8859-1"),Const.UTF8);
+						} catch (UnsupportedEncodingException e) {
+							e.printStackTrace();
+						}
+					}
+					// 若为文章字段,则保存至文章字段集合;否则保存至自定义字段集合
+					if (ObjectUtil.isNotNull(basicField.get(entry.getKey())) && ObjectUtil.isNotNull(value)) {
+						articleFieldName.put(entry.getKey(), value);
+					} else {
+						if (!StringUtil.isBlank(value)) {
+							diyFieldName.put(entry.getKey(), value);
+							//判断请求中的是否是自定义模型中的字段
+							if(filedStr.contains(entry.getKey())){
+								//设置自定义模型字段和值
+								DiyModelMap diyMap = new DiyModelMap();
+								diyMap.setKey(entry.getKey());
+								diyMap.setValue(value);
+								fieldValueList.add(diyMap);
+							}
+						} 
+					}
+				}
+			}
+		}
+		//添加自定义模型的字段和值
+		if(fieldValueList.size()>0){
+			map.put("diyModel", fieldValueList);
+		}
+		//组织where查询条件
+		Map whereMap = this.searchMap(articleFieldName, diyFieldName, fieldList);
+		
+		// 获取符合条件的文章总数
+		int count = articleBiz.getSearchCount(contentModel, whereMap, BasicUtil.getAppId(), categoryIds);
+		//设置分页类
+		PageBean page = new PageBean();
+		//读取模板的分页数量
+		int size = BasicUtil.getInt(ParserUtil.SIZE,10);
+		try {
+			size = TagParser.getPageSize(ParserUtil.read(search.getSearchTemplets(),false ));
+		} catch (TemplateNotFoundException e1) {
+			e1.printStackTrace();
+		} catch (MalformedTemplateNameException e1) {
+			e1.printStackTrace();
+		} catch (ParseException e1) {
+			e1.printStackTrace();
+		} catch (IOException e1) {
+			e1.printStackTrace();
+		}
+		int total = PageUtil.totalPage(count, size);
+		
+		int pageNo = BasicUtil.getInt(ParserUtil.PAGE_NO, 1);
+		if(pageNo >= total && total!=0) {
+			pageNo = total;
+		}
+ 		//获取总数
+		page.setTotal(total);
+		//设置页面显示数量
+		page.setSize(size);
+		//设置列表当前页
+		
+		page.setPageNo(pageNo);
+		
+		String str = ParserUtil.PAGE_NO+","+ParserUtil.SIZE;
+		//设置分页的统一链接
+		String url = BasicUtil.getUrl()+request.getServletPath() +"?" + BasicUtil.assemblyRequestUrlParams(str.split(","));
+		String pageNoStr = "&"+ParserUtil.SIZE+"="+size+"&"+ParserUtil.PAGE_NO+"=";
+		//下一页
+		String nextUrl = url + pageNoStr+((pageNo+1 > total)?total:pageNo+1);
+		//首页
+		String indexUrl = url + pageNoStr + 1;
+		//尾页
+		String lastUrl = url + pageNoStr + total;
+		//上一页 当前页为1时,上一页就是1
+		String preUrl = url + pageNoStr + ((pageNo==1) ? 1:pageNo-1);
+		
+		page.setIndexUrl(indexUrl);
+		page.setNextUrl(nextUrl);
+		page.setPreUrl(preUrl);
+		page.setLastUrl(lastUrl);
+		map.put(ParserUtil.URL, BasicUtil.getUrl());
+		Map<String, Object> searchMap = BasicUtil.assemblyRequestMap();
+		searchMap.put(ParserUtil.PAGE_NO, pageNo);
+		map.put(SEARCH, searchMap);
+		map.put(ParserUtil.PAGE, page);
+		//动态解析
+		map.put(ParserUtil.IS_DO,false);
+		//设置动态请求的模块路径
+		map.put(ParserUtil.MODEL_NAME, "mcms");
+		//解析后的内容
+		String content = "";
+		try {
+			//根据模板路径,参数生成
+			content = CmsParserUtil.generate(search.getSearchTemplets(),map, isMobileDevice(request));
+		} catch (TemplateNotFoundException e) {
+			e.printStackTrace();
+		} catch (MalformedTemplateNameException e) {
+			e.printStackTrace();
+		} catch (ParseException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		this.outString(response, content);
+	}
+
+	/**
+	 * 动态组织查询where条件 获取查询条件的Map key:字段名 value:List 字段的各种判断值 list[0]:是否为自定义字段
+	 * list[1]:是否为整形 list[2]:是否是等值查询 list[3]:字段的值
+	 * 
+	 * @param articleField
+	 *            文章字段
+	 * @param diyFieldName
+	 *            动态字段
+	 * @param fields
+	 *            模型对应的字段类型
+	 * @return
+	 */
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	private Map<String, List> searchMap(Map<String, Object> articleField, Map<String, String> diyFieldName,
+			List fields) {
+		Map<String, List> map = new HashMap<String, List>();
+
+		// 遍历文章中的字段
+		for (Iterator iter = articleField.keySet().iterator(); iter.hasNext();) {
+			String key = iter.next().toString();
+			String fieldValue = articleField.get(key).toString();
+			List list = new ArrayList();
+			List listValue = new ArrayList();
+			// 是否为自定义字段
+			list.add(false);
+
+			// 是否是数字类型,true:不是
+			list.add(true);
+			// 是否是模糊查询3
+			list.add(true);
+			// 字段值
+			listValue.add(articleField.get(key));
+			list.add(listValue);
+			map.put(key, list);
+		}
+
+		// 遍历字段自定义字段
+		for (Iterator iter = diyFieldName.keySet().iterator(); iter.hasNext();) {
+			String key = iter.next().toString();
+			String fieldValue = diyFieldName.get(key);
+			// 获取字段实体
+			ContentModelFieldEntity field = this.get(key, fields);
+			if (field != null) {
+				List list = new ArrayList();
+				// 是否为自定义字段0
+				list.add(0, true);
+				List listValue = new ArrayList();
+				// 字段的值
+				if (field.getFieldType() == IContentModelFieldBiz.INT || field.getFieldType() == IContentModelFieldBiz.FLOAT) {
+					// 判断是否为区间查询
+
+					if (diyFieldName.get(key).toString().indexOf("-") > 0) {
+						String[] values = fieldValue.toString().split("-");
+						// 是否是数字类型,false:是
+						list.add(false);
+						// 是否是区间比较 false:是
+						list.add(false);
+						// 字段值1
+						listValue.add(values[0]);
+						listValue.add(values[1]);
+					} else {
+						// 是否是数字类型,false:是2
+						list.add(false);
+						// 是否是区间比较 true:不是3
+						list.add(true);
+						// 字段值 1
+						listValue.add(fieldValue);
+					}
+				} else {
+					// 是否是数字类型,true:不是2
+					list.add(true);
+					list.add(false);
+					// 字段值 1
+					listValue.add(fieldValue);
+				}
+				list.add(listValue);
+				map.put(key, list);
+			}
+		}
+		return map;
+	}
+
+	/**
+	 * 根据字段名称获取字段类型
+	 * 
+	 * @param columnName
+	 *            字段名称
+	 * @return 字段实体
+	 */
+	private ContentModelFieldEntity get(String columnName, List<ContentModelFieldEntity> fields) {
+		if (fields == null) {
+			return null;
+		}
+		for (ContentModelFieldEntity field : fields) {
+			if (field.getFieldFieldName().equals(columnName)) {
+				return field;
+			}
+		}
+		return null;
+	}
+	/**
+	 * 存储自定义模型字段和接口参数
+	 * @author 铭飞开源团队
+	 * @date 2019年3月5日
+	 */
+	public class DiyModelMap {
+		String key;
+		Object value;
+		public String getKey() {
+			return key;
+		}
+		public void setKey(String key) {
+			this.key = key;
+		}
+		public Object getValue() {
+			return value;
+		}
+		public void setValue(Object value) {
+			this.value = value;
+		}
+	}
+}

+ 45 - 0
src/main/java/net/mingsoft/cms/bean/ColumnArticleIdBean.java

@@ -0,0 +1,45 @@
+/**
+The MIT License (MIT) * Copyright (c) 2016 铭飞科技(mingsoft.net)
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package net.mingsoft.cms.bean;
+
+import net.mingsoft.basic.entity.ColumnEntity;
+
+/**
+ * 文章解析生成
+ * @author 铭飞开源团队  
+ * @date 2018年12月13日
+ */
+public class ColumnArticleIdBean extends ColumnEntity{
+	/**
+	 * 文章编号
+	 */
+	private int articleId;
+
+	public int getArticleId() {
+		return articleId;
+	}
+
+	public void setArticleId(int articleId) {
+		this.articleId = articleId;
+	}
+	
+}

+ 191 - 0
src/main/java/net/mingsoft/cms/biz/IArticleBiz.java

@@ -0,0 +1,191 @@
+/**
+ The MIT License (MIT) * Copyright (c) 2016 铭飞科技(mingsoft.net)
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package net.mingsoft.cms.biz;
+
+import java.util.List;
+import java.util.Map;
+
+import net.mingsoft.basic.biz.IBasicBiz;
+import net.mingsoft.cms.bean.ColumnArticleIdBean;
+import net.mingsoft.cms.entity.ArticleEntity;
+import net.mingsoft.mdiy.entity.ContentModelEntity;
+
+
+/**
+ *
+ * @ClassName:  IArticleBiz
+ * @Description:TODO(文章管理业务处理层 || 继承IBasicBiz业务处理层)   
+ * @author: 铭飞开发团队
+ * @date:   2018年1月31日 下午2:53:32   
+ *
+ * @Copyright: 2018 www.mingsoft.net Inc. All rights reserved.
+ */
+public interface IArticleBiz extends IBasicBiz {
+
+	/**
+	 * @para webId 网站编号
+	 * @param basicCategoryId
+	 *            栏目编号
+	 * @param flag
+	 *            文章属性
+	 * @param noFlag
+	 *            文章不存在的属性
+	 * @param article
+	 *            文件实体
+	 * @return
+	 */
+	@Deprecated
+	int count(int webId, int[] basicCategoryId, String flag, String noFlag, ArticleEntity article);
+
+
+	/**
+	 * 通过分类id获取文章内容
+	 *
+	 * @param categoryId
+	 *            分类编号
+	 * @return
+	 */
+	@Deprecated
+	public ArticleEntity getByCategoryId(int categoryId);
+
+	/**
+	 * 通过视图表来查询文章总数
+	 *
+	 * @param basicId
+	 *            文章编号
+	 */
+	public ArticleEntity getById(int basicId);
+
+
+	/**
+	 * 查找basicId下一篇文章
+	 *
+	 * @param appId
+	 *            应用编号
+	 * @param basicId
+	 *            文章编号
+	 * @return
+	 */
+	@Deprecated
+	public ArticleEntity getNext(int appId, int basicId, Integer categoryId);
+
+	/**
+	 * 查找basicId上一篇文章
+	 *
+	 * @param appId
+	 *            应用编号
+	 * @param basicId
+	 *            文章编号
+	 * @return
+	 */
+	@Deprecated
+	public ArticleEntity getPrevious(int appId, int basicId, Integer categoryId);
+
+	/**
+	 * 高级查询接口,主要提供给有自定义模型的栏目,返回總數
+	 *
+	 * @param contentModel
+	 *            自定义模型
+	 * @param whereMap
+	 *            條件
+	 * @param appId
+	 *            appId 應用編號
+	 * @param ids
+	 *            子类id
+	 * @return 记录数量
+	 * @see IArticleBiz.count
+	 */
+	public int getSearchCount(ContentModelEntity contentModel, Map whereMap, int appId, String ids);
+
+	/**
+	 * 文章查询
+	 *
+	 * @para webId 网站编号
+	 * @param basicCategoryIds
+	 *            栏目编号集合
+	 * @param flag
+	 *            文章属性
+	 * @param noFlag
+	 *            文章不存在的属性
+	 * @param orderBy
+	 *            排序字段
+	 * @param order
+	 *            true 升序 false 降序 排序方式
+	 * @param beginTime 开始时间
+	 * @param endTime 结束时间
+	 * @param article
+	 *            文章实体,便于扩展查询
+	 * @return 文章集合
+	 */
+	List<ArticleEntity> query(int webId, int[] basicCategoryIds, String flag, String noFlag, String orderBy,
+							  boolean order, String beginTime,String endTime, ArticleEntity article);
+
+	/**
+	 * 查询文章编号集合
+	 * @param categoryId 栏目编号
+	 * @param beginTime 开始时间
+	 * @param endTime 结束时间
+	 * @return
+	 */
+	public List<ColumnArticleIdBean> queryIdsByCategoryIdForParser(int categoryId, String beginTime,String endTime);
+	/**
+	 * 查询文章编号集合
+	 * @param categoryId 栏目编号
+	 * @param beginTime 开始时间
+	 * @param endTime 结束时间
+	 * @param orderBy 排序字段
+	 * @param order 排序方式
+	 * @return
+	 */
+	public List<ColumnArticleIdBean> queryIdsByCategoryIdForParser(int categoryId, String beginTime,String endTime,String orderBy,String order);
+	/**
+	 * 根据页面栏目的id获取与其绑定的文章实体
+	 *
+	 * @param basicCategoryId
+	 * @return 文章实体
+	 */
+	@Deprecated
+	public List<ArticleEntity> queryListByColumnId(int basicCategoryId);
+
+
+
+
+	/**
+	 * 高级查询接口,主要提供给有自定义模型的栏目,
+	 *
+	 * @param conntentModel
+	 *            自定义模型
+	 * @param whereMap
+	 *            條件
+	 * @param page
+	 *            分頁
+	 * @param appId
+	 *            應用編號
+	 * @param ids
+	 *            子类id
+	 * @return 记录集合
+	 */
+	@Deprecated
+	public List<ArticleEntity> queryListForSearch(ContentModelEntity conntentModel, Map whereMap,
+												  int appId, List ids, Map orders);
+
+}

+ 222 - 0
src/main/java/net/mingsoft/cms/biz/impl/ArticleBizImpl.java

@@ -0,0 +1,222 @@
+/**
+ The MIT License (MIT) * Copyright (c) 2016 铭飞科技(mingsoft.net)
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package net.mingsoft.cms.biz.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import com.github.pagehelper.PageHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import net.mingsoft.base.dao.IBaseDao;
+import net.mingsoft.basic.biz.ICategoryBiz;
+import net.mingsoft.basic.biz.IColumnBiz;
+import net.mingsoft.basic.biz.IModelBiz;
+import net.mingsoft.basic.biz.impl.BasicBizImpl;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.cms.bean.ColumnArticleIdBean;
+import net.mingsoft.cms.biz.IArticleBiz;
+import net.mingsoft.cms.dao.IArticleDao;
+import net.mingsoft.cms.entity.ArticleEntity;
+import net.mingsoft.mdiy.biz.IContentModelBiz;
+import net.mingsoft.mdiy.entity.ContentModelEntity;
+
+/**
+ *
+ * @ClassName:  ArticleBizImpl
+ * @Description:TODO(文章管理业务层实现类 || 继承BasicBizImpl || 实现IArticleBiz)
+ * @author: 铭飞开发团队
+ * @date:   2018年1月31日 下午2:53:53
+ *
+ * @Copyright: 2018 www.mingsoft.net Inc. All rights reserved.
+ */
+@Service("ArticleBizImpl")
+public class ArticleBizImpl extends BasicBizImpl implements IArticleBiz {
+
+
+	/**
+	 * 文章持久化处理
+	 */
+	private IArticleDao articleDao;
+
+
+
+	/**
+	 * 栏目业务处理
+	 */
+	@Autowired
+	private ICategoryBiz categoryBiz;
+
+	/**
+	 * 自定类型义业务处理
+	 */
+	@Autowired
+	private IColumnBiz columnBiz;
+
+	/**
+	 * 自定义模型
+	 */
+	@Autowired
+	private IContentModelBiz contentModelBiz;
+
+	/**
+	 * 模块管理业务层
+	 */
+	@Autowired
+	private IModelBiz modelBiz;
+
+	@Override
+	@Deprecated
+	public int count(int webId, int[] basicCategoryId, String flag, String noFlag,ArticleEntity article) {
+		return articleDao.count(webId, basicCategoryId, flag, noFlag,article);
+	}
+
+
+	/**
+	 * 获取Article的持久化层
+	 *
+	 * @return 返回持Article的久化对象
+	 */
+	public IArticleDao getArticleDao() {
+		return articleDao;
+	}
+
+	@Override
+	@Deprecated
+	public ArticleEntity getByCategoryId(int categoryId) {
+		// TODO Auto-generated method stub
+		List list = articleDao.getByCategoryId(categoryId);
+		if (list != null && list.size() > 0) {
+			return (ArticleEntity) list.get(0);
+		}
+		return null;
+	}
+
+	@Override
+	public ArticleEntity getById(int basicId) {
+		// TODO Auto-generated method stub
+		ArticleEntity article = (ArticleEntity) articleDao.getEntity(basicId);
+		String contentModelTableName = null;
+		int ccmi = article.getColumn().getColumnContentModelId(); // 内容模型编号
+		if (ccmi > 0) {
+			ContentModelEntity contentModel = (ContentModelEntity) contentModelBiz.getEntity(ccmi);
+			contentModelTableName = contentModel.getCmTableName();
+		}
+		List temp = articleDao.getById(basicId, contentModelTableName);
+		if (temp != null && temp.size() > 0) {
+			return (ArticleEntity) temp.get(0);
+		}
+		return null;
+	}
+
+
+
+	/**
+	 * 获取IBaseDao的持久化层
+	 *
+	 * @return 返回持articleDao的久化对象
+	 */
+	@Override
+	protected IBaseDao getDao() {
+		// TODO Auto-generated method stub
+		return articleDao;
+	}
+
+	@Override
+	@Deprecated
+	public ArticleEntity getNext(int appId, int basicId,Integer categoryId) {
+		// TODO Auto-generated method stub
+		return articleDao.getNextOrPrevious(appId, basicId, true,categoryId);
+	}
+
+	@Override
+	@Deprecated
+	public ArticleEntity getPrevious(int appId, int basicId,Integer categoryId) {
+		// TODO Auto-generated method stub
+		return articleDao.getNextOrPrevious(appId, basicId, false,categoryId);
+	}
+	@Override
+	public int getSearchCount(ContentModelEntity contentModel,Map wherMap, int websiteId,String  ids) {
+		if (contentModel!=null) {
+			return articleDao.getSearchCount(contentModel.getCmTableName(),wherMap, websiteId,ids);
+		}
+		return articleDao.getSearchCount(null,wherMap, websiteId,ids);
+	}
+
+	@Override
+	public List<ArticleEntity> query(int webId, int[] basicCategoryIds, String flag, String noFlag, String orderBy,
+									 boolean order,String beginTime,String endTime, ArticleEntity article) {
+		// TODO Auto-generated method stub
+		if(article == null) {
+			article = new ArticleEntity();
+		}
+		return articleDao.query(webId, basicCategoryIds, flag, noFlag, orderBy, order, beginTime, endTime, article);
+	}
+
+	/**
+	 * 根据页面栏目的id获取与其绑定的文章实体
+	 *
+	 * @param basicCategoryId
+	 * @return 文章实体
+	 */
+	@Override
+	@Deprecated
+	public List<ArticleEntity> queryListByColumnId(int basicCategoryId) {
+		// TODO Auto-generated method stub
+		return articleDao.queryListByColumnId(basicCategoryId);
+	}
+
+
+	@Deprecated
+	public List<ArticleEntity> queryListForSearch(ContentModelEntity conntentModel, Map whereMap,  int websiteId,List ids,Map orders) {
+		List<ArticleEntity> articleList = new ArrayList<ArticleEntity>();
+		String tableName = null;
+		if (conntentModel!=null) {
+			tableName = conntentModel.getCmTableName();
+		}
+		// 查找所有符合条件的文章实体
+		articleList = articleDao.queryListForSearch(tableName, whereMap, websiteId,ids,orders);
+		return articleList;
+	}
+
+	/**
+	 * 设置Article的持久化层
+	 *
+	 * @param articleDao
+	 */
+	@Autowired
+	public void setArticleDao(IArticleDao articleDao) {
+		this.articleDao = articleDao;
+	}
+
+
+	@Override
+	public List<ColumnArticleIdBean> queryIdsByCategoryIdForParser(int categoryId, String beginTime,String endTime) {
+		return this.articleDao.queryIdsByCategoryIdForParser(categoryId,BasicUtil.getAppId(), beginTime, endTime,null,null);
+	}
+	@Override
+	public List<ColumnArticleIdBean> queryIdsByCategoryIdForParser(int categoryId, String beginTime,String endTime,String orderBy,String order) {
+		return this.articleDao.queryIdsByCategoryIdForParser(categoryId,BasicUtil.getAppId(), beginTime, endTime,orderBy,order);
+	}
+}

+ 14 - 0
src/main/java/net/mingsoft/cms/constant/Const.java

@@ -0,0 +1,14 @@
+package net.mingsoft.cms.constant;
+
+import java.util.ResourceBundle;
+
+/**
+ * @Author: 铭飞开源团队--huise
+ * @Date: 2019/8/9 20:51
+ */
+public class Const {
+    /**
+     * 资源文件
+     */
+    public final static ResourceBundle RESOURCES = ResourceBundle.getBundle("net.mingsoft.cms.resources.resources");
+}

+ 115 - 0
src/main/java/net/mingsoft/cms/constant/ModelCode.java

@@ -0,0 +1,115 @@
+/**
+The MIT License (MIT) * Copyright (c) 2016 铭飞科技(mingsoft.net)
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package net.mingsoft.cms.constant;
+
+import net.mingsoft.base.constant.e.BaseEnum;
+
+public enum ModelCode implements BaseEnum{
+	/**
+	 * 内容:栏目模块编号
+	 */
+	CMS_COLUMN("02990000"),
+
+	/**
+	 * 内容:文章模块编号
+	 */
+	CMS_ARTICLE("02980100"),
+	/**
+	 * 内容:文章列表
+	 */
+	CMS_ARTICLE_BASIC("02980000"),
+	/**
+	 * 内容:自定义搜索
+	 */
+	CMS_SEARCH("02050000"),
+
+	/**
+	 * 内容:自定义模型
+	 */
+	CMS_CONTENT_MODEL("02060000"),
+
+	/**
+	 * 内容:一键更新
+	 */
+	CMS_GENERATE_ALL("02070100"),
+
+	/**
+	 * 内容:更新主页
+	 */
+	CMS_GENERATE_INDEX("02070200"),
+
+	/**
+	 * 内容:更新文档
+	 */
+	CMS_GENERATE_ARTICLE("02070300"),
+
+	/**
+	 * 内容: 更新栏目
+	 */
+	CMS_GENERATE_COLUMN("02070400"),
+
+	/**
+	 * 内容:模版
+	 */
+	CMS_TEMPLETSKIN("02080000"),
+	
+	
+	
+	/**
+	 * 内容:织梦数据导入
+	 */
+	COM_DEDE_DATA_IMPORT("02090100"),
+	
+	/**
+	 * 内容:栏目属性管理模块
+	 */
+	CMS_COLUMN_TYPE("02090200");
+	/**
+	 * 设置modelCode的常量
+	 * @param code 常量
+	 */
+	ModelCode(String code) {
+		this.code = code;
+	}
+
+	private String code;
+
+	/**
+	 * 返回该modelCode常量的字符串表示
+	 * @return 字符串
+	 */
+	@Override
+	public String toString() {
+		// TODO Auto-generated method stub
+		return code;
+	}
+
+	/**
+	 * 返回该modelCode常量的整型表示
+	 * @return 整型
+	 */
+	public int toInt() {
+		// TODO Auto-generated method stub
+		return Integer.parseInt(code);
+	}
+
+}

+ 59 - 0
src/main/java/net/mingsoft/cms/constant/e/ColumnTypeEnum.java

@@ -0,0 +1,59 @@
+/**
+The MIT License (MIT) * Copyright (c) 2016 铭飞科技(mingsoft.net)
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package net.mingsoft.cms.constant.e;
+
+import net.mingsoft.base.constant.e.BaseEnum;
+
+/**
+ * 
+ * @ClassName:  ColumnTypeEnum   
+ * @Description:TODO(文章栏目分类类型)   
+ * @author: 铭飞开发团队
+ * @date:   2018年1月31日 下午2:55:18   
+ *     
+ * @Copyright: 2018 www.mingsoft.net Inc. All rights reserved.
+ */
+public enum ColumnTypeEnum implements BaseEnum {
+	/**
+	 * 列表
+	 */
+	COLUMN_TYPE_LIST(1),
+	/**
+	 * 单页
+	 */
+	COLUMN_TYPE_COVER(2),
+	/**
+	 * 跳转地址
+	 */
+	COLUMN_TYPE_URL(3);
+	ColumnTypeEnum(Object code) {
+		this.code = code;
+	}
+	
+	private Object code;
+	@Override
+	public int toInt() {
+		// TODO Auto-generated method stub
+		return Integer.valueOf(code+"");
+	}
+	
+}

+ 169 - 0
src/main/java/net/mingsoft/cms/dao/IArticleDao.java

@@ -0,0 +1,169 @@
+/**
+ The MIT License (MIT) * Copyright (c) 2016 铭飞科技(mingsoft.net)
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package net.mingsoft.cms.dao;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ibatis.annotations.Param;
+
+import net.mingsoft.cms.bean.ColumnArticleIdBean;
+import net.mingsoft.cms.entity.ArticleEntity;
+
+import net.mingsoft.base.dao.IBaseDao;
+
+
+/**
+ *
+ * @ClassName:  IArticleDao
+ * @Description:TODO(文章管理持久化层 || 继承IBaseDao持久化层)   
+ * @author: 铭飞开发团队
+ * @date:   2018年1月31日 下午2:55:33   
+ *
+ * @Copyright: 2018 www.mingsoft.net Inc. All rights reserved.
+ */
+public interface IArticleDao extends IBaseDao {
+
+	/**
+	 * @para webId 网站编号
+	 * @param basicCategoryIds
+	 *            栏目编号集合
+	 * @param flag
+	 *            文章属性
+	 * @param noFlag
+	 *            文章不存在的属性
+	 * @param article
+	 *            文章实体,便于扩展查询
+	 * @return 文章总数
+	 */
+	@Deprecated
+	int count(@Param("webId") int webId, @Param("basicCategoryIds") int[] basicCategoryIds, @Param("flag") String flag,
+			  @Param("noFlag") String noFlag, @Param("article") ArticleEntity article);
+
+	/**
+	 * 通过分类id获取文章内容
+	 *
+	 * @param categoryId
+	 *            分类编号
+	 * @return 文章集合
+	 */
+	@Deprecated
+	List getByCategoryId(@Param("categoryId") int categoryId);
+
+	/**
+	 * 通过视图表来查询文章总数
+	 *
+	 * @param basicId
+	 *            文章编号
+	 * @param contentModelTableName
+	 *            对应模块表名称
+	 */
+	List getById(@Param("basicId") int basicId, @Param("contentModelTableName") String contentModelTableName);
+
+	/**
+	 * 查找basicId上一篇文章
+	 *
+	 * @param appId
+	 *            应用编号
+	 * @param basicId
+	 *            文章编号
+	 * @param flag
+	 *            true:上一条 false:下一条
+	 * @return
+	 */
+	ArticleEntity getNextOrPrevious(@Param("appId") int appId, @Param("basicId") int basicId,
+									@Param("flag") boolean flag, @Param("categoryId") Integer categoryId);
+
+	/**
+	 * 根据查询文章实体总数
+	 *
+	 * @param tableName
+	 *            :自定义生成的表名
+	 * @param map
+	 *            key:字段名 value:List 字段的各种判断值 list[0]:是否为自定义字段 list[1]:是否为整形
+	 *            list[2]:是否是等值查询 list[3]:字段的值
+	 * @return 文章实体总数
+	 */
+	int getSearchCount(@Param("tableName") String tableName, @Param("map") Map<String, List> map,
+					   @Param("websiteId") int websiteId, @Param("ids") String ids);
+
+	/**
+	 * 文章查询
+	 *
+	 * @para webId 网站编号
+	 * @param basicCategoryIds
+	 *            栏目编号集合
+	 * @param flag
+	 *            文章属性
+	 * @param noFlag
+	 *            文章不存在的属性
+	 * @param orderBy
+	 *            排序字段
+	 * @param order
+	 *            true 升序 false 降序 排序方式
+	 * @param article
+	 *            文章实体,便于扩展查询
+	 * @param beginTime 开始时间    
+	 * @param endTime 结束时间 
+	 * @return 文章集合
+	 */
+	List<ArticleEntity> query(@Param("webId") int webId, @Param("basicCategoryIds") int[] basicCategoryIds,
+							  @Param("flag") String flag, @Param("noFlag") String noFlag, @Param("orderBy") String orderBy,
+							  @Param("order") boolean order, @Param("beginTime") String beginTime,@Param("endTime") String endTime,
+							  @Param("article") ArticleEntity article);
+
+	/**
+	 * 根据页面栏目的id获取与其绑定的文章实体
+	 *
+	 * @param basicCategoryId
+	 * @return 文章实体
+	 */
+	@Deprecated
+	List<ArticleEntity> queryListByColumnId(@Param("basicCategoryId") int basicCategoryId);
+
+	/**
+	 * 根据查询文章实体
+	 *
+	 * @param tableName
+	 *            :自定义生成的表名
+	 * @param map
+	 *            获取查询条件的Map key:字段名 value:List 字段的各种判断值 list[0]:是否为自定义字段
+	 *            list[1]:是否为整形 list[2]:是否是等值查询 list[3]:字段的值
+	 * @return 文章实体
+	 */
+	@Deprecated
+	List<ArticleEntity> queryListForSearch(@Param("tableName") String tableName, @Param("map") Map<String, List> map,
+										   @Param("websiteId") int websiteId, @Param("ids") List ids,
+										   @Param("sortMap") Map sortMap);
+
+	/**
+	 * 查询文章编号集合
+	 * @param categoryId 栏目编号
+	 * @param appId 站点编号
+	 * @param beginTime 开始时间
+	 * @param endTime 结束时间
+	 * @return
+	 */
+	public List<ColumnArticleIdBean> queryIdsByCategoryIdForParser(@Param("categoryId")int categoryId,@Param("appId")int appId , @Param("beginTime") String beginTime,@Param("endTime") String endTime,@Param("orderBy")String orderBy,@Param("order")String order);
+
+
+}

+ 624 - 0
src/main/java/net/mingsoft/cms/dao/IArticleDao.xml

@@ -0,0 +1,624 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<!-- 文章管理持久化层配置文件 -->
+<mapper namespace="net.mingsoft.cms.dao.IArticleDao">
+	<!-- 表栏目名 开始 -->
+	<sql id="column_list">
+		a.ARTICLE_BASICID,a.ARTICLE_CONTENT,a.ARTICLE_AUTHOR,a.ARTICLE_TYPE,a.ARTICLE_SOURCE,a.ARTICLE_URL,a.ARTICLE_KEYWORD,a.ARTICLE_FREEORDER,a.ARTICLE_WEBID,
+		b.BASIC_ID,b.BASIC_TITLE,b.BASIC_DESCRIPTION,b.BASIC_THUMBNAILS,b.BASIC_HIT,b.BASIC_DISPLAY,b.BASIC_DATETIME,b.BASIC_UPDATETIME,b.BASIC_PEOPLEID,b.BASIC_CATEGORYID,b.BASIC_SORT
+	</sql>
+	<!-- 表栏目名 结束 -->
+
+
+	<!-- 获取表字段 开始 -->
+	<resultMap type="net.mingsoft.cms.entity.ArticleEntity" id="resultMap">
+		<id column="ARTICLE_BASICID" property="articleID" />				<!-- 与cms_article表绑定id -->
+		<result column="ARTICLE_CONTENT" property="articleContent" />	<!-- 文章内容 -->
+		<result column="ARTICLE_AUTHOR" property="articleAuthor" />		<!-- 文章作者 -->
+		<result column="ARTICLE_TYPE" property="articleType" />			<!-- 文章属性 -->
+		<result column="ARTICLE_SOURCE" property="articleSource" />		<!-- 文章来源 -->
+		<result column="ARTICLE_URL" property="articleUrl" />			<!-- 文章跳转链接地址 -->
+		<result column="ARTICLE_KEYWORD" property="articleKeyword" />	<!-- 文章关键字 -->
+		<result column="ARTICLE_FREEORDER" property="articleFreeOrder" /><!-- 
+			文章自定义显示顺序 -->
+		<result column="ARTICLE_WEBID" property="articleWebId" />				<!-- 站点id -->
+		<result column="BASIC_ID" property="basicId" />					<!-- 与表basic绑定 自增长ID -->
+		<result column="BASIC_TITLE" property="basicTitle" />			<!-- 文章标题 -->
+		<result column="BASIC_DESCRIPTION" property="basicDescription" /><!-- 
+			文章描述 -->
+		<result column="BASIC_THUMBNAILS" property="basicThumbnails" />	<!-- 文章缩略图 -->
+		<result column="BASIC_HIT" property="basicHit" />				<!-- 文章点击次数 -->
+		<result column="BASIC_DATETIME" property="basicDateTime" />		<!-- 文章发布时间 -->
+		<result column="BASIC_UPDATETIME" property="basicUpdateTime" />	<!-- 文章更新时间 -->
+		<result column="BASIC_PEOPLEID" property="basicPeopleId" />		<!-- 文章发布者id -->
+		<result column="BASIC_CATEGORYID" property="basicCategoryId" />	<!-- 文章所属主栏目id -->
+		<result column="BASIC_SORT" property="basicSort" />
+		<result column="BASIC_DISPLAY" property="basicDisplay" />
+		<!-- 一对一关联栏目 -->
+		<association property="column" column="COLUMN_CATEGORY_ID"
+					 javaType="net.mingsoft.basic.entity.ColumnEntity">
+			<result property="columnPath" column="column_path" />
+			<result property="categoryTitle" column="category_title" />
+			<result property="categoryId" column="category_id" />
+			<result property="columnContentModelId" column="COLUMN_CM_ID" />
+			<result property="columnType" column="COLUMN_TYPE" />
+		</association>
+	</resultMap>
+	<!-- 获取表字段 结束 -->
+	<!-- 通过视图查询返回结果集 开始 -->
+	<resultMap type="net.mingsoft.cms.bean.ColumnArticleIdBean" id="resultMapBean">
+		<result column="ARTICLE_BASICID" property="articleId" />
+		<result column="column_path" property="columnPath"/>
+		<result column="column_url" property="columnUrl" />
+		<result column="column_listurl" property="columnListUrl" />
+		<result column="category_title" property="categoryTitle" />
+		<result column="category_id" property="categoryId" />
+		<result column="COLUMN_CM_ID" property="columnContentModelId" />
+		<result column="category_categoryid" property="categoryCategoryId" /><!--关联表category的父类别ID category_categoryid字段 -->
+		<result column="category_modelId" property="categoryModelId" /><!--关联表category的所属模块ID category_modelid字段 -->
+		<result column="COLUMN_TYPE" property="columnType" />
+		<result column="category_parent_id" property="categoryParentId" /><!--关联表category的字典对应编号 -->
+	</resultMap>
+	<!-- 通过视图查询返回结果集 结束 -->
+	<!-- 通过视图查询返回结果集 开始 -->
+	<resultMap type="net.mingsoft.cms.entity.ArticleEntity" id="viewResultMap">
+		<id column="ARTICLE_BASICID" property="articleID" />				<!-- 与cms_article表绑定id -->
+		<result column="ARTICLE_CONTENT" property="articleContent" />	<!-- 文章内容 -->
+		<result column="ARTICLE_AUTHOR" property="articleAuthor" />		<!-- 文章作者 -->
+		<result column="ARTICLE_TYPE" property="articleType" />			<!-- 文章属性 -->
+		<result column="ARTICLE_SOURCE" property="articleSource" />		<!-- 文章来源 -->
+		<result column="ARTICLE_URL" property="articleUrl" />			<!-- 文章跳转链接地址 -->
+		<result column="ARTICLE_KEYWORD" property="articleKeyword" />	<!-- 文章关键字 -->
+		<result column="ARTICLE_FREEORDER" property="articleFreeOrder" /><!--
+			文章自定义显示顺序 -->
+		<result column="ARTICLE_WEBID" property="articleWebId" />				<!-- 站点id -->
+
+		<result column="BASIC_ID" property="basicId" />					<!-- 与表basic绑定 自增长ID -->
+		<result column="BASIC_TITLE" property="basicTitle" />			<!-- 文章标题 -->
+		<result column="BASIC_DESCRIPTION" property="basicDescription" /><!--
+			文章描述 -->
+		<result column="BASIC_THUMBNAILS" property="basicThumbnails" />	<!-- 文章缩略图 -->
+		<result column="BASIC_HIT" property="basicHit" />				<!-- 文章点击次数 -->
+		<result column="BASIC_DATETIME" property="basicDateTime" />		<!-- 文章发布时间 -->
+		<result column="BASIC_UPDATETIME" property="basicUpdateTime" />	<!-- 文章更新时间 -->
+		<result column="BASIC_CATEGORYID" property="basicCategoryId" />	<!-- 文章所属主栏目id -->
+		<result column="BASIC_SORT" property="basicSort" />
+		<result column="BASIC_DISPLAY" property="basicDisplay" />
+		<!-- 一对一关联栏目 -->
+		<association property="column"
+					 javaType="net.mingsoft.basic.entity.ColumnEntity">
+			<result property="columnPath" column="column_path" />
+			<result property="categoryTitle" column="category_title" />
+			<result property="categoryId" column="category_id" />
+			<result property="columnContentModelId" column="COLUMN_CM_ID" />
+			<result property="columnType" column="COLUMN_TYPE" />
+		</association>
+	</resultMap>
+	<!-- 通过视图查询返回结果集 结束 -->
+
+	<!-- 文章bean返回数据列表 开始 -->
+	<sql id="bean_column_list">
+		BASIC_ID,ARTICLE_AUTHOR,ARTICLE_TYPE,ARTICLE_SOURCE,ARTICLE_URL,ARTICLE_KEYWORD,ARTICLE_FREEORDER,
+		BASIC_DISPLAY,BASIC_TITLE,BASIC_DESCRIPTION,BASIC_THUMBNAILS,BASIC_HIT,BASIC_DATETIME,BASIC_UPDATETIME,BASIC_PEOPLEID,BASIC_CATEGORYID,BASIC_SORT
+	</sql>
+	<!-- 表栏目名结束 -->
+
+	<!-- 文章基础数据返回数据列表 开始 -->
+	<sql id="basic_data_list">
+		BASIC_DISPLAY,BASIC_ID,BASIC_CATEGORYID,BASIC_TITLE,BASIC_DESCRIPTION,BASIC_THUMBNAILS,BASIC_HIT,BASIC_DATETIME,BASIC_UPDATETIME,BASIC_PEOPLEID,BASIC_SORT,
+		ARTICLE_BASICID,ARTICLE_AUTHOR,ARTICLE_CONTENT,ARTICLE_TYPE,ARTICLE_SOURCE,ARTICLE_URL,ARTICLE_KEYWORD,ARTICLE_FREEORDER,ARTICLE_WEBID,
+		COLUMN_KEYWORD,COLUMN_DESCRIP,COLUMN_TYPE,COLUMN_URL,COLUMN_LISTURL,COLUMN_PATH,COLUMN_CM_ID,COLUMN_CATEGORY_ID,
+		CATEGORY_TITLE,CATEGORY_APPID,CATEGORY_ID
+	</sql>
+	<!-- 文章基础数据返回数据列表结束 -->
+
+	<!-- 添加文章信息 开始 -->
+	<insert id="saveEntity" parameterType="net.mingsoft.base.entity.BaseEntity">
+		insert into cms_article
+		<!-- 添加表字段 -->
+		<trim prefix="(" suffix=")" suffixOverrides=",">
+			<if test="basicId != null">ARTICLE_BASICID,</if>
+			<if test="articleContent != null">ARTICLE_CONTENT,</if>
+			<if test="articleAuthor != null">ARTICLE_AUTHOR,</if>
+			<if test="articleType != null">ARTICLE_TYPE,</if>
+			<if test="articleSource != null">ARTICLE_SOURCE,</if>
+			<if test="articleUrl != null">ARTICLE_URL,</if>
+			<if test="articleKeyword != null">ARTICLE_KEYWORD,</if>
+			<if test="articleFreeOrder != null">ARTICLE_FREEORDER,</if>
+			<if test="articleWebId != null">ARTICLE_WEBID,</if>
+		</trim>
+		<!-- 注入控制层字段 -->
+		<trim prefix="values (" suffix=")" suffixOverrides=",">
+			<if test="basicId != null">#{basicId},</if>
+			<if test="articleContent != null">#{articleContent},</if>
+			<if test="articleAuthor != null">#{articleAuthor},</if>
+			<if test="articleType != null">#{articleType},</if>
+			<if test="articleSource != null">#{articleSource},</if>
+			<if test="articleUrl != null">#{articleUrl},</if>
+			<if test="articleKeyword != null">#{articleKeyword},</if>
+			<if test="articleFreeOrder != null">#{articleFreeOrder},</if>
+			<if test="articleWebId != null">#{articleWebId},</if>
+		</trim>
+	</insert>
+	<!-- 添加文章信息 结束 -->
+
+	<!-- 删除文章管理的信息 开始 -->
+	<delete id="deleteEntity" parameterType="int">
+		DELETE b from basic b WHERE b.basic_id=#{basicId};
+		DELETE c from cms_article c WHERE c.article_basicid=#{basicId}
+	</delete>
+	<!-- 删除文章管理的信息 结束 -->
+
+	<!-- 更新文章管理的信息 开始 -->
+	<update id="updateEntity" parameterType="net.mingsoft.base.entity.BaseEntity">
+		update cms_article
+		<set>
+			<if test="articleContent != null">ARTICLE_CONTENT=#{articleContent},</if>
+			<if test="articleAuthor != null">ARTICLE_AUTHOR=#{articleAuthor},</if>
+			<if test="articleType != null">ARTICLE_TYPE=#{articleType},</if>
+			<if test="articleSource != null">ARTICLE_SOURCE=#{articleSource},</if>
+			<if test="articleUrl != null">ARTICLE_URL=#{articleUrl},</if>
+			<if test="articleKeyword != null">ARTICLE_KEYWORD=#{articleKeyword},</if>
+			<if test="articleFreeOrder != null">ARTICLE_FREEORDER=#{articleFreeOrder},</if>
+			<if test="articleWebId != null">ARTICLE_WEBID=#{articleWebId},</if>
+		</set>
+		where ARTICLE_BASICID = #{basicId}
+	</update>
+	<!-- 更新文章管理的信息 开始 -->
+
+
+	<!-- 查找文章管理的信息 开始 -->
+	<select id="getEntity" resultMap="resultMap" parameterType="int">
+		select
+		<include refid="column_list" />
+		,c.CATEGORY_TITLE,cl.column_path,cl.column_type,c.CATEGORY_id,cl.COLUMN_CM_ID
+		FROM
+		basic b
+		LEFT JOIN
+		category c ON b.BASIC_CATEGORYID = c.CATEGORY_ID
+		LEFT JOIN basic_column
+		cl ON c.CATEGORY_ID = cl.COLUMN_CATEGORY_ID
+		LEFT
+		JOIN cms_article a ON
+		a.ARTICLE_BASICID = b.BASIC_ID
+
+		<!-- 查询与关联表id相同的信息 -->
+
+		where a.ARTICLE_BASICID=#{basicId}
+	</select>
+	<!-- 查找文章管理的信息 结束 -->
+
+	<!-- 标题字段query -->
+	<sql id="queryWhereBasicTitle" databaseId="mysql">
+		CONCAT('%',#{article.basicTitle},'%')
+	</sql>
+	<sql id="queryWhereBasicTitle" databaseId="oracle">
+		'%'||#{ article.basicTitle}||'%'
+	</sql>
+	<sql id="queryWhereBasicTitle" databaseId="sqlServer">
+		'%'+#{ article.basicTitle}+'%'
+	</sql>
+	<!-- flag字段 -->
+	<sql id="queryWhereFlag" databaseId="mysql">
+		CONCAT('%',#{flag},'%')
+	</sql>
+	<sql id="queryWhereFlag" databaseId="oracle">
+		'%'||#{ flag}||'%'
+	</sql>
+	<sql id="queryWhereFlag" databaseId="sqlServer">
+		'%'+#{ flag}+'%'
+	</sql>
+	<!-- noFlag字段 -->
+	<sql id="queryWhereNoFlag" databaseId="mysql">
+		CONCAT('%',#{noFlag},'%')
+	</sql>
+	<sql id="queryWhereNoFlag" databaseId="oracle">
+		'%'||#{ noFlag}||'%'
+	</sql>
+	<sql id="queryWhereNoFlag" databaseId="sqlServer">
+		'%'+#{ noFlag}+'%'
+	</sql>
+	<!-- 已过期 -->
+	<select id="count" resultType="int">
+		select count(basic_id) FROM basic b
+		LEFT JOIN category c ON
+		b.BASIC_CATEGORYID = c.CATEGORY_ID
+		LEFT JOIN basic_column cl ON
+		c.CATEGORY_ID = cl.COLUMN_CATEGORY_ID
+		LEFT JOIN cms_article a ON
+		a.ARTICLE_BASICID = b.BASIC_ID
+		<where>
+			a.ARTICLE_WEBID = #{webId}
+			<if test="article != null ">
+				<if test="article.basicTitle != null and article.basicTitle != ''">
+					and b.BASIC_TITLE like
+					<include refid="queryWhereBasicTitle"></include>
+				</if>
+			</if>
+			<if test="basicCategoryIds != null">
+				and b.BASIC_CATEGORYID in
+				<foreach collection="basicCategoryIds" index="index" item="categoryId"
+						 open="(" separator="," close=")">
+					#{categoryId}
+				</foreach>
+			</if>
+			<if test="flag != null">
+				and a.ARTICLE_TYPE like <include refid="queryWhereFlag"></include>
+			</if>
+			<if test="noFlag != null">
+				and a.ARTICLE_TYPE not like <include refid="queryWhereNoFlag"></include>
+			</if>
+		</where>
+	</select>
+	<!-- 列表查询结束 -->
+
+	<!-- 列表查询开始 -->
+	<select id="query" resultMap="resultMap" >
+		select
+		<include refid="column_list" />
+		,c.CATEGORY_TITLE,c.CATEGORY_ID
+		,cl.COLUMN_PATH,cl.COLUMN_CM_ID,cl.COLUMN_TYPE,cl.COLUMN_CATEGORY_ID
+		FROM cms_article a LEFT JOIN basic b  ON a.ARTICLE_BASICID = b.BASIC_ID
+		LEFT JOIN basic_column cl ON b.BASIC_CATEGORYID = cl.COLUMN_CATEGORY_ID
+		JOIN category c ON c.CATEGORY_ID = cl.COLUMN_CATEGORY_ID
+		where a.ARTICLE_WEBID = #{webId}
+		<if test="article != null ">
+			<if test="article.basicTitle != null and article.basicTitle != ''">
+				and b.BASIC_TITLE like
+				<include refid="queryWhereBasicTitle"></include>
+			</if>
+		</if>
+		<if test="basicCategoryIds != null">
+			and b.BASIC_CATEGORYID in
+			<foreach collection="basicCategoryIds" index="index" item="categoryId"
+					 open="(" separator="," close=")">
+				#{categoryId}
+			</foreach>
+		</if>
+		<if test="flag != null">
+			and a.ARTICLE_TYPE like <include refid="queryWhereFlag"></include>
+		</if>
+		<if test="noFlag != null">
+			and a.ARTICLE_TYPE not like <include refid="queryWhereNoFlag"></include>
+		</if>
+		<if test="article !=null and article.basicDisplay &gt; -1">
+			and b.basic_display = #{article.basicDisplay}
+		</if>
+		<if test="beginTime!=null and beginTime!=''">
+			and basic_updatetime &gt;= #{beginTime}
+		</if>
+		<if test="endTime!=null and endTime!=''">
+			and basic_updatetime &gt;= #{endTime}
+		</if>
+		<if test="orderBy != null">
+			order by
+			<choose>
+				<when test='orderBy=="sort"'>basic_sort</when>
+				<when test='orderBy=="date"'>basic_datetime</when>
+				<when test='orderBy=="hit"'>basic_hit</when>
+				<when test='orderBy=="updatedate"'>basic_updatedate</when>
+				<when test='orderBy=="id"'>basic_id</when>
+				<otherwise>
+					${orderBy}
+				</otherwise>
+			</choose>
+		</if>
+		<if test="orderBy==null">
+			order by b.basic_id
+		</if>
+		<if test="order == true">desc</if>
+		<if test="order == false">asc</if>
+	</select>
+	<sql id="queryWhereCategoryId" databaseId="mysql">
+		find_in_set('${categoryId}',CATEGORY_PARENT_ID)
+	</sql>
+	<sql id="queryWhereCategoryId" databaseId="oracle" >
+		instr(','||'${categoryId}'||',', ','||CATEGORY_PARENT_ID||',')>0
+	</sql>
+	<sql id="queryWhereCategoryId" databaseId="sqlServer">
+		CHARINDEX(','+'${categoryId}'+',' , ','+CATEGORY_PARENT_ID +',')>0
+	</sql>
+	<!-- 根据站点编号、开始、结束时间和栏目编号查询文章编号集合 -->
+	<select id="queryIdsByCategoryIdForParser" resultMap="resultMapBean" >
+		select
+		ARTICLE_BASICID,cl.*,c.*
+		FROM cms_article a LEFT JOIN basic  ON a.ARTICLE_BASICID = basic.BASIC_ID
+		LEFT JOIN basic_column cl ON basic.BASIC_CATEGORYID = cl.COLUMN_CATEGORY_ID
+		JOIN category c ON c.CATEGORY_ID = cl.COLUMN_CATEGORY_ID
+		where
+		<if test="appId &gt; 0">
+			a.ARTICLE_WEBID = #{appId}
+		</if>
+		<!-- 查询子栏目数据 -->
+		<if test="categoryId &gt; 0">
+			and (basic.basic_categoryid=#{categoryId} or basic.basic_categoryid in
+			(select category_id FROM category where <include refid="queryWhereCategoryId"></include>))
+		</if>
+		<if test="beginTime!=null and beginTime!=''">
+			and basic.basic_updatetime &gt;= #{beginTime}
+		</if>
+		<if test="endTime!=null and endTime!=''">
+			and basic.basic_updatetime &gt;= #{endTime}
+		</if>
+		<if test="orderBy!=null and order!=null and orderBy!='' and order!=''">
+			ORDER BY `${orderBy}` ${order}
+		</if>
+	</select>
+
+
+
+	<!--查询页面栏目的文章 开始 -->
+	<!-- 已过期 -->
+	<select id="queryListByColumnId" resultMap="resultMap">
+		select
+		<include refid="column_list" />
+		from cms_article a left join basic b on b.basic_id=a.ARTICLE_BASICID
+		where b.BASIC_CATEGORYID = #{basicCategoryId}
+	</select>
+	<!-- 查询页面栏目的文章 结束 -->
+
+
+
+
+	<!-- 根据字段条件查找文章实体开始 -->
+	<sql id="queryLike" databaseId="mysql">
+		like CONCAT("%",
+		<foreach item="val" index="index" collection="item[3]">
+			<if test="index==0">#{val}</if>
+		</foreach>
+		,"%")
+	</sql>
+	<sql id="queryLike" databaseId="oracle">
+		like '%'||
+		<foreach item="val" index="index" collection="item[3]">
+			<if test="index==0">#{val}</if>
+		</foreach>
+		||'%'
+	</sql>
+	<sql id="queryLike" databaseId="sqlServer">
+		like '%'+
+		<foreach item="val" index="index" collection="item[3]">
+			<if test="index==0">#{val}</if>
+		</foreach>
+		+'%'
+	</sql>
+	<!-- 已过期 -->
+	<select id="queryListForSearch" resultMap="resultMap">
+		select
+		<include refid="column_list" />
+		,c.CATEGORY_TITLE,cl.column_path,c.CATEGORY_id,cl.COLUMN_CM_ID,cl.column_type
+		from cms_article a
+		left join basic b
+		on b.basic_id=a.ARTICLE_BASICID
+		left join category c
+		ON b.BASIC_CATEGORYID = c.CATEGORY_ID
+		left join
+		basic_column cl
+		on c.CATEGORY_ID = cl.COLUMN_CATEGORY_ID
+		<if test="tableName!=null">left join ${tableName} d on d.basicId=a.ARTICLE_BASICID
+		</if>
+		where c.DEL=0 and a.ARTICLE_WEBID = #{websiteId}
+		<if test="ids!=null">
+			and
+			b.BASIC_CATEGORYID in
+			<foreach item="id" index="key" collection="ids" open="("
+					 separator="," close=")">
+				#{id.categoryId}
+			</foreach>
+		</if>
+		<foreach item="item" index="key" collection="map" open=""
+				 separator="" close="">
+			<if test=" item[0] == false">
+				and ${key}
+			</if>
+			<if test="item[0]== true">
+				and d.${key}
+			</if>
+			<!-- 数字类型的查找 item[1]:字段是否为数字类型false:数字 -->
+			<if test="item[1] == false">
+				<!--item[2]: 是采用等值还是区间查询。false:区间 itme[3][0]第一个值item[3][1]的二个值 -->
+				<if test="item[2] == true">
+					=
+					<foreach item="val" index="index" collection="item[3]">#{val}
+					</foreach>
+				</if>
+				<if test="item[2] == false">
+					between
+					<foreach item="val" index="index" collection="item[3]"
+							 separator="and">
+						#{val}
+					</foreach>
+				</if>
+			</if>
+			<!-- 字符型数据的查找 item[1]:字段是否为数字类型true:字符串 -->
+			<if test="item[1] == true">
+				<!--item[2]: 是采用模糊查询。false:不采用模糊 -->
+				<if test="item[2] == true">
+					<include refid="queryLike"></include>
+				</if>
+				<if test="item[2] == false">
+					=
+					<foreach item="val" index="index" collection="item[3]">#{val}
+					</foreach>
+				</if>
+			</if>
+		</foreach>
+		<if test="sortMap!=null">
+			order by ${sortMap.order} ${sortMap.by}
+		</if>
+	</select>
+	<!-- 根据字段条件查找文章实体结束 -->
+
+	<!--已过期 根据字段条件查找文章实体总数开始 -->
+	<select id="getSearchCount" resultType="int">
+		select count(*) from
+		cms_article a
+		left join basic b
+		on
+		b.basic_id=a.ARTICLE_BASICID
+		left join category c
+		ON b.BASIC_CATEGORYID
+		= c.CATEGORY_ID
+		left join basic_column cl
+		on c.CATEGORY_ID =
+		cl.COLUMN_CATEGORY_ID
+		<if test="tableName!=null and tableName!=''">left join ${tableName} d on d.basicId=a.ARTICLE_BASICID
+		</if>
+		where a.ARTICLE_WEBID = #{websiteId}
+		<if test="ids!=null and ids!=''">
+			and FIND_IN_SET(category_categoryid,'${ids}')
+		</if>
+		<foreach item="item" index="key" collection="map" open=""
+				 separator="" close="">
+			<if test=" item[0] == false">
+				and ${key}
+			</if>
+			<if test="item[0]== true">
+				and d.${key}
+			</if>
+			<!-- 数字类型的查找 item[1]:字段是否为数字类型false:数字 -->
+			<if test="item[1] == false">
+				<!--item[2]: 是采用等值还是区间查询。false:区间 itme[3][0]第一个值item[3][1]的二个值 -->
+				<if test="item[2] == true">
+					=
+					<foreach item="val" index="index" collection="item[3]">#{val}
+					</foreach>
+				</if>
+				<if test="item[2] == false">
+					between
+					<foreach item="val" index="index" collection="item[3]"
+							 separator="and">
+						#{val}
+					</foreach>
+				</if>
+			</if>
+			<!-- 字符型数据的查找 item[1]:字段是否为数字类型true:字符串 -->
+			<if test="item[1] == true">
+				<!--item[2]: 是采用模糊查询。false:不采用模糊 -->
+				<if test="item[2] == true">
+					<include refid="queryLike"></include>
+				</if>
+				<if test="item[2] == false">
+					=
+					<foreach item="val" index="index" collection="item[3]">#{val}
+					</foreach>
+				</if>
+			</if>
+		</foreach>
+	</select>
+	<!-- 根据字段条件查找文章实体总数结束 -->
+
+	<select id="getById" resultMap="viewResultMap">
+		select
+		<include refid="basic_data_list" />
+		from
+		(((basic JOIN cms_article ON (BASIC_ID = ARTICLE_BASICID))
+		JOIN basic_column ON (BASIC_CATEGORYID = COLUMN_CATEGORY_ID))
+		JOIN category ON (COLUMN_CATEGORY_ID = CATEGORY_ID))
+		<if test="contentModelTableName!=null">
+			left join ${contentModelTableName} cmt on
+			cmt.basicid=basic_id
+		</if>
+		where basic_id=#{basicId}
+	</select>
+
+
+	<!-- 通过文章标题、应用ID、模块编号来查询文章集合开始 -->
+	<resultMap type="java.util.HashMap" id="resultTitleMap">
+		<result column="basic_id" property="basicId" />
+		<result column="basic_title" property="basicTitle" />
+		<result column="basic_hit" property="basicHit" />
+		<result column="basic_categoryid" property="basicCategoryId" />
+		<result column="model_id" property="modelId" />
+
+	</resultMap>
+	<!-- 已过期 -->
+	<!-- 查找上一篇下一篇 -->
+	<sql id="selectOne">
+		from
+		(((basic JOIN cms_article ON (BASIC_ID = ARTICLE_BASICID))
+		JOIN basic_column ON (BASIC_CATEGORYID = COLUMN_CATEGORY_ID))
+		JOIN category ON (COLUMN_CATEGORY_ID = CATEGORY_ID))
+
+		where category_appid=#{appId}
+		<if test="flag==false">
+			and basic_id &lt; ${basicId}
+
+		</if>
+		<if test="flag==true">
+			and basic_id &gt; ${basicId}
+
+		</if>
+		<if test="categoryId!=null">
+			and BASIC_CATEGORYID = #{categoryId}
+		</if>
+	</sql>
+	<!-- 已过期 -->
+	<select id="getNextOrPrevious" resultMap="resultMap" databaseId="mysql">
+		select
+		<include refid="basic_data_list" />
+		<include refid="selectOne"></include>
+		<if test="flag==false">
+			order by basic_id desc
+		</if>
+		<if test="flag==true">
+			order by basic_id asc
+		</if>
+		limit 0,1
+	</select>
+	<!-- 已过期 -->
+	<select id="getNextOrPrevious" resultMap="resultMap" databaseId="oracle">
+		select
+		<include refid="basic_data_list" />
+		<include refid="selectOne"></include>
+		and rownum=1
+		<if test="flag==false">
+			order by basic_id desc
+		</if>
+		<if test="flag==true">
+			order by basic_id asc
+		</if>
+	</select>
+	<!-- 已过期 -->
+	<select id="getNextOrPrevious" resultMap="resultMap" databaseId="sqlServer">
+		select top(1)
+		<include refid="basic_data_list" />
+		<include refid="selectOne"></include>
+		<if test="flag==false">
+			order by basic_id desc
+		</if>
+		<if test="flag==true">
+			order by basic_id asc
+		</if>
+	</select>
+	<sql id="queryTime" databaseId="oracle">
+		to_date(#{dateTime},'yyyy-MM-dd HH24:mi:ss')
+	</sql>
+	<sql id="queryTime" databaseId="mysql">
+		#{dateTime}
+	</sql>
+	<sql id="queryTime" databaseId="sqlServer">
+		#{dateTime}
+	</sql>
+	<!-- 已过期 -->
+	<select id="getByCategoryId" resultMap="resultMap">
+		select
+		<include refid="basic_data_list" />
+		from
+		(((basic JOIN cms_article ON (BASIC_ID = ARTICLE_BASICID))
+		JOIN basic_column ON (BASIC_CATEGORYID = COLUMN_CATEGORY_ID))
+		JOIN category ON (COLUMN_CATEGORY_ID = CATEGORY_ID))
+		where basic_categoryId=#{categoryId} order by basic_id desc
+	</select>
+
+	<!-- 根据basicID删除开始 -->
+	<delete id="delete">
+		delete from cms_article
+		<where>
+			ARTICLE_BASICID in
+			<foreach collection="ids" item="item" index="index" open="("
+					 separator="," close=")">#{item}</foreach>
+		</where>
+	</delete>
+
+</mapper>

+ 293 - 0
src/main/java/net/mingsoft/cms/entity/ArticleEntity.java

@@ -0,0 +1,293 @@
+/**
+The MIT License (MIT) * Copyright (c) 2016 铭飞科技(mingsoft.net)
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package net.mingsoft.cms.entity;
+
+import java.io.File;
+import java.util.Arrays;
+
+import net.mingsoft.basic.entity.AppEntity;
+import net.mingsoft.basic.entity.BasicEntity;
+import net.mingsoft.basic.entity.ColumnEntity;
+import org.apache.commons.lang3.StringUtils;
+
+import cn.hutool.core.util.ArrayUtil;
+import net.mingsoft.base.constant.Const;
+import net.mingsoft.mdiy.util.ParserUtil;
+
+/**
+ * 
+ * @ClassName:  ArticleEntity   
+ * @Description:TODO(文章模块实体类 || 继承BasicEntity实体)   
+ * @author: 铭飞开发团队
+ * @date:   2018年1月31日 下午2:55:48   
+ *     
+ * @Copyright: 2018 www.mingsoft.net Inc. All rights reserved.
+ */
+public class ArticleEntity extends BasicEntity{
+	
+	/**
+	 * 文章Id
+	 */
+	private int articleID;
+	
+	/**
+	 * 文章内容
+	 */
+	private String articleContent;
+	
+	/**
+	 * 文章作者
+	 */
+	private String articleAuthor;
+	
+	/**
+	 * 文章属性
+	 */
+	private String articleType ;
+	
+	/**
+	 * 文章的来源
+	 */
+	private String articleSource;
+
+	/**
+	 * 文章跳转链接地址
+	 */
+	private String articleUrl;
+	
+	/**
+	 * 文章关键字
+	 */
+	private String articleKeyword;
+	
+	/**
+	 * 文章自定义显示顺序
+	 */
+	@Deprecated
+	private int articleFreeOrder;
+	
+	
+	/**
+	 * 站点d
+	 */
+	private int articleWebId;
+	
+	/**
+	 * 文章url地址 主要是用户生成html使用
+	 */
+	private String articleLinkURL;
+	
+	/**
+	 * 文章分类url地址,主要是用户生成html使用
+	 */
+	private String articleTypeLinkURL;
+	
+	/**
+	 * 一对一管理栏目
+	 */
+	private ColumnEntity  column;
+	
+	
+	/**
+	 * 获取文章实体所属的栏目实体
+	 * @return
+	 */
+	public ColumnEntity getColumn() {
+		return column;
+	}
+	
+	/**
+	 * 设置文章所属的栏目实体
+	 * @param column
+	 */
+	public void setColumn(ColumnEntity column) {
+		this.column = column;
+	}
+
+	public String getArticleTypeLinkURL() {
+		return articleTypeLinkURL;
+	}
+
+	public void setArticleTypeLinkURL(String articleTypeLinkURL) {
+		this.articleTypeLinkURL = articleTypeLinkURL;
+	}
+
+	public String getArticleLinkURL() {
+		return articleLinkURL;
+	}
+
+	public void setArticleLinkURL(String articleLinkURL) {
+		this.articleLinkURL = articleLinkURL;
+	}
+
+	/**
+	 * 获取文章作者
+	 * @return 返回文章作者
+	 */
+	public String getArticleAuthor() {
+		return articleAuthor;
+	}
+
+	/**
+	 * 获取文章内容
+	 * @return 返回文章内容
+	 */
+	public String getArticleContent() {
+		return articleContent;
+	}
+
+	/**
+	 * 获取自定义显示顺序
+	 * @return
+	 */
+	public int getArticleFreeOrder() {
+		return articleFreeOrder;
+	}
+	
+	/**
+	 * 获取文章Id
+	 * @return 返回文章Id
+	 */
+	public int getArticleID() {
+		return articleID;
+	}
+	
+	/**
+	 * 获取文章关键字
+	 * @return 返回文章关键字
+	 */
+	public String getArticleKeyword() {
+		return articleKeyword;
+	}
+	
+	/**
+	 * 获取文章的来源
+	 * @return 返回文章的来源
+	 */
+	public String getArticleSource() {
+		return articleSource;
+	}
+	
+	/**
+	 * 获取文章属性
+	 * @return 返回文章属性
+	 */
+	public String getArticleType() {
+		return articleType;
+	}
+	
+	/**
+	 * 获取文章跳转链接
+	 * @return 返回文章跳转链接
+	 */
+	public String getArticleUrl() {
+		return articleUrl; 
+	}
+	
+	/**
+	 * 获取文章站点id
+	 * @return
+	 */
+	public int getArticleWebId() {
+		return articleWebId;
+	}
+	
+	/**
+	 * 设置文章作者
+	 * @param articleAuthor 传入文章作者
+	 */
+	public void setArticleAuthor(String articleAuthor) {
+		this.articleAuthor = articleAuthor;
+	}
+	
+	/**
+	 * 设置文章内容
+	 * @param articleContent 传入文章内容
+	 */
+	public void setArticleContent(String articleContent) {
+		this.articleContent = articleContent;
+	}
+	
+	/**
+	 * 设置文章自定义显示循序排序
+	 * @param articleFreeOrder
+	 */
+	public void setArticleFreeOrder(int articleFreeOrder) {
+		this.articleFreeOrder = articleFreeOrder;
+	}
+
+	/**
+	 * 设置文章Id
+	 * @param articleID 传入文章Id
+	 */
+	public void setArticleID(int articleID) {
+		this.articleID = articleID;
+	}
+
+	/**
+	 * 设置文章关键字
+	 * @param articleKeyword 传入文章关键字列表
+	 */
+	public void setArticleKeyword(String articleKeyword) {
+		this.articleKeyword = articleKeyword;
+	}
+
+	/**
+	 * 设置文章的来源
+	 * @param articleSource 传入文章的来源
+	 */
+	public void setArticleSource(String articleSource) {
+		this.articleSource = articleSource;
+	}
+
+	/**
+	 * 设置文章属性
+	 * @param articleType 传入文章属性
+	 */
+	public void setArticleType(String articleType) {
+		this.articleType = articleType;
+	}
+	
+	/**
+	 * 设置文章跳转链接
+	 * @param articleUrl 传入文章跳转链接地址
+	 */
+	public void setArticleUrl(String articleUrl) {
+		this.articleUrl = articleUrl;
+	}
+
+
+	/**
+	 * 设置文章站点id
+	 * @param articleWebId
+	 */
+	public void setArticleWebId(int articleWebId) {
+		this.articleWebId = articleWebId;
+	}
+	
+	public String getArticleUrl(AppEntity app) {
+		if (!StringUtils.isBlank(app.getAppMobileStyle())) {
+			return app.getAppHostUrl()+ParserUtil.HTML+Const.SEPARATOR+ParserUtil.MOBILE+Const.SEPARATOR+this.getArticleUrl();
+		}
+		return app.getAppHostUrl()+Const.SEPARATOR+ParserUtil.HTML+Const.SEPARATOR+this.getArticleUrl();
+	}
+}

+ 6 - 0
src/main/java/net/mingsoft/cms/resources/resources_zh_CN.properties

@@ -0,0 +1,6 @@
+#mcms\u7248\u672C
+version=d3a98fefcb242db78da5fc31608ff247
+templet.file=\u6A21\u677F\u6587\u4EF6\u4E0D\u5B58\u5728
+id=\u6587\u7AE0\u7F16\u53F7
+typeid=\u680F\u76EE\u7F16\u53F7
+order=\u6392\u5E8F

+ 289 - 0
src/main/java/net/mingsoft/cms/util/CmsParserUtil.java

@@ -0,0 +1,289 @@
+package net.mingsoft.cms.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.PageUtil;
+import freemarker.cache.FileTemplateLoader;
+import freemarker.core.ParseException;
+import freemarker.template.MalformedTemplateNameException;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+import freemarker.template.TemplateNotFoundException;
+import net.mingsoft.base.constant.Const;
+import net.mingsoft.basic.entity.ColumnEntity;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.basic.util.SpringUtil;
+import net.mingsoft.cms.bean.ColumnArticleIdBean;
+import net.mingsoft.cms.constant.e.ColumnTypeEnum;
+import net.mingsoft.mdiy.bean.PageBean;
+import net.mingsoft.mdiy.biz.IContentModelBiz;
+import net.mingsoft.mdiy.entity.ContentModelEntity;
+import net.mingsoft.mdiy.parser.TagParser;
+import net.mingsoft.mdiy.util.ParserUtil;
+
+public class CmsParserUtil extends ParserUtil {
+
+	/**
+	 * 指定模板,指定路径进行生成静态页面,会自定识别pc与移动端
+	 * 
+	 * @param templatePath
+	 *            模板路径
+	 * @param targetPath
+	 *            生成后的路径,默认生成的html文件,所以不能带.html后缀,
+	 * @throws IOException
+	 */
+	public static void generate(String templatePath, String targetPath) throws IOException {
+		Map<String, Object> map = new HashMap<String, Object>();
+		map.put(IS_DO, false);
+		ColumnEntity column = new ColumnEntity();
+		//内容管理栏目编码
+		column.setCategoryModelId(BasicUtil.getModelCodeId("02990000"));
+		map.put(COLUMN, column);
+		String content = CmsParserUtil.generate(templatePath, map, false);
+		FileUtil.writeString(content, ParserUtil.buildHtmlPath(targetPath), Const.UTF8);
+		
+		// 生成移动页面
+		if (ParserUtil.hasMobileFile(templatePath)) {
+			// 手机端m
+			map.put(ParserUtil.MOBILE, BasicUtil.getApp().getAppMobileStyle());
+			content = CmsParserUtil.generate(templatePath, map, true);
+			FileUtil.writeString(content, ParserUtil.buildMobileHtmlPath(targetPath), Const.UTF8);
+		}
+	}
+
+	/**
+	 * 生成静态列表页
+	 * @param column
+	 * @param articleIdTotal
+	 * @throws TemplateNotFoundException
+	 * @throws MalformedTemplateNameException
+	 * @throws ParseException
+	 * @throws IOException
+	 */
+	public static void generateList(ColumnEntity column, int articleIdTotal)
+			throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException {
+		// 只初始化一次cfg
+		if (ftl == null) {
+			ftl = new FileTemplateLoader(new File(ParserUtil.buildTempletPath()));
+			cfg.setTemplateLoader(ftl);
+		}
+		// 移动端模板
+		Template mobileTemplate = cfg.getTemplate(
+				BasicUtil.getApp().getAppMobileStyle() + File.separator + column.getColumnListUrl(), Const.UTF8);
+		// pc端模板
+		Template template = cfg.getTemplate(File.separator + column.getColumnListUrl(), Const.UTF8);
+
+		// 文章的栏目模型编号
+		int columnContentModelId = column.getColumnContentModelId();
+		StringWriter writer = new StringWriter();
+		try {
+			// 为了分页添加column,判断栏目是否为父栏目
+			template.process(null, writer);
+			String content = writer.toString();
+			//获取列表页显示的文章数量
+			int pageSize = TagParser.getPageSize(content);
+			//获取总数
+			int totalPageSize = PageUtil.totalPage(articleIdTotal, pageSize);
+			
+			String columnListPath;
+			String mobilePath;
+			ContentModelEntity contentModel = null;
+			// 判断当前栏目是否有自定义模型
+			if (columnContentModelId > 0) {
+				// 通过栏目模型编号获取自定义模型实体
+				contentModel = (ContentModelEntity) SpringUtil.getBean(IContentModelBiz.class).getEntity(columnContentModelId);
+			}
+			int pageNo = 1;
+			PageBean page = new PageBean();
+			page.setSize(pageSize);
+			//全局参数设置
+			Map<String, Object> parserParams = new HashMap<String, Object>();
+			parserParams.put(COLUMN, column);
+			page.setTotal(totalPageSize);
+			parserParams.put(IS_DO, false);
+			parserParams.put(HTML, HTML);
+			parserParams.put(APP_ID, BasicUtil.getAppId());
+			if (contentModel!=null) {
+				// 将自定义模型编号设置为key值
+				parserParams.put(TABLE_NAME, contentModel.getCmTableName());
+			}
+			//如果单站点,就废弃站点地址
+			if(ParserUtil.IS_SINGLE) {
+				parserParams.put(ParserUtil.URL, BasicUtil.getUrl());
+			}
+			
+			//文章列表页没有写文章列表标签,总数为0
+			if (totalPageSize <= 0) {
+	            // 数据库中第一页是从开始0*size
+	            // 首页路径index.html
+	            mobilePath = ParserUtil.buildMobileHtmlPath(column.getColumnPath() + File.separator + ParserUtil.INDEX);
+	            columnListPath = ParserUtil.buildHtmlPath(column.getColumnPath() + File.separator + ParserUtil.INDEX);
+	            // 设置分页的起始位置
+				page.setPageNo(pageNo);
+				parserParams.put(ParserUtil.PAGE, page);
+				TagParser tag = new TagParser(content,parserParams);
+	            FileUtil.writeString(tag.rendering(), columnListPath, Const.UTF8);
+	            // 判断是手机端生成还是pc端,防止重复生成
+	            if (ParserUtil.hasMobileFile(column.getColumnListUrl())) {
+	               writer = new StringWriter();
+	               mobileTemplate.process(null, writer);
+	               tag = new TagParser(writer.toString(), parserParams);
+	               // 将tag.getContent()写入路径
+	               FileUtil.writeString(tag.rendering(), mobilePath, Const.UTF8);
+	            }
+	            writer = new StringWriter();
+	         } else {
+	            // 遍历分页
+	            for (int i = 0; i < totalPageSize; i++) {
+	            	if (i == 0) {
+						// 数据库中第一页是从开始0*size
+						// 首页路径index.html
+						mobilePath = ParserUtil
+								.buildMobileHtmlPath(column.getColumnPath() + File.separator + ParserUtil.INDEX);
+						columnListPath = ParserUtil
+								.buildHtmlPath(column.getColumnPath() + File.separator + ParserUtil.INDEX);
+					} else {
+						// 其他路径list-2.html
+						mobilePath = ParserUtil.buildMobileHtmlPath(
+								column.getColumnPath() + File.separator + ParserUtil.PAGE_LIST + pageNo);
+						columnListPath = ParserUtil
+								.buildHtmlPath(column.getColumnPath() + File.separator + ParserUtil.PAGE_LIST + pageNo);
+					}
+					// 设置分页的起始位置
+					page.setPageNo(pageNo);
+					parserParams.put(ParserUtil.PAGE, page);
+					TagParser tag = new TagParser(content,parserParams);
+					FileUtil.writeString(tag.rendering(), columnListPath, Const.UTF8);
+					// 判断是手机端生成还是pc端,防止重复生成
+					if (ParserUtil.hasMobileFile(column.getColumnListUrl())) {
+						writer = new StringWriter();
+						mobileTemplate.process(null, writer);
+						tag = new TagParser(writer.toString(),parserParams);
+						// 将tag.getContent()写入路径
+						FileUtil.writeString(tag.rendering(), mobilePath, Const.UTF8);
+					}
+					writer = new StringWriter();
+					pageNo++;
+	            }
+	         }
+		} catch (TemplateException e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * 生成内容
+	 * 
+	 * @param articleIdList
+	 *            文章集合
+	 * @return
+	 * @throws IOException
+	 * @throws ParseException
+	 * @throws MalformedTemplateNameException
+	 * @throws TemplateNotFoundException
+	 */
+	public static void generateBasic(List<ColumnArticleIdBean> articleIdList)
+			throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException {
+
+		Map<Object, Object> contentModelMap = new HashMap<Object, Object>();
+		ContentModelEntity contentModel = null;
+		String writePath = null;
+		// 记录已经生成了文章编号
+		List<Integer> generateIds = new ArrayList<>();
+		// 生成文档
+		for (int artId = 0; artId < articleIdList.size();) {
+			//设置分页类
+			PageBean page = new PageBean();
+			// 文章编号
+			int articleId = articleIdList.get(artId).getArticleId();
+			// 文章的栏目路径
+			String articleColumnPath = articleIdList.get(artId).getColumnPath();
+			// 文章的模板路径
+			String columnUrl = articleIdList.get(artId).getColumnUrl();
+			// 文章的栏目模型编号
+			int columnContentModelId = articleIdList.get(artId).getColumnContentModelId();
+			// 文章是否已经生成了,生成了就跳过
+			if (generateIds.contains(articleId)) {
+				artId++;
+				continue;
+			}
+
+			// 判断文件是否存在,若不存在弹出返回信息
+			if (!FileUtil.exist(ParserUtil.buildTempletPath(columnUrl))) {
+				artId++;
+				continue;
+			}
+			// 将
+			generateIds.add(articleId);
+			// 组合文章路径如:html/站点id/栏目id/文章id.html
+			writePath = ParserUtil.buildHtmlPath(articleColumnPath + File.separator + articleId);
+			//如果是封面就生成index.html
+			if(articleIdList.get(artId).getColumnType() == ColumnTypeEnum.COLUMN_TYPE_COVER.toInt()) {
+				writePath = ParserUtil.buildHtmlPath(articleColumnPath + File.separator + ParserUtil.INDEX);
+			}
+			Map<String, Object> parserParams = new HashMap<String, Object>();
+			parserParams.put(ParserUtil.COLUMN, articleIdList.get(artId));
+			// 判断当前栏目是否有自定义模型
+			if (columnContentModelId > 0) {
+				// 通过当前栏目的模型编号获取,自定义模型表名
+				if (contentModelMap.containsKey(columnContentModelId)) {
+					parserParams.put(TABLE_NAME, contentModel.getCmTableName());
+				} else {
+					// 通过栏目模型编号获取自定义模型实体
+					contentModel = (ContentModelEntity) SpringUtil.getBean(IContentModelBiz.class)
+							.getEntity(columnContentModelId);
+					// 将自定义模型编号设置为key值
+					contentModelMap.put(columnContentModelId, contentModel.getCmTableName());
+					parserParams.put(TABLE_NAME, contentModel.getCmTableName());
+				}
+			}
+
+			parserParams.put(ID, articleId);
+			// 第一篇文章没有上一篇
+			if (artId > 0) {
+				ColumnArticleIdBean preCaBean = articleIdList.get(artId - 1);
+				//判断当前文档是否与上一页文章在同一栏目下,并且不能使用父栏目字符串,因为父栏目中没有所属栏目编号
+				if(articleColumnPath.contains(preCaBean.getCategoryId()+"")){
+					page.setPreId(preCaBean.getArticleId());
+				}
+			}
+			// 最后一篇文章没有下一篇
+			if (artId + 1 < articleIdList.size()) {
+				ColumnArticleIdBean nextCaBean = articleIdList.get(artId + 1);
+				//判断当前文档是否与下一页文章在同一栏目下并且不能使用父栏目字符串,因为父栏目中没有所属栏目编号
+				if(articleColumnPath.contains(nextCaBean.getCategoryId()+"")){
+					page.setNextId(nextCaBean.getArticleId());
+				}
+			}
+
+			parserParams.put(IS_DO, false);
+			parserParams.put(ParserUtil.PAGE, page);
+			String content = CmsParserUtil.generate(articleIdList.get(artId).getColumnUrl(), parserParams, false);
+			FileUtil.writeString(content, writePath, Const.UTF8);
+			// 手机端
+			if (ParserUtil.hasMobileFile(columnUrl)) {
+				writePath = ParserUtil.buildMobileHtmlPath(articleColumnPath + File.separator + articleId);
+				//如果是封面就生成index.html
+				if(articleIdList.get(artId).getColumnType() == ColumnTypeEnum.COLUMN_TYPE_COVER.toInt()) {
+					writePath = ParserUtil.buildMobileHtmlPath(articleColumnPath + File.separator + ParserUtil.INDEX);
+				}
+				// 判断文件是否存在,若不存在弹出返回信息
+				if (!FileUtil.exist(ParserUtil.buildTempletPath(MOBILE + File.separator + columnUrl))) {
+					artId++;
+					continue;
+				}
+				parserParams.put(MOBILE, BasicUtil.getApp().getAppMobileStyle());
+				content = CmsParserUtil.generate(articleIdList.get(artId).getColumnUrl(), parserParams, true);
+				FileUtil.writeString(content, writePath, Const.UTF8);
+			}
+			artId++;
+		}
+	}
+}

+ 41 - 26
src/main/java/net/mingsoft/config/WebConfig.java

@@ -1,11 +1,14 @@
 package net.mingsoft.config;
 
 import java.io.File;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.springframework.aop.Advisor;
 import net.mingsoft.basic.filter.XSSEscapeFilter;
 import org.springframework.aop.support.DefaultPointcutAdvisor;
 import org.springframework.aop.support.JdkRegexpMethodPointcut;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.web.servlet.FilterRegistrationBean;
 import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
 import org.springframework.boot.web.servlet.ServletRegistrationBean;
@@ -31,6 +34,16 @@ import net.mingsoft.basic.util.BasicUtil;
 @Configuration
 public class WebConfig implements WebMvcConfigurer {
 
+	/**
+	 * 上传路径
+	 */
+	@Value("${ms.upload.path}")
+	private String uploadFloderPath;
+	/**
+	 * 上传路径映射
+	 */
+	@Value("${ms.upload.mapping}")
+	private String uploadMapping;
 	@Bean
 	public ActionInterceptor actionInterceptor() {
 		return new ActionInterceptor();
@@ -54,23 +67,24 @@ public class WebConfig implements WebMvcConfigurer {
 
 	@Override
 	public void addResourceHandlers(ResourceHandlerRegistry registry) {
-		//jar包方式映射处理
-		String classPath = BasicUtil.getClassPath("");
-		if (classPath.startsWith("file")) {
-			registry.addResourceHandler("/upload/**").addResourceLocations("file:" + BasicUtil.getRealPath("upload") + File.separator);
-			registry.addResourceHandler("/html/**").addResourceLocations("file:" + BasicUtil.getRealPath("html") + File.separator);
-			registry.addResourceHandler("/templets/**").addResourceLocations("file:" + BasicUtil.getRealPath("templets") + File.separator);
-		} else {
-			//必须做判断,不然jar运行的html路径会被覆盖掉
-			registry.addResourceHandler("/html/**").addResourceLocations("/html/");
+		registry.addResourceHandler("/upload/**").addResourceLocations("/upload/","file:upload/");
+		registry.addResourceHandler("/templets/**").addResourceLocations("/templets/","file:templets/");
+		registry.addResourceHandler("/html/**").addResourceLocations("/html/","file:html/");
+		//三种映射方式 webapp下、当前目录下、jar内
+		registry.addResourceHandler("/app/**").addResourceLocations("/app/","file:app/", "classpath:/app/");
+		registry.addResourceHandler("/static/**","/**").addResourceLocations("/static/","file:static/","classpath:/static/","classpath:/META-INF/resources/");
+		registry.addResourceHandler("/api/**").addResourceLocations("/api/","file:api/", "classpath:/api/");
+		if(new File(uploadFloderPath).isAbsolute()){
+			//如果指定了绝对路径,上传的文件都映射到uploadMapping下
+			registry.addResourceHandler(uploadMapping).addResourceLocations("file:"+uploadFloderPath+ File.separator
+					//映射其他路径文件
+					//,file:F://images
+			);
 		}
-		registry.addResourceHandler("/app/**").addResourceLocations("/app/", "classpath:/app/");
-		registry.addResourceHandler("/static/**").addResourceLocations("/static/", "classpath:/static/");
-		registry.addResourceHandler("/api/**").addResourceLocations("/api/", "classpath:/api/");
 	}
-		/**
-         * druidServlet注册
-         */
+	/**
+	 * druidServlet注册
+	 */
 	@Bean
 	public ServletRegistrationBean druidServletRegistration() {
 		ServletRegistrationBean registration = new ServletRegistrationBean(new StatViewServlet());
@@ -132,16 +146,17 @@ public class WebConfig implements WebMvcConfigurer {
 		return new DefaultPointcutAdvisor(druidStatPointcut(), druidStatInterceptor());
 	}
 
-	 /**
-	 * xssFilter注册
-	 */
-//	 @Bean
-//	 public FilterRegistrationBean xssFilterRegistration() {
-//	 XSSEscapeFilter xssFilter = new XSSEscapeFilter();
-//	 FilterRegistrationBean registration = new FilterRegistrationBean(xssFilter);
-//	 registration.addUrlPatterns("/*");
-//	 return registration;
-//	 }
+    @Bean
+    public FilterRegistrationBean xssFilterRegistration() {
+        XSSEscapeFilter xssFilter = new XSSEscapeFilter();
+        FilterRegistrationBean registration = new FilterRegistrationBean(xssFilter);
+        xssFilter.excludes.add(".*file/upload.do");
+        xssFilter.excludes.add(".*/jsp/editor.do");
+        xssFilter.excludes.add(".*/?(jpg|js|css|gif|png|ico)$");
+        xssFilter.excludes.add("/");
+        registration.addUrlPatterns("/*");
+        return registration;
+    }
 
 	/**
 	 * RequestContextListener注册
@@ -156,7 +171,7 @@ public class WebConfig implements WebMvcConfigurer {
 	@Override
 	public void addViewControllers(ViewControllerRegistry registry) {
 		registry.addViewController("/").setViewName("forward:/index");
-        registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
+		registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
 		WebMvcConfigurer.super.addViewControllers(registry);
 	}
 }

+ 16 - 6
src/main/resources/application.yml

@@ -12,14 +12,23 @@ ms:
   view-path: /WEB-INF/manager
   
  upload: 
-   path: /upload 
+   path: upload
+   mapping: /upload/**
    denied: .exe,.jsp
-   allowed: jpg
-   max-size: 1
-   memory-size: 4096
-      
+   multipart:
+     #最大上传文件大小 单位:KB
+     max-file-size: 10240
+     #文件暂存临时目录
+     upload-temp-dir: temp
+     #临时文件大小
+     max-in-memory-size: 10240
+     #总上传最大大小 单位:KB -1禁用
+     max-request-size: -1
+
+
+
+
 spring:
-  http.multipart.enabled: false
   profiles:
     active: dev
   mvc:
@@ -53,6 +62,7 @@ spring:
       time_format: HH:mm:ss
       datetime_format: yyyy-MM-dd HH:mm:ss
       auto_import: /include/macro.ftl as ms
+      number_format: 0.##
       
 mybatis:
   mapper-locations: classpath*:**/dao/*.xml

+ 231 - 0
src/main/webapp/WEB-INF/manager/cms/article/article_form.ftl

@@ -0,0 +1,231 @@
+<@ms.html5>
+	<@ms.nav title="文章管理" back=true>
+		<#if article.basicId == 0>
+	 		<@ms.saveButton id="saveUpdate" value="保存"/>
+	 	<#else>
+	 		<@ms.updateButton id="saveUpdate" value="更新"/>
+	 	</#if>
+	</@ms.nav>
+	<@ms.panel>
+		<@ms.form isvalidation=true name="articleForm" action="${managerPath}/cms/article/${action}.do">
+			<@ms.text name="basicTitle" colSm="2" width="400" label="文章标题"	title="文章标题" size="5"  placeholder="请输入文章标题"  value="${article.basicTitle?default('')}"  validation={"maxlength":"300","required":"true", "data-bv-notempty-message":"文章标题不能为空","data-bv-stringlength-message":"标题在300个字符以内!", "data-bv-notempty-message":"必填项目"}/>
+			<@ms.text name="basicSort"  colSm="2" width="200" label="自定义顺序" title="自定义顺序" size="5"  placeholder="请输入文章顺序" value="${article.basicSort?c?default(0)}" validation={"data-bv-between":"true","required":"true", "data-bv-between-message":"自定义顺序必须大于0","data-bv-between-min":"0", "data-bv-between-max":"99999999","data-bv-notempty-message":"自定义顺序不能为空"}/>
+			<#if articleType?has_content>
+				<@ms.checkboxlist colSm="2" name="checkbox" label="文章属性" list=articleType listKey="dictValue"  listValue="dictLabel" />
+			</#if>
+			<@ms.radio name="basicDisplay" 
+			    list=[{"id":"0","value":"是"},{"id":"1","value":"否"}] value="${article.basicDisplay?c?default()}" 
+			    listKey="id" listValue="value" label="是否显示" help="选择否后前端将不显示,需要重新生成才有效果"
+			/>
+			<@ms.formRow colSm="2" label="文章缩略图" width="400" >
+					<@ms.uploadImg path="${websiteId}/article" inputName="basicThumbnails" size="1" msg="提示:文章缩略图,支持jpg格式"  imgs="${article.basicThumbnails?default('')}"  />
+			</@ms.formRow>
+			<@ms.text name="articleSource" colSm="2" width="200" label="文章来源" title="文章来源" size="5"  placeholder="请输入文章来源"  value="${article.articleSource?default('')}" validation={"maxlength":"300", "data-bv-stringlength-message":"文章来源在300个字符以内!"} />
+			<@ms.text name="articleAuthor" colSm="2" width="200" label="文章作者" title="文章作者" size="5"  placeholder="请输入文章作者"  value="${article.articleAuthor?default('')}" validation={"maxlength":"12", "data-bv-stringlength-message":"文章作者在12个字符以内!"} />
+			<#if !isEditCategory><!-- 如果不是单篇 -->
+	            <@ms.formRow colSm="2" label="所属栏目" width="300">
+	            <#if categoryTitle=="">
+	            	<@ms.treeInput treeId="inputTree" json="${listColumn?default('')}" jsonId="categoryId" jsonPid="categoryCategoryId" jsonName="categoryTitle" inputName="basicCategoryId" inputValue="${categoryId}" buttonText="选择栏目" clickZtreeId="clickZtreeId(event,treeId,treeNode);" expandAll="true"  showIcon="true"/>
+	            <#else>
+	            	<@ms.treeInput treeId="inputTree" json="${listColumn?default('')}" jsonId="categoryId" jsonPid="categoryCategoryId" jsonName="categoryTitle" inputName="basicCategoryId" inputValue="${categoryId}" buttonText="${(categoryTitle)!}" clickZtreeId="clickZtreeId(event,treeId,treeNode);" expandAll="true"  showIcon="true"/>
+				</#if>
+				</@ms.formRow>
+            </#if>
+            <@ms.hidden id="basicDateTime" name="basicDateTime" value=""/>
+            <@ms.date id="articleDateTime" name="articleDateTime" time=true label="发布时间" single=true readonly="readonly" width="300" value="${(article.basicDateTime?default(.now))?string('yyyy-MM-dd HH:mm')}" validation={"required":"true", "data-bv-notempty-message":"必填项目"} placeholder="点击该框选择时间段"  />
+			<@ms.textarea colSm="2" name="basicDescription" label="描述" wrap="Soft" rows="4"  size=""  value="${article.basicDescription?default('')}" placeholder="请输入对该文章的简短描述,以便用户查看文章简略" validation={"maxlength":"400","data-bv-stringlength-message":"文章描述在400个字符以内!"}/>
+			<@ms.textarea colSm="2" name="articleKeyword" label="关键字" wrap="Soft" rows="4"  size="" placeholder="请输入文章关键字"   value="${article.articleKeyword?default('')}" validation={"maxlength":"155", "data-bv-stringlength-message":"文章作者在155个字符以内!"}/>
+			<!--新填字段内容开始-->
+			<div id="addFieldForm">		
+			</div>
+			<@ms.hidden name="articleTypeJson" />
+			<@ms.editor colSm="2" name="articleContent" label="文章内容" content="${article.articleContent?default('')}"  appId="${appId?default(0)}"/>			
+			<@ms.hidden name="modelId"  value="${Session.model_id_session?default('0')}" />
+		</@ms.form>
+	</@ms.panel>
+</@ms.html5>     
+<script>
+//重写时间控件
+$('#articleDateTime').daterangepicker({
+	format:'YYYY-MM-DD HH:mm',
+	singleDatePicker: true,
+	showDropdowns: true,
+	timePickerIncrement: 1,
+  	timePicker: true,
+  	timePicker12Hour: true,
+  	startDate: moment().hours(0).minutes(0).seconds(0),
+   	showDropdowns: true,
+    showWeekNumbers: true,
+  });
+$('#articleDateTime').on('apply.daterangepicker', function(ev, picker) {
+		$('#articleDateTime').parents("form:first").data('bootstrapValidator').revalidateField('articleDateTime');
+});
+var articleBasicId=0;
+$(function(){
+	//页面标题
+	var articleTitle="<#if categoryTitle?has_content>${categoryTitle}&nbsp;</#if><#if article.basicId !=0><small>编辑文章</small><#else><small>添加文章</small></#if>";
+	$(".ms-weixin-content-body-title>span").html(articleTitle);	
+	//隐藏跳转地址
+	$("input[name='articleUrl']").parent().hide();
+	
+	//文章属性
+	var actionUrl="";
+	
+	<#if article.basicId !=0>
+	actionUrl = "${managerPath}/cms/article/${article.basicId?c?default(0)}/update.do";
+	var type="${article.articleType?default('')}";
+	var articleType = new Array;
+	//文章属性
+	$("#articleForm input[name='checkbox']").each(function(){
+		if(type!=""){
+			articleType = type.split(",");
+		  	for(i=0;i<articleType.length;i++){
+				if($(this).val()==articleType[i]){
+					$(this).attr("checked",'true');
+				}
+			}
+		}
+	});
+	articleBasicId=${article.basicId?c?default(0)};
+	<#else>
+	actionUrl = "${managerPath}/cms/article/save.do";
+	</#if>	
+	
+	//获取当前栏目的自定义模型
+	var url="${managerPath}/mdiy/contentModel/contentModelField/"+${categoryId?default(0)}+"/queryField.do";
+	var articleId="basicId="+${article.basicId?c?default(0)};
+	$(this).request({url:url,data:articleId,method:"get",func:function(data) {
+		$("#addFieldForm").html(data);
+	}});
+
+	//显示跳转地址
+	$("input[name='checkbox']").click(function(){
+		$("input[name='checkbox']").each(function(){
+			if( $(this).val() == 'j'){
+				if($(this).is(":checked") ){
+					$("input[name='articleUrl']").parent().show();
+				}else{
+					$("input[name='articleUrl']").parent().hide();
+				}
+			}
+		});
+	});	
+	
+	//更新或保存				
+	$("#saveUpdate").click(function(){
+		//禁用按钮
+		$("#saveUpdate").attr("disabled",true);
+		//获取按钮值
+		var bottonText = $("#saveUpdate").text().trim();
+		//设置按钮加载状态值
+		$("#saveUpdate").attr("data-loading-text",bottonText+"中");
+		
+		var articleDateTimeValue = $("#articleDateTime").val()+":00";//让时间能精确到秒与后台对应
+		$("#basicDateTime").val(articleDateTimeValue); //给basicDateTime字段赋值
+		//获取所有栏目属性被选中的值
+		var typeJson=""
+		$("#articleTypeField").find("select").each(function(index){ 
+			var typeValue=0;
+			if($(this).find("option:selected").val()==undefined){
+				return;
+			}
+			var typeValue=$(this).find("option:selected").val();
+			if($("#articleTypeField").find("select").length==index){
+				typeJson =typeJson+ "{bcCategoryId:\"" + typeValue + "\",bcBasicId:'${article.basicId?default(0)}'}"
+			}else{
+				typeJson =typeJson+ "{bcCategoryId:\"" + typeValue + "\",bcBasicId:'${article.basicId?default(0)}'},"
+			}
+			
+		})
+		$("input[name=articleTypeJson]").val("["+typeJson+"]");
+		var basicCategoryId="";
+		<#if !isEditCategory><!-- 如果不是单篇 -->
+			basicCategoryId=$("input[name='basicCategoryId']").val(); //多篇时的文章栏目
+		<#else>
+			basicCategoryId=${categoryId}; //单篇时的文章栏目
+		</#if>
+		//文章所属栏目是数字且不能为0
+		if(basicCategoryId !=0 && !isNaN(basicCategoryId) ){
+			//将表单序列化
+			var saveArticle = $("#articleForm").serialize();
+			saveArticle += "&basicCategoryId="+basicCategoryId;
+			//文章属性
+			var checkboxType="";
+			$("input[name='checkbox']").each(function(){
+				if($(this).is(":checked")){
+					checkboxType+=$(this).val()+",";
+				}
+			});
+			var dataMsg = saveArticle+"&checkboxType="+checkboxType;
+			var seeMsg = "";
+			<#if article.basicId !=0>
+	   			seeMsg="更新中....";
+	   		<#else>
+	   			seeMsg="保存中....";
+	   		</#if>
+	   		var vobj = $("#articleForm").data('bootstrapValidator').validate();
+			if(vobj.isValid()){
+				if(isNaN($("input[name=basicSort]").val())){
+					<@ms.notify msg="自定义排序必须是数字" type="warning"/>
+					$("input[name=basicSort]").val(0);
+					//启用按钮
+					$("#saveUpdate").button('reset');
+					return;
+				}
+				$(this).request({url:actionUrl,data:dataMsg,loadingText:seeMsg,method:"post",type:"json",func:function(obj) {
+					//执行加载状态
+					$("#saveUpdate").button('loading');
+					if(obj.result){
+						<#if article.basicId !=0>
+		   					<@ms.notify msg="更新文章成功" type="success"/>
+			   			<#else>
+			   				<@ms.notify msg="保存文章成功" type="success"/>
+			   			</#if>
+			   			var columnType = ${columnType?default(0)};
+		   			    if(columnType == 1){
+		   			    	//更新并生成之后路径进行跳转
+					    	location.href=managerPath+"/cms/article/${categoryId?default(0)}/main.do";
+		   			    }else{
+		   			    	var dataId = obj.resultData;
+		   			    	if(dataId!=""){
+		   			    		location.href = "${managerPath}/cms/article/"+dataId+"/edit.do";
+		   			    	}
+		   			    };
+		   			    $("#saveUpdate").button('reset');
+					}else{
+						$('.ms-notifications').offset({top:43}).notify({
+					    	type:'warning',
+					    	message: { text:obj.resultMsg }
+					 	}).show();
+					}
+				}});
+			}
+		}else{
+			<@ms.notify msg="请选择文章所属栏目" type="warning"/>
+			//启用按钮
+			$("#saveUpdate").attr("disabled",false);
+		}
+		 //启用按钮
+		 $("#saveUpdate").button('reset');
+	     $("#saveUpdate").attr("disabled",false);
+	});	
+});
+
+//选择栏目后查询自定义模型
+function clickZtreeId(event,treeId,treeNode){
+	if(treeNode.columnType == 2){
+		<@ms.notify msg="不能选择单篇栏目" />
+		return false;
+	}
+	if(treeNode.isParent==true){
+		<@ms.notify msg="不能选择父级栏目" />
+		return false;
+	}
+	var url="${managerPath}/mdiy/contentModel/contentModelField/"+treeNode.categoryId+"/queryField.do";
+	var basicId="basicId=${article.basicId?c?default(0)}";
+	$(this).request({url:url,data:basicId,method:"get",func:function(data) {
+		$("#addFieldForm").html("");
+		$("#addFieldForm").html(data);
+	}});
+} 
+</script>

+ 163 - 0
src/main/webapp/WEB-INF/manager/cms/article/article_main.ftl

@@ -0,0 +1,163 @@
+<@ms.html5>
+	<@ms.nav title="文章列表"></@ms.nav>
+	<@ms.searchForm   name="searchForm" action="">
+			<#if articleTypeList?has_content>
+				<@ms.select label="文章属性" default="全部" value="a" name="articleType" id="forumSelect"  list=articleTypeList  listValue="dictLabel"   listKey="dictValue"    value="${articleType?default('')}"/>
+			<#else>
+				<@ms.select label="文章属性"     name="articleType" id="forumSelect" value="" list=["默认属性"]  />
+			</#if>
+			<@ms.text label="文章标题"  name="basicTitle" value="" title="请输入文章标题"  placeholder="请输入文章标题" />
+			<@ms.searchFormButton>
+				<@ms.queryButton id="submitSearch" />								
+			</@ms.searchFormButton>
+	</@ms.searchForm>
+	<div id="toolbar">
+		<@ms.panelNavBtnGroup>
+			<@shiro.hasPermission name="article:save"><@ms.panelNavBtnAdd title=""/></@shiro.hasPermission> 
+			<@shiro.hasPermission name="article:del"><@ms.panelNavBtnDel title=""/></@shiro.hasPermission> 
+		</@ms.panelNavBtnGroup>
+	</div>
+	<@ms.panel>
+		<table id="articleListTable"
+			data-show-refresh="true"
+	        data-show-columns="true"
+	        data-show-export="true"
+			data-method="post" 
+			data-detail-formatter="detailFormatter" 
+			data-pagination="true"
+			data-page-size="10"
+			data-side-pagination="server">
+		</table>
+	</@ms.panel>
+</@ms.html5>	
+<!--删除限时文章-->    
+<@ms.modal modalName="delete" title="删除文章">
+	  <@ms.modalBody>
+	  		确定要删除所选的文章吗?
+     </@ms.modalBody>
+	 <@ms.modalButton>
+ 		<@ms.button class="btn btn-danger rightDelete" value="确定"/>
+ 	</@ms.modalButton>
+</@ms.modal>			
+<script>
+	
+	
+	$(function(){
+		var search = $("form[name='searchForm']").serializeJSON();
+		var articleType = search.articleType; 
+		$("#articleListTable").bootstrapTable({
+		url:"${managerPath}/cms/article/${categoryId}/list.do?articleTypeStr="+articleType,
+		contentType : "application/x-www-form-urlencoded",
+		queryParamsType : "undefined",
+		toolbar: "#toolbar",
+	    columns: [{ checkbox: true}, {
+	        field: 'column.categoryTitle',
+	        title: '栏目名',
+	        width: 90,
+	        align: 'left'
+	    },{
+	        field: 'basicTitle',
+	        title: '文章标题',
+	        
+	        formatter: function (value, row, index){
+				<@shiro.hasPermission name="article:update">	        
+	        	var url='${managerPath}/cms/article/'+row.articleID+"/edit.do";
+	    		return "<a href="+url+" target='_self' >"+value+"</a>";
+	    		</@shiro.hasPermission> 
+	    		<@shiro.lacksPermission name="article:update">
+	    			return value;
+	    		</@shiro.lacksPermission> 
+	    		
+	    	}
+	    }, {
+	        field: 'articleAuthor',
+	        title: '作者',
+	        width: 100
+	    }, {
+	        field: 'basicSort',
+	        title: '排序',
+	        align: 'center',
+	        width: 50
+	    }, {
+	        field: 'basicHit',
+	        title: '点击',
+	        align: 'center',
+	        width: 50
+	    }, {
+	        field: 'basicDateTime',
+	        title: '发布时间',
+	        align: 'center',
+	        width: 150
+	    }]
+	});
+	//查询文章标题
+	$("#submitSearch").click(function(){
+		var search = $("form[name='searchForm']").serializeJSON();
+		var params = $('#articleListTable').bootstrapTable('getOptions');
+		params.queryParams = function(params) {  
+		 	$.extend(params,search);
+	        	return params;  
+			}  
+		$("#articleListTable").bootstrapTable('refresh', {query:$("form[name='searchForm']").serializeJSON()});
+	});
+	//添加文章
+	$("#addButton").click(function(){
+		if(${isParent}==true){
+			<@ms.notify msg="不能选择父级栏目" />
+			return false;
+		}
+		location.href = "${managerPath}/cms/article/add.do?categoryId=${categoryId?default(0)}&modelId=${Session.model_id_session?default(0)}&categoryTitle=${categoryTitle?default('')}"; 
+	});	
+	//点击重置按钮
+	$(".reset").click(function(){
+		$("input[name=basicTitle]").val("");
+	})
+	//多选删除
+	$("#delButton").click(function(){
+		//获取勾选的所在行的所有数据
+		var rows = $("#articleListTable").bootstrapTable("getSelections");
+		if(rows!=""){
+		//弹出modal窗体
+			$(".delete").modal();
+		}else{
+			<@ms.notify msg="请选择文章!" type="warning"/>
+		}
+	});
+	//删除多个文章
+	$(".rightDelete").click(function(){
+		var rows = $("#articleListTable").bootstrapTable("getSelections");
+		if(rows!=""){
+			$.ajax({
+				url:"${managerPath}/cms/article/delete.do",
+				type:'post',
+				dataType:'json',
+				data:JSON.stringify(rows),
+				contentType:'application/json',
+				success:function(msg) {
+					if (msg.result) {
+						<@ms.notify msg="删除成功!" type="success"/>
+						location.reload();
+					} else {
+						<@ms.notify msg="删除失败" type="fail"/>
+					}
+				}
+			});
+		}else{
+	    	<@ms.notify msg="请选择文章!" type="warning"/>
+	    }
+	});
+});
+</script>
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 57 - 0
src/main/webapp/WEB-INF/manager/cms/article/index.ftl

@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html lang="zh">
+ <head>
+<#include "/include/macro.ftl"/>
+<#include "/include/meta.ftl"/>
+</head>
+<body class="over-hide">
+<@ms.content>
+ 	<@ms.contentMenu>
+		 <!-- 树形模块菜单开始 -->
+		<#if listColumn?has_content>
+				<@ms.tree  treeId="inputTree" json="${listColumn?default('')}" addNodesName="全部"  jsonId="categoryId" jsonPid="categoryCategoryId" jsonName="categoryTitle"   showIcon="true" expandAll="true" getZtreeId="getZtreeId(event,treeId,treeNode);" />
+			<#else> 
+				<@ms.nodata content="暂无栏目"/>
+		</#if>
+		<!-- 树形模块菜单结束 -->
+	</@ms.contentMenu>
+	<@ms.contentBody width="85%" style="overflow-y: hidden;">
+		<@ms.contentPanel  style="margin:0;padding:0;overflow-y: hidden;">
+		<iframe src="${managerPath}/cms/article/0/main.do" style="width:100%;maring:0;padding:0;border:none;height:100%;background-image: url(${skin_manager_loadding});  background-repeat: no-repeat;  background-position: center;" id="listFrame" target="listFrame" ></iframe>
+		</@ms.contentPanel>
+	</@ms.contentBody>
+</@ms.content>
+<script>
+
+//树形结点
+function getZtreeId(event,treeId,treeNode){
+	if (treeNode.columnType==1) {
+		//父级栏目为true,子级栏目为false
+		var isParent = false;
+		if(treeNode.isParent == true){
+			 isParent = true;
+		}
+		$("#listFrame").attr("src","${managerPath}/cms/article/"+treeNode.categoryId+"/main.do?isParent="+isParent+"&categoryTitle="+encodeURIComponent(treeNode.categoryTitle));
+	} else if(treeNode.columnType==2){
+		//判断该单篇栏目是否存在文章
+		$.ajax({ 
+			type: "POST", 
+			url: "${managerPath}/cms/article/"+treeNode.categoryId+"/queryColumnArticle.do",
+			dataType:"json",
+			success: function(msg){
+				if (msg.result) {
+					$("#listFrame").attr("src","${managerPath}/cms/article/add.do?categoryId="+treeNode.categoryId+"&categoryTitle="+encodeURIComponent(treeNode.categoryTitle));
+				} else {
+					//如果该单篇栏目下存在文章则跳转到文章编辑页
+					$("#listFrame").attr("src","${managerPath}/cms/article/"+treeNode.categoryId+"/edit.do?categoryId="+treeNode.categoryId+"&categoryTitle="+encodeURIComponent(treeNode.categoryTitle));
+				}
+			},
+		});
+	} else if(treeNode.columnType=="" || treeNode.columnType == undefined){
+		$("#listFrame").attr("src","${managerPath}/cms/article/0/main.do"); 
+	}
+	
+}
+</script>
+</body>
+</html>

+ 2 - 0
src/main/webapp/WEB-INF/manager/cms/column/shiro-button.ftl

@@ -0,0 +1,2 @@
+<@shiro.hasPermission name="cms:column:save"><@ms.addButton id="addColumnBtn"/></@shiro.hasPermission>
+<@shiro.hasPermission name="cms:column:del"><@ms.delButton id="delColumnBtn"/></@shiro.hasPermission>

+ 7 - 0
src/main/webapp/WEB-INF/manager/cms/column/shiro-update.ftl

@@ -0,0 +1,7 @@
+<@shiro.hasPermission name="cms:column:update">
+var url = "${managerPath}/${model?default("")}/column/"+row.categoryId+"/edit.do?modelId=${Session.model_id_session?default(0)}&modelTitle=${Session.model_title_session?default('')}";
+return "<a href=" +url+ " target='_self'>" + value + "</a>";
+</@shiro.hasPermission>
+<@shiro.lacksPermission name="cms:column:update">
+return value;
+</@shiro.lacksPermission> 

+ 161 - 0
src/main/webapp/WEB-INF/manager/cms/generate/index.ftl

@@ -0,0 +1,161 @@
+<@ms.html5>
+	<@ms.nav title="静态化"></@ms.nav>
+	<@ms.panel>
+		<p class="alert alert-info" role="alert">
+			<span class="glyphicon glyphicon-pushpin text-lef "></span>
+			<a class="alert-link text-lef" style="margin-left: 12px;">
+        		更新主页,如果系统存在引导页面可以手动修改主页位置文件名,default.html引导页面index.html主页。
+			</a><br/>
+			<span class="glyphicon glyphicon-pushpin text-lef "></span>
+			<a class="alert-link text-lef" style="margin-left: 12px;">
+        		更新栏目列表,推荐使用指定栏目更新。系统提示“更新中...”请不要刷新页面或点击其他菜单。
+			</a><br/>
+			<span class="glyphicon glyphicon-pushpin text-lef "></span>
+			<a class="alert-link text-lef" style="margin-left: 12px;">
+            	根据时间与栏目类型生成文章
+			</a>
+		</p>		
+		<@ms.form name="generateIndex">
+			<@ms.formRow label="选择主页模板" width="300">
+					<select class="form-control" id="select_id"></select>
+					<input type="hidden" name="url"/>				
+			</@ms.formRow>
+			<@ms.text  id="position" label="选择主页位置	" width="300" value="index" placeholder="输入主页位置" name="position"  help="注:主页位置htm文件名一般为index.html或default.html"/>
+			<div class="form-group ms-form-group"><div class="col-sm-2"></div><div class="col-sm-9 ms-from-group-input ms-form-input">
+			<@shiro.hasPermission name="cms:generate:index">	  
+				<@ms.button class="btn btn-primary" id="updateIndex" value="生成主页" /> 	
+				<@ms.panelNavBtnSave title="" id="viewIndex" value="预览主页" />
+			</@shiro.hasPermission>
+			</div>
+			</div>
+		</@ms.form>
+		<!--选择更新的栏目-->
+		<@ms.form name="generateColumn">
+			<@ms.formRow label="选择要生成栏目" width="300">
+					<#if list?has_content>
+						<@ms.treeInput treeId="inputTree" json="${list?default('')}" jsonId="categoryId" jsonPid="categoryCategoryId" jsonName="categoryTitle" buttonText="选择更新的栏目" addNodesName="所有栏目" inputName="columnId" showIcon="true" expandAll="true" />
+					<#else>
+						<@ms.treeInput treeId="errorTree" buttonText="暂无数据" />
+					</#if>
+			</@ms.formRow>
+			<div class="form-group ms-form-group"><div class="col-sm-2"></div><div class="col-sm-9 ms-from-group-input ms-form-input">
+			<@shiro.hasPermission name="cms:generate:column">
+				<@ms.button class="btn btn-primary" id="updateColumn" value="生成栏目" />
+			</@shiro.hasPermission>
+			</div></div>
+		</@ms.form>
+		<@ms.form name="generateArticle">
+			<@ms.formRow label="文章栏目" width="300">
+        			<#if list?has_content>
+						<@ms.treeInput  treeId="inputTreee" json="${list?default('')}" jsonId="categoryId" jsonPid="categoryCategoryId" jsonName="categoryTitle" addNodesName="所有栏目" buttonText="选择更新的栏目" inputName="articleId"  showIcon="true" expandAll="true" />
+    				<#else> 
+						<@ms.treeInput  treeId="errorTree"  buttonText="暂无数据" />
+    				</#if>	
+    		</@ms.formRow>
+            <@ms.date name="dateTime" label="指定时间" single=true readonly="readonly" width="300" value="${now?string('yyyy-MM-dd')}" validation={"required":"true", "data-bv-notempty-message":"必填项目"} placeholder="点击该框选择时间段"  />
+			<div class="form-group ms-form-group"><div class="col-sm-2"></div><div class="col-sm-9 ms-from-group-input ms-form-input">
+			<@shiro.hasPermission name="cms:generate:article">
+				<@ms.button class="btn btn-primary" id="updateArticle" value="生成文章" />
+			</@shiro.hasPermission>
+			</div></div>
+		</@ms.form>	
+	</@ms.panel>
+</@ms.html5>	
+
+<!--点击进行按钮提交-->
+<script>
+	$(function(){
+		var URL="${managerPath}/template/queryTemplateFileForColumn.do";
+		var DATA = "";
+		$(this).request({url:URL,data:DATA,type:"json",method:"get",func:function(msg) {
+			if(msg.length==0){
+				$("#select_id").append("<option value='' >暂无文件</option>")
+			}
+			for(var i = 0;i<msg.length;i++){
+				$("#select_id").append("<option value="+msg[i]+">"+msg[i]+"</option>");
+				//如果存在index.html
+				if(msg[i]=="index.html" || msg[i]=="index.htm"){
+					$("#select_id").find("option[value='"+msg[i]+"']").attr("selected",true);
+				}
+			}
+		}});
+	})
+	
+	//点击一键更新主页时,进行主页更新
+	$("#updateIndex").click(function(){
+		//选择的主页模板名称和主页位置
+		var url = $("#select_id").val();
+		var position =$("input[name='position']").val();
+		//封装ajax请求参数
+		var URL="${managerPath}/cms/generate//generateIndex.do";
+		var DATA = "url="+url+"&position="+position;
+		$(this).html("更新中..").attr("disabled", "disabled");
+		$(this).request({url:URL,data:DATA,type:"json",method:"post",func:function(msg) {
+			$("#updateIndex").html("更新主页").removeAttr("disabled");
+			if(msg.result){
+				<@ms.notify msg="更新成功" type="success"/>
+			}else{
+				$('.ms-notifications').offset({top:43}).notify({
+			    	type:'warning',
+			    	message: { text:msg.resultMsg }
+			 	}).show();
+			}
+			$("#updateIndex").html("更新主页")
+		}});
+	});
+	//点击预览时,进行预览
+	$("#viewIndex").click(function(){
+		var position =$("input[name='position']").val();
+		window.open("${managerPath}/cms/generate/"+position+"/viewIndex.do");
+	});
+</script>
+
+<!--点击生成栏目按钮-->
+<script>
+	$("#updateColumn").click(function() {
+		var columnId = 0;
+		if($("input[name='columnId']").val() !="" && $("input[name='columnId']").val().length>0){
+			columnId = $("input[name='columnId']").val();
+		}
+		var URL="${managerPath}/cms/generate/"+columnId+"/genernateColumn.do";
+		$(this).html("更新中..").attr("disabled", "disabled");
+		$(this).request({url:URL,data:columnId,type:"json",method:"post",func:function(msg) {
+			$("#updateColumn").html("更新栏目").removeAttr("disabled");
+			//回调处理方式
+			if(msg.result){
+				<@ms.notify msg="更新成功" type="success"/>
+			}else{
+				$('.ms-notifications').offset({top:43}).notify({
+			    	type:'warning',
+			    	message: { text:msg.resultMsg }
+			 	}).show();
+			}
+		}});
+	});
+</script>
+
+<!--点击生成文章按钮-->
+<script>
+	$("#updateArticle").click(function() {
+		var articleId = 0;
+		if($("input[name='articleId']").val() !="" ){
+			articleId = $("input[name='articleId']").val();
+		}
+		var URL="${managerPath}/cms/generate/" + articleId + "/generateArticle.do";
+		var DATA = "dateTime=" + $("input[name='dateTime']").val();
+		$(this).html("更新中..").attr("disabled", "disabled");
+		
+		$(this).request({url:URL,data:DATA,type:"json",method:"post",func:function(msg) {
+			$("#updateArticle").html("更新文档").removeAttr("disabled");
+			//回调处理方式
+			if(msg.result){
+				<@ms.notify msg="更新成功" type="success"/>
+			}else{
+				$('.ms-notifications').offset({top:43}).notify({
+			    	type:'warning',
+			    	message: { text:msg.resultMsg }
+			 	}).show();
+			}
+		}});
+	});
+</script>

+ 26 - 0
src/main/webapp/WEB-INF/manager/main.ftl

@@ -0,0 +1,26 @@
+<!--主界面-->
+<!DOCTYPE html>
+<html lang="en">
+<head> 
+  <title>铭飞CMS</title> 
+  <meta content="IE=edge" http-equiv="X-UA-Compatible" /> 
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> 
+  <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> 
+<style>
+body{  height: 100%;}
+</style>
+</head>
+<body>
+<div style="
+    text-align: center;
+    color: #555;
+    background: #FCFCFC;
+    height: 300px;
+    padding-top: 200px;
+    vertical-align: middle;
+"><h2>欢迎使用铭飞产品</h2><p>技术交流加群:①242805203 ②231212174(满) ③221335098(满)  或到<a href="http://ms.mingsoft.net/mbbs/main.do" target="_blank"  style="
+    text-decoration: none;
+">官方论坛进行技术交流</a></p></div>
+</body>
+</html>