소스 검색

内部测试

guwd 4 년 전
부모
커밋
ee267f1360
30개의 변경된 파일4427개의 추가작업 그리고 0개의 파일을 삭제
  1. 22 0
      src/main/java/net/mingsoft/cms/action/BaseAction.java
  2. 330 0
      src/main/java/net/mingsoft/cms/action/CategoryAction.java
  3. 272 0
      src/main/java/net/mingsoft/cms/action/ContentAction.java
  4. 282 0
      src/main/java/net/mingsoft/cms/action/GeneraterAction.java
  5. 116 0
      src/main/java/net/mingsoft/cms/action/web/CategoryAction.java
  6. 140 0
      src/main/java/net/mingsoft/cms/action/web/ContentAction.java
  7. 594 0
      src/main/java/net/mingsoft/cms/action/web/MCmsAction.java
  8. 84 0
      src/main/java/net/mingsoft/cms/aop/ContentAop.java
  9. 28 0
      src/main/java/net/mingsoft/cms/bean/CategoryBean.java
  10. 73 0
      src/main/java/net/mingsoft/cms/bean/ContentBean.java
  11. 39 0
      src/main/java/net/mingsoft/cms/biz/ICategoryBiz.java
  12. 29 0
      src/main/java/net/mingsoft/cms/biz/IContentBiz.java
  13. 14 0
      src/main/java/net/mingsoft/cms/biz/IHistoryLogBiz.java
  14. 284 0
      src/main/java/net/mingsoft/cms/biz/impl/CategoryBizImpl.java
  15. 102 0
      src/main/java/net/mingsoft/cms/biz/impl/ContentBizImpl.java
  16. 50 0
      src/main/java/net/mingsoft/cms/biz/impl/HistoryLogBizImpl.java
  17. 12 0
      src/main/java/net/mingsoft/cms/constant/Const.java
  18. 70 0
      src/main/java/net/mingsoft/cms/constant/e/CategoryTypeEnum.java
  19. 25 0
      src/main/java/net/mingsoft/cms/dao/ICategoryDao.java
  20. 222 0
      src/main/java/net/mingsoft/cms/dao/ICategoryDao.xml
  21. 12 0
      src/main/java/net/mingsoft/cms/dao/ICmsHistoryLogDao.java
  22. 121 0
      src/main/java/net/mingsoft/cms/dao/ICmsHistoryLogDao.xml
  23. 45 0
      src/main/java/net/mingsoft/cms/dao/IContentDao.java
  24. 336 0
      src/main/java/net/mingsoft/cms/dao/IContentDao.xml
  25. 416 0
      src/main/java/net/mingsoft/cms/entity/CategoryEntity.java
  26. 261 0
      src/main/java/net/mingsoft/cms/entity/ContentEntity.java
  27. 84 0
      src/main/java/net/mingsoft/cms/entity/HistoryLogEntity.java
  28. 37 0
      src/main/java/net/mingsoft/cms/resources/resources_en_US.properties
  29. 37 0
      src/main/java/net/mingsoft/cms/resources/resources_zh_CN.properties
  30. 290 0
      src/main/java/net/mingsoft/cms/util/CmsParserUtil.java

+ 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 = getLocaleString(key,net.mingsoft.cms.constant.Const.RESOURCES);
+        }
+
+        return str;
+    }
+}

+ 330 - 0
src/main/java/net/mingsoft/cms/action/CategoryAction.java

@@ -0,0 +1,330 @@
+package net.mingsoft.cms.action;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import net.mingsoft.base.entity.BaseEntity;
+import net.mingsoft.base.entity.ResultData;
+import net.mingsoft.basic.annotation.LogAnn;
+import net.mingsoft.basic.bean.EUListBean;
+import net.mingsoft.basic.constant.e.BusinessTypeEnum;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.basic.util.PinYinUtil;
+import net.mingsoft.basic.util.StringUtil;
+import net.mingsoft.cms.biz.ICategoryBiz;
+import net.mingsoft.cms.entity.CategoryEntity;
+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.validation.BindingResult;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 分类管理控制层
+ * @author 铭飞开发团队
+ * 创建日期:2019-11-28 15:12:32<br/>
+ * 历史修订:<br/>
+ */
+@Api(value = "分类接口")
+@Controller("cmsCategoryAction")
+@RequestMapping("/${ms.manager.path}/cms/category")
+public class CategoryAction extends BaseAction {
+
+
+	/**
+	 * 注入分类业务层
+	 */
+	@Autowired
+	private ICategoryBiz categoryBiz;
+
+	/**
+	 * 返回主界面index
+	 */
+	@GetMapping("/index")
+	public String index(HttpServletResponse response,HttpServletRequest request){
+		return "/cms/category/index";
+	}
+
+	/**
+	 * 查询分类列表
+	 * @param category 分类实体
+	 */
+	@ApiOperation(value = "查询分类列表接口")
+	@ApiImplicitParams({
+    	@ApiImplicitParam(name = "categoryTitle", value = "栏目管理名称", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryId", value = "所属栏目", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryType", value = "栏目管理属性", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categorySort", value = "自定义顺序", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryListUrl", value = "列表模板", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryUrl", value = "内容模板", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryKeyword", value = "栏目管理关键字", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryDescrip", value = "栏目管理描述", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryImg", value = "缩略图", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryDiyUrl", value = "自定义链接", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "mdiyModelId", value = "栏目管理的内容模型id", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryDatetime", value = "类别发布时间", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "dictId", value = "字典对应编号", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryFlag", value = "栏目属性", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryPath", value = "栏目路径", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryParentId", value = "父类型编号", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "createBy", value = "创建人", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "createDate", value = "创建时间", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "updateBy", value = "修改人", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "updateDate", value = "修改时间", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "del", value = "删除标记", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "id", value = "编号", required =false,paramType="query"),
+    })
+	@RequestMapping("/list")
+	@ResponseBody
+	public ResultData list(@ModelAttribute @ApiIgnore CategoryEntity category, HttpServletResponse response, HttpServletRequest request, @ApiIgnore ModelMap model, BindingResult result) {
+		BasicUtil.startPage();
+		List categoryList = categoryBiz.query(category);
+		return ResultData.build().success(new EUListBean(categoryList,(int) BasicUtil.endPage(categoryList).getTotal()));
+	}
+
+	/**
+	 * 返回编辑界面category_form
+	 */
+	@GetMapping("/form")
+	public String form(@ModelAttribute CategoryEntity category, HttpServletResponse response, HttpServletRequest request, ModelMap model){
+		model.addAttribute("appId", BasicUtil.getApp().getAppId());
+		return "/cms/category/form";
+	}
+
+	/**
+	 * 获取分类
+	 * @param category 分类实体
+	 */
+	@ApiOperation(value = "获取分类列表接口")
+    @ApiImplicitParam(name = "id", value = "编号", required =true,paramType="query")
+	@GetMapping("/get")
+	@ResponseBody
+	public ResultData get(@ModelAttribute @ApiIgnore CategoryEntity category, HttpServletResponse response, HttpServletRequest request, @ApiIgnore ModelMap model){
+		if(category.getId()==null) {
+			return ResultData.build().error();
+		}
+		CategoryEntity _category = (CategoryEntity)categoryBiz.getById(category.getId());
+		return ResultData.build().success(_category);
+	}
+
+	@ApiOperation(value = "保存分类列表接口")
+	 @ApiImplicitParams({
+    	@ApiImplicitParam(name = "categoryTitle", value = "栏目管理名称", required =true,paramType="query"),
+		@ApiImplicitParam(name = "categoryId", value = "所属栏目", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryType", value = "栏目管理属性", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categorySort", value = "自定义顺序", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryListUrl", value = "列表模板", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryUrl", value = "内容模板", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryKeyword", value = "栏目管理关键字", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryDescrip", value = "栏目管理描述", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryImg", value = "缩略图", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryDiyUrl", value = "自定义链接", required =false,paramType="query"),
+		@ApiImplicitParam(name = "mdiyModelId", value = "栏目管理的内容模型id", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryDatetime", value = "类别发布时间", required =false,paramType="query"),
+		@ApiImplicitParam(name = "dictId", value = "字典对应编号", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryFlag", value = "栏目属性", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryPath", value = "栏目路径", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryParentId", value = "父类型编号", required =false,paramType="query"),
+		@ApiImplicitParam(name = "createBy", value = "创建人", required =false,paramType="query"),
+		@ApiImplicitParam(name = "createDate", value = "创建时间", required =false,paramType="query"),
+		@ApiImplicitParam(name = "updateBy", value = "修改人", required =false,paramType="query"),
+		@ApiImplicitParam(name = "updateDate", value = "修改时间", required =false,paramType="query"),
+		@ApiImplicitParam(name = "del", value = "删除标记", required =false,paramType="query"),
+		@ApiImplicitParam(name = "id", value = "编号", required =false,paramType="query"),
+	})
+
+	/**
+	* 保存分类
+	* @param category 分类实体
+	*/
+	@PostMapping("/save")
+	@ResponseBody
+	@LogAnn(title = "保存分类", businessType = BusinessTypeEnum.INSERT)
+	@RequiresPermissions("cms:category:save")
+	public ResultData save(@ModelAttribute @ApiIgnore CategoryEntity category, HttpServletResponse response, HttpServletRequest request) {
+		//验证栏目管理名称的值是否合法
+		if(StringUtil.isBlank(category.getCategoryTitle())){
+			return ResultData.build().error(getResString("err.empty", this.getResString("category.title")));
+		}
+		if(!StringUtil.checkLength(category.getCategoryTitle()+"", 1, 100)){
+			return ResultData.build().error(getResString("err.length", this.getResString("category.title"), "1", "100"));
+		}
+
+		if(!StringUtil.checkLength(category.getCategoryPath()+"", 1, 100)){
+			return ResultData.build().error(getResString("err.length", this.getResString("category.path"), "1", "100"));
+		}
+		if(!StringUtil.checkLength(category.getCategoryParentIds()+"", 1, 100)){
+			return ResultData.build().error(getResString("err.length", this.getResString("category.parent.id"), "1", "100"));
+		}
+		//判断拼音是否重复
+		if(StrUtil.isNotBlank(category.getCategoryPinyin())) {
+			CategoryEntity _category = new CategoryEntity();
+			_category.setCategoryPinyin(category.getCategoryPinyin());
+			List<CategoryEntity> query = categoryBiz.query(_category);
+			if (query.size() > 0) {
+				return ResultData.build().error(getResString("err.exist", this.getResString("category.pinyin")));
+			}
+		}
+
+		categoryBiz.saveEntity(category);
+		return ResultData.build().success(category);
+	}
+
+	/**
+	 * @param categorys 分类实体
+	 */
+	@ApiOperation(value = "批量删除分类列表接口")
+	@PostMapping("/delete")
+	@ResponseBody
+	@LogAnn(title = "删除分类", businessType = BusinessTypeEnum.DELETE)
+	@RequiresPermissions("cms:category:del")
+	public ResultData delete(@RequestBody List<CategoryEntity> categorys, HttpServletResponse response, HttpServletRequest request) {
+		for(int i = 0;i<categorys.size();i++){
+			categoryBiz.delete(categorys.get(i).getId());
+		}
+		return ResultData.build().success();
+	}
+	/**
+	*	更新分类列表
+	* @param category 分类实体
+	*/
+	 @ApiOperation(value = "更新分类列表接口")
+	 @ApiImplicitParams({
+	    @ApiImplicitParam(name = "id", value = "编号", required =true,paramType="query"),
+    	@ApiImplicitParam(name = "categoryTitle", value = "栏目管理名称", required =true,paramType="query"),
+		@ApiImplicitParam(name = "categoryId", value = "所属栏目", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryType", value = "栏目管理属性", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categorySort", value = "自定义顺序", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryListUrl", value = "列表模板", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryUrl", value = "内容模板", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryKeyword", value = "栏目管理关键字", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryDescrip", value = "栏目管理描述", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryImg", value = "缩略图", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryDiyUrl", value = "自定义链接", required =false,paramType="query"),
+		@ApiImplicitParam(name = "mdiyModelId", value = "栏目管理的内容模型id", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryDatetime", value = "类别发布时间", required =false,paramType="query"),
+		@ApiImplicitParam(name = "dictId", value = "字典对应编号", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryFlag", value = "栏目属性", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryPath", value = "栏目路径", required =false,paramType="query"),
+		@ApiImplicitParam(name = "categoryParentId", value = "父类型编号", required =false,paramType="query"),
+		@ApiImplicitParam(name = "createBy", value = "创建人", required =false,paramType="query"),
+		@ApiImplicitParam(name = "createDate", value = "创建时间", required =false,paramType="query"),
+		@ApiImplicitParam(name = "updateBy", value = "修改人", required =false,paramType="query"),
+		@ApiImplicitParam(name = "updateDate", value = "修改时间", required =false,paramType="query"),
+		@ApiImplicitParam(name = "del", value = "删除标记", required =false,paramType="query"),
+		@ApiImplicitParam(name = "id", value = "编号", required =false,paramType="query"),
+	})
+	@PostMapping("/update")
+	@ResponseBody
+	@LogAnn(title = "更新分类", businessType = BusinessTypeEnum.UPDATE)
+	@RequiresPermissions("cms:category:update")
+	public ResultData update(@ModelAttribute @ApiIgnore CategoryEntity category, HttpServletResponse response,
+                             HttpServletRequest request) {
+		//验证栏目管理名称的值是否合法
+		if(StringUtil.isBlank(category.getCategoryTitle())){
+			return ResultData.build().error(getResString("err.empty", this.getResString("category.title")));
+		}
+		if(!StringUtil.checkLength(category.getCategoryTitle()+"", 1, 100)){
+			return ResultData.build().error(getResString("err.length", this.getResString("category.title"), "1", "100"));
+		}
+
+		if(!StringUtil.checkLength(category.getCategoryPath()+"", 0, 100)){
+			return ResultData.build().error(getResString("err.length", this.getResString("category.path"), "1", "100"));
+		}
+		if(!StringUtil.checkLength(category.getCategoryParentIds()+"", 0, 100)){
+			return ResultData.build().error(getResString("err.length", this.getResString("category.parent.id"), "1", "100"));
+		}
+		 //判断拼音是否重复并且是否和原拼音相同
+		 if(StrUtil.isNotBlank(category.getCategoryPinyin()) && !categoryBiz.getById(category.getId()).getCategoryPinyin().equals(category.getCategoryPinyin())) {
+			 CategoryEntity _category = new CategoryEntity();
+			 _category.setCategoryPinyin(category.getCategoryPinyin());
+			 List<CategoryEntity> query = categoryBiz.query(_category);
+			 if (query.size() > 0) {
+				 return ResultData.build().error(getResString("err.exist", this.getResString("category.pinyin")));
+			 }
+		 }
+		 String pingYin = PinYinUtil.getPingYin(category.getCategoryTitle());
+		 //如果用户填写了拼音则使用用户填写的
+		 if (StrUtil.isNotBlank(category.getCategoryPinyin())) {
+		 	pingYin = category.getCategoryPinyin();
+		 }
+		 CategoryEntity categoryEntity=new CategoryEntity();
+		 categoryEntity.setCategoryPinyin(pingYin);
+		 CategoryEntity categoryBizEntity = (CategoryEntity)categoryBiz.getEntity(categoryEntity);
+		 category.setCategoryPinyin(pingYin);
+		 //如果存在此拼音栏目则拼接上id
+		 if(categoryBizEntity!=null&&!categoryBizEntity.getId().equals(category.getId())){
+			 category.setCategoryPinyin(pingYin+category.getId());
+		 }
+		//判断是否选择子级为所属栏目
+		 CategoryEntity _category = new CategoryEntity();
+		 _category.setCategoryParentIds(category.getId());
+		 List<CategoryEntity> categoryList = categoryBiz.queryChilds(_category);
+		 for(CategoryEntity item:categoryList){
+			 if(item.getId().equals(category.getCategoryId())){
+				 return ResultData.build().error(getResString("cannot.select.child"));
+			 }
+		 }
+		categoryBiz.updateEntity(category);
+		return ResultData.build().success(category);
+	}
+
+	@ApiOperation(value = "验证拼音")
+	@GetMapping("/verifyPingYin")
+	@ResponseBody
+	public ResultData verifyPingYin(@ModelAttribute @ApiIgnore CategoryEntity category, HttpServletResponse response, HttpServletRequest request, @ApiIgnore ModelMap model){
+	 	int count = categoryBiz.count(Wrappers.<CategoryEntity>lambdaQuery()
+				.ne(StrUtil.isNotBlank(category.getId()), CategoryEntity::getId, category.getId())
+				.eq(CategoryEntity::getCategoryPinyin, category.getCategoryPinyin()));
+
+		if(count>0){
+			return ResultData.build().error("存在相同拼音的栏目");
+		}
+		return ResultData.build().success();
+	}
+
+	@ApiOperation(value = "批量更新模版")
+	@GetMapping("/updateTemplate")
+	@ResponseBody
+	@RequiresPermissions("cms:category:update")
+	public ResultData updateTemplate(@ModelAttribute @ApiIgnore CategoryEntity category){
+		if (category ==null || StringUtils.isEmpty(category.getId())) {
+			return ResultData.build().error(getResString("err.error", this.getResString("id")));
+		}
+		category = categoryBiz.getById(category.getId());
+		category.setCategoryParentIds(null);
+		List<CategoryEntity> childs = categoryBiz.queryChilds(category);
+		//更新与父节点相同类型的子栏目的模板内容
+		for (int i =0; i < childs.size(); i++) {
+			if (childs.get(i).getCategoryType().equals(category.getCategoryType())) {
+				childs.get(i).setCategoryUrl(category.getCategoryUrl());
+				childs.get(i).setCategoryListUrl(category.getCategoryListUrl());
+				categoryBiz.updateEntity(childs.get(i));
+			}
+		}
+		return ResultData.build().success();
+	}
+
+	@ApiOperation(value = "复制栏目")
+	@GetMapping("/copyCategory")
+	@ResponseBody
+	@RequiresPermissions("cms:category:save")
+	public ResultData copyCategory(@ModelAttribute @ApiIgnore CategoryEntity category){
+		if (category == null || StringUtils.isEmpty(category.getId())) {
+			return ResultData.build().error(getResString("err.error", this.getResString("id")));
+		}
+		categoryBiz.copyCategory(category);
+		return ResultData.build().success();
+	}
+
+}

+ 272 - 0
src/main/java/net/mingsoft/cms/action/ContentAction.java

@@ -0,0 +1,272 @@
+package net.mingsoft.cms.action;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import net.mingsoft.base.entity.ResultData;
+import net.mingsoft.basic.annotation.LogAnn;
+import net.mingsoft.basic.bean.EUListBean;
+import net.mingsoft.basic.constant.e.BusinessTypeEnum;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.basic.util.StringUtil;
+import net.mingsoft.cms.biz.IContentBiz;
+import net.mingsoft.cms.entity.ContentEntity;
+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.validation.BindingResult;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 文章管理控制层
+ * @author 铭飞开发团队
+ * 创建日期:2019-11-28 15:12:32<br/>
+ * 历史修订:<br/>
+ */
+@Api(value = "文章接口")
+@Controller("cmsContentAction")
+@RequestMapping("/${ms.manager.path}/cms/content")
+public class ContentAction extends BaseAction {
+	
+	
+	/**
+	 * 注入文章业务层
+	 */	
+	@Autowired
+	private IContentBiz contentBiz;
+
+	/**
+	 * 返回主界面index
+	 */
+	@GetMapping("/index")
+	public String index(HttpServletResponse response,HttpServletRequest request){
+		return "/cms/content/index";
+	}
+	/**
+	 * 返回主界面main
+	 */
+	@GetMapping("/main")
+	public String main(HttpServletResponse response,HttpServletRequest request){
+		return "/cms/content/main";
+	}
+
+	/**
+	 * 查询文章列表
+	 * @param content 文章实体
+	 */
+	@ApiOperation(value = "查询文章列表接口")
+	@ApiImplicitParams({
+    	@ApiImplicitParam(name = "contentTitle", value = "文章标题", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryId", value = "所属栏目", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentType", value = "文章类型", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentDisplay", value = "是否显示", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentAuthor", value = "文章作者", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentSource", value = "文章来源", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentDatetime", value = "发布时间", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentSort", value = "自定义顺序", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentImg", value = "文章缩略图", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentDescription", value = "描述", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentKeyword", value = "关键字", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentDetails", value = "文章内容", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentUrl", value = "文章跳转链接地址", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "appid", value = "文章管理的应用id", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "createBy", value = "创建人", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "createDate", value = "创建时间", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "updateBy", value = "修改人", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "updateDate", value = "修改时间", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "del", value = "删除标记", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "id", value = "编号", required =false,paramType="query"),
+    })
+	@RequestMapping("/list")
+	@ResponseBody
+	public ResultData list(@ModelAttribute @ApiIgnore ContentEntity content, HttpServletResponse response, HttpServletRequest request, @ApiIgnore ModelMap model, BindingResult result) {
+		BasicUtil.startPage();
+		List contentList = contentBiz.query(content);
+		return ResultData.build().success(new EUListBean(contentList,(int) BasicUtil.endPage(contentList).getTotal()));
+	}
+	
+	/**
+	 * 返回编辑界面content_form
+	 */
+	@GetMapping("/form")
+	public String form(@ModelAttribute ContentEntity content, HttpServletResponse response, HttpServletRequest request, ModelMap model){
+		model.addAttribute("appId", BasicUtil.getApp().getAppId());
+		return "/cms/content/form";
+	}
+
+	/**
+	 * 获取文章
+	 * @param content 文章实体
+	 */
+	@ApiOperation(value = "获取文章列表接口")
+    @ApiImplicitParam(name = "id", value = "编号", required =true,paramType="query")
+	@GetMapping("/get")
+	@ResponseBody
+	public ResultData get(@ModelAttribute @ApiIgnore ContentEntity content, HttpServletResponse response, HttpServletRequest request, @ApiIgnore ModelMap model){
+		if(content.getId()==null) {
+			return ResultData.build().error();
+		}
+		ContentEntity _content = contentBiz.getById(content.getId());
+		return ResultData.build().success(_content);
+	}
+	/**
+	 * 获取文章
+	 * @param content 文章实体
+	 */
+	@ApiOperation(value = "根据封面获取文章列表接口")
+    @ApiImplicitParam(name = "categoryId", value = "分类编号", required =true,paramType="query")
+	@GetMapping("/getFromFengMian")
+	@ResponseBody
+	public ResultData getFromFengMian(@ModelAttribute @ApiIgnore ContentEntity content){
+		if(content.getCategoryId() == null) {
+			return ResultData.build().error();
+		}
+		List<ContentEntity> list = contentBiz.lambdaQuery().eq(ContentEntity::getCategoryId, content.getCategoryId()).list();
+		if (list.size() > 1) {
+			LOG.error("获取封面文章异常");
+		}
+		return ResultData.build().success(list.size() > 0 ? list.get(0) : null);
+	}
+	
+	@ApiOperation(value = "保存文章列表接口")
+	 @ApiImplicitParams({
+    	@ApiImplicitParam(name = "contentTitle", value = "文章标题", required =true,paramType="query"),
+		@ApiImplicitParam(name = "categoryId", value = "所属栏目", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentType", value = "文章类型", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentDisplay", value = "是否显示", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentAuthor", value = "文章作者", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentSource", value = "文章来源", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentDatetime", value = "发布时间", required =true,paramType="query"),
+		@ApiImplicitParam(name = "contentSort", value = "自定义顺序", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentImg", value = "文章缩略图", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentDescription", value = "描述", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentKeyword", value = "关键字", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentDetails", value = "文章内容", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentUrl", value = "文章跳转链接地址", required =false,paramType="query"),
+		@ApiImplicitParam(name = "appid", value = "文章管理的应用id", required =false,paramType="query"),
+		@ApiImplicitParam(name = "createBy", value = "创建人", required =false,paramType="query"),
+		@ApiImplicitParam(name = "createDate", value = "创建时间", required =false,paramType="query"),
+		@ApiImplicitParam(name = "updateBy", value = "修改人", required =false,paramType="query"),
+		@ApiImplicitParam(name = "updateDate", value = "修改时间", required =false,paramType="query"),
+		@ApiImplicitParam(name = "del", value = "删除标记", required =false,paramType="query"),
+		@ApiImplicitParam(name = "id", value = "编号", required =false,paramType="query"),
+	})
+
+	/**
+	* 保存文章
+	* @param content 文章实体
+	*/
+	@PostMapping("/save")
+	@ResponseBody
+	@LogAnn(title = "保存文章", businessType = BusinessTypeEnum.INSERT)
+	@RequiresPermissions("cms:content:save")
+	public ResultData save(@ModelAttribute @ApiIgnore ContentEntity content, HttpServletResponse response, HttpServletRequest request) {
+		//验证文章标题的值是否合法
+		if(StringUtil.isBlank(content.getContentTitle())){
+			return ResultData.build().error(getResString("err.empty", this.getResString("content.title")));
+		}
+		if(!StringUtil.checkLength(content.getContentTitle()+"", 0, 200)){
+			return ResultData.build().error(getResString("err.length", this.getResString("content.title"), "0", "200"));
+		}
+		if(!StringUtil.checkLength(content.getContentAuthor()+"", 0, 200)){
+			return ResultData.build().error(getResString("err.length", this.getResString("content.author"), "0", "200"));
+		}
+		if(!StringUtil.checkLength(content.getContentSource()+"", 0, 200)){
+			return ResultData.build().error(getResString("err.length", this.getResString("content.source"), "0", "200"));
+		}
+		//验证发布时间的值是否合法
+		if(StringUtil.isBlank(content.getContentDatetime())){
+			return ResultData.build().error(getResString("err.empty", this.getResString("content.datetime")));
+		}
+		if(!StringUtil.checkLength(content.getContentUrl()+"", 0, 200)){
+			return ResultData.build().error(getResString("err.length", this.getResString("content.url"), "0", "200"));
+		}
+		contentBiz.save(content);
+		return ResultData.build().success(content);
+	}
+	
+	/**
+	 * @param contents 文章实体
+	 */
+	@ApiOperation(value = "批量删除文章列表接口")
+	@PostMapping("/delete")
+	@ResponseBody
+	@LogAnn(title = "删除文章", businessType = BusinessTypeEnum.DELETE)
+	@RequiresPermissions("cms:content:del")
+	public ResultData delete(@RequestBody List<ContentEntity> contents, HttpServletResponse response, HttpServletRequest request) {
+		List<String> ids = new ArrayList<>();
+		for(int i = 0;i<contents.size();i++){
+			ids.add(contents.get(i).getId());
+		}
+		contentBiz.removeByIds(ids);
+		return ResultData.build().success();
+	}
+	/**
+	*	更新文章列表
+	* @param content 文章实体
+	*/
+	 @ApiOperation(value = "更新文章列表接口")
+	 @ApiImplicitParams({
+	    @ApiImplicitParam(name = "id", value = "编号", required =true,paramType="query"),
+    	@ApiImplicitParam(name = "contentTitle", value = "文章标题", required =true,paramType="query"),
+		@ApiImplicitParam(name = "categoryId", value = "所属栏目", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentType", value = "文章类型", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentDisplay", value = "是否显示", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentAuthor", value = "文章作者", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentSource", value = "文章来源", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentDatetime", value = "发布时间", required =true,paramType="query"),
+		@ApiImplicitParam(name = "contentSort", value = "自定义顺序", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentImg", value = "文章缩略图", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentDescription", value = "描述", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentKeyword", value = "关键字", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentDetails", value = "文章内容", required =false,paramType="query"),
+		@ApiImplicitParam(name = "contentUrl", value = "文章跳转链接地址", required =false,paramType="query"),
+		@ApiImplicitParam(name = "appid", value = "文章管理的应用id", required =false,paramType="query"),
+		@ApiImplicitParam(name = "createBy", value = "创建人", required =false,paramType="query"),
+		@ApiImplicitParam(name = "createDate", value = "创建时间", required =false,paramType="query"),
+		@ApiImplicitParam(name = "updateBy", value = "修改人", required =false,paramType="query"),
+		@ApiImplicitParam(name = "updateDate", value = "修改时间", required =false,paramType="query"),
+		@ApiImplicitParam(name = "del", value = "删除标记", required =false,paramType="query"),
+		@ApiImplicitParam(name = "id", value = "编号", required =false,paramType="query"),
+	})
+	@PostMapping("/update")
+	@ResponseBody
+	@LogAnn(title = "更新文章", businessType = BusinessTypeEnum.UPDATE)
+	@RequiresPermissions("cms:content:update")
+	public ResultData update(@ModelAttribute @ApiIgnore ContentEntity content, HttpServletResponse response,
+                             HttpServletRequest request) {
+		//验证文章标题的值是否合法			
+		if(StringUtil.isBlank(content.getContentTitle())){
+			return ResultData.build().error(getResString("err.empty", this.getResString("content.title")));
+		}
+		if(!StringUtil.checkLength(content.getContentTitle()+"", 0, 200)){
+			return ResultData.build().error(getResString("err.length", this.getResString("content.title"), "0", "200"));
+		}
+		if(!StringUtil.checkLength(content.getContentAuthor()+"", 0, 200)){
+			return ResultData.build().error(getResString("err.length", this.getResString("content.author"), "0", "200"));
+		}
+		if(!StringUtil.checkLength(content.getContentSource()+"", 0, 200)){
+			return ResultData.build().error(getResString("err.length", this.getResString("content.source"), "0", "200"));
+		}
+		//验证发布时间的值是否合法			
+		if(StringUtil.isBlank(content.getContentDatetime())){
+			return ResultData.build().error(getResString("err.empty", this.getResString("content.datetime")));
+		}
+		if(!StringUtil.checkLength(content.getContentUrl()+"", 0, 200)){
+			return ResultData.build().error(getResString("err.length", this.getResString("content.url"), "0", "200"));
+		}
+		contentBiz.updateEntity(content);
+		return ResultData.build().success(content);
+	}
+
+
+		
+}

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

@@ -0,0 +1,282 @@
+/**
+ * The MIT License (MIT) * Copyright (c) 2016 铭飞科技(mingsoft.net)
+ * <p>
+ * 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:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ * <p>
+ * 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 cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.bean.copier.CopyOptions;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import net.mingsoft.base.entity.ResultData;
+import net.mingsoft.basic.annotation.LogAnn;
+import net.mingsoft.basic.biz.IModelBiz;
+import net.mingsoft.basic.constant.e.BusinessTypeEnum;
+import net.mingsoft.basic.entity.AppEntity;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.cms.bean.CategoryBean;
+import net.mingsoft.cms.bean.ContentBean;
+import net.mingsoft.cms.biz.ICategoryBiz;
+import net.mingsoft.cms.biz.IContentBiz;
+import net.mingsoft.cms.constant.e.CategoryTypeEnum;
+import net.mingsoft.cms.entity.CategoryEntity;
+import net.mingsoft.cms.util.CmsParserUtil;
+import net.mingsoft.mdiy.bean.PageBean;
+import net.mingsoft.mdiy.util.ParserUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+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 javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @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 {
+
+    /*
+     * log4j日志记录
+     */
+    protected final Logger LOG = LoggerFactory.getLogger(this.getClass());
+
+    /**
+     * 文章管理业务层
+     */
+    @Autowired
+    private IContentBiz contentBiz;
+
+    /**
+     * 栏目管理业务层
+     */
+    @Autowired
+    private ICategoryBiz categoryBiz;
+
+    /**
+     * 模块管理业务层
+     */
+    @Autowired
+    private IModelBiz modelBiz;
+
+    @Value("${ms.manager.path}")
+    private String managerPath;
+
+    @Value("${ms.diy.html-dir:html}")
+    private String htmlDir;
+
+    /**
+     * /**
+     * 更新主页
+     *
+     * @return
+     */
+    @RequestMapping("/index")
+    public String index(HttpServletRequest request, ModelMap model) {
+        return "/cms/generate/index";
+    }
+
+    /**
+     * 生成主页
+     *
+     * @param request
+     * @param response
+     */
+    @RequestMapping("/generateIndex")
+    @RequiresPermissions("cms:generate:index")
+    @LogAnn(title = "生成主页", businessType = BusinessTypeEnum.UPDATE)
+    @ResponseBody
+    public ResultData generateIndex(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        // 模版文件名称
+        String tmpFileName = request.getParameter("url");
+        // 生成后的文件名称
+        String generateFileName = request.getParameter("position");
+
+        // 获取文件所在路径 首先判断用户输入的模版文件是否存在
+        if (!FileUtil.exist(ParserUtil.buildTempletPath())) {
+            return ResultData.build().error(getResString("templet.file"));
+        } else {
+
+            CmsParserUtil.generate(tmpFileName, generateFileName,htmlDir);
+            return ResultData.build().success();
+        }
+    }
+
+
+    /**
+     * 生成列表的静态页面
+     *
+     * @param request
+     * @param response
+     * @param categoryId
+     */
+    @RequestMapping("/{categoryId}/genernateColumn")
+    @LogAnn(title = "生成栏目", businessType = BusinessTypeEnum.UPDATE)
+    @RequiresPermissions("cms:generate:column")
+    @ResponseBody
+    public ResultData genernateColumn(HttpServletRequest request, HttpServletResponse response, @PathVariable String categoryId) throws IOException {
+        // 获取站点id
+        AppEntity app = BasicUtil.getApp();
+
+        //栏目列表
+        List<CategoryEntity> columns = new ArrayList<CategoryEntity>();
+
+        if ("0".equals(categoryId)) {// 0更新所有栏目
+            CategoryEntity categoryEntity = new CategoryEntity();
+            columns = categoryBiz.query(categoryEntity);
+        } else { //选择栏目更新
+            CategoryEntity categoryEntity = new CategoryEntity();
+            categoryEntity.setId(categoryId);
+            columns = categoryBiz.queryChilds(categoryEntity);
+        }
+
+        //文章列表
+        List<CategoryBean> articleIdList = null;
+
+        // 获取栏目列表模版
+        for (CategoryEntity column : columns) {
+
+            ContentBean contentBean = new ContentBean();
+            contentBean.setCategoryId(column.getId());
+
+            articleIdList = contentBiz.queryIdsByCategoryIdForParser(contentBean);
+            // 判断列表类型
+            switch (CategoryTypeEnum.get(column.getCategoryType())) {
+                //TODO 暂时先用字符串代替
+                case LIST: // 列表
+
+                    // 判断模板文件是否存在
+                    if (!FileUtil.exist(ParserUtil.buildTempletPath(column.getCategoryListUrl()))) {
+                        LOG.error("模板不存在:{}", column.getCategoryUrl());
+                        continue;
+                    }
+
+                    CmsParserUtil.generateList(column, articleIdList.size(),htmlDir);
+                    break;
+                case COVER:// 单页
+                    if (articleIdList.size() == 0) {
+                        CategoryBean columnArticleIdBean = new CategoryBean();
+                        CopyOptions copyOptions = CopyOptions.create();
+                        copyOptions.setIgnoreError(true);
+                        BeanUtil.copyProperties(column, columnArticleIdBean, copyOptions);
+                        articleIdList.add(columnArticleIdBean);
+                    }
+                    CmsParserUtil.generateBasic(articleIdList,htmlDir);
+                    break;
+            }
+        }
+
+        return ResultData.build().success();
+    }
+
+    /**
+     * 根据栏目id更新所有的文章
+     *
+     * @param request
+     * @param response
+     * @param columnId
+     */
+    @RequestMapping("/{columnId}/generateArticle")
+    @RequiresPermissions("cms:generate:article")
+    @LogAnn(title = "生成文章", businessType = BusinessTypeEnum.UPDATE)
+    @ResponseBody
+    public ResultData generateArticle(HttpServletRequest request, HttpServletResponse response, @PathVariable String columnId) throws IOException {
+        String dateTime = request.getParameter("dateTime");
+        // 网站风格物理路径
+        List<CategoryBean> articleIdList = null;
+        List<CategoryEntity> categoryList = new ArrayList<CategoryEntity>();
+        ContentBean contentBean = new ContentBean();
+        contentBean.setBeginTime(dateTime);
+
+        // 生成所有栏目的文章
+        if ("0".equals(columnId)) {
+            categoryList = categoryBiz.list(Wrappers.<CategoryEntity>lambdaQuery()
+                    .isNull(CategoryEntity::getCategoryParentIds));
+        } else {
+            CategoryEntity category = (CategoryEntity) categoryBiz.getById(columnId);
+            categoryList.add(category);
+        }
+
+        for (CategoryEntity category : categoryList) {
+            contentBean.setCategoryId(category.getId());
+            //将文章列表标签中的中的参数
+            articleIdList = contentBiz.queryIdsByCategoryIdForParser(contentBean);
+            // 分类是列表
+            if (category.getCategoryType().equals(CategoryTypeEnum.LIST.toString())) {
+                // 判断模板文件是否存在
+                if (!FileUtil.exist(ParserUtil.buildTempletPath(category.getCategoryListUrl())) || StringUtils.isEmpty(category.getCategoryListUrl())) {
+                    LOG.error("模板不存在:{}", category.getCategoryUrl());
+                    continue;
+                }
+            } else if (category.getCategoryType().equals(CategoryTypeEnum.COVER.toString())) {
+                CategoryBean columnArticleIdBean = new CategoryBean();
+                CopyOptions copyOptions = CopyOptions.create();
+                copyOptions.setIgnoreError(true);
+                BeanUtil.copyProperties(category, columnArticleIdBean, copyOptions);
+                articleIdList.add(columnArticleIdBean);
+            }
+            // 有符合条件的就更新
+            if (articleIdList.size() > 0) {
+                CmsParserUtil.generateBasic(articleIdList,htmlDir);
+            }
+        }
+
+
+        return ResultData.build().success();
+    }
+
+
+    /**
+     * 用户预览主页
+     *
+     * @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 + htmlDir+ File.separator + app.getAppDir()
+                + File.separator + position + ParserUtil.HTML_SUFFIX;
+        return "redirect:" + indexPosition;
+    }
+}

+ 116 - 0
src/main/java/net/mingsoft/cms/action/web/CategoryAction.java

@@ -0,0 +1,116 @@
+package net.mingsoft.cms.action.web;
+
+import java.util.List;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.alibaba.fastjson.JSON;
+import net.mingsoft.base.entity.ResultData;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.validation.BindingResult;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.ui.ModelMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import net.mingsoft.cms.biz.ICategoryBiz;
+import net.mingsoft.cms.entity.CategoryEntity;
+import net.mingsoft.base.util.JSONObject;
+import net.mingsoft.base.entity.BaseEntity;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.basic.util.StringUtil;
+import net.mingsoft.base.filter.DateValueFilter;
+import net.mingsoft.base.filter.DoubleValueFilter;
+import net.mingsoft.basic.bean.EUListBean;
+import net.mingsoft.basic.annotation.LogAnn;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import springfox.documentation.annotations.ApiIgnore;
+/**
+ * 分类管理控制层
+ * @author 铭飞开发团队
+ * 创建日期:2019-11-28 15:12:32<br/>
+ * 历史修订:<br/>
+ */
+@Api(value = "分类接口")
+@Controller("WebcmsCategoryAction")
+@RequestMapping("/cms/category")
+public class CategoryAction extends net.mingsoft.cms.action.BaseAction{
+	
+	
+	/**
+	 * 注入分类业务层
+	 */	
+	@Autowired
+	private ICategoryBiz categoryBiz;
+
+	/**
+	 * 查询分类列表
+	 * @param category 分类实体
+	 */
+	@ApiOperation(value = "查询分类列表接口")
+	@ApiImplicitParams({
+    	@ApiImplicitParam(name = "categoryTitle", value = "栏目管理名称", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryId", value = "所属栏目", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryType", value = "栏目管理属性", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categorySort", value = "自定义顺序", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryListUrl", value = "列表模板", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryUrl", value = "内容模板", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryKeyword", value = "栏目管理关键字", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryDescrip", value = "栏目管理描述", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryImg", value = "缩略图", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryDiyUrl", value = "自定义链接", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "mdiyModelId", value = "栏目管理的内容模型id", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryDatetime", value = "类别发布时间", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "dictId", value = "字典对应编号", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryFlag", value = "栏目属性", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryPath", value = "栏目路径", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryParentId", value = "父类型编号", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "createBy", value = "创建人", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "createDate", value = "创建时间", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "updateBy", value = "修改人", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "updateDate", value = "修改时间", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "del", value = "删除标记", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "id", value = "编号", required =false,paramType="query"),
+    })
+	@RequestMapping("/list")
+	@ResponseBody
+	public ResultData list(@ModelAttribute @ApiIgnore CategoryEntity category,HttpServletResponse response, HttpServletRequest request,@ApiIgnore ModelMap model,BindingResult result) {
+		BasicUtil.startPage();
+		List categoryList = categoryBiz.query(category);
+		return ResultData.build().success(new EUListBean(categoryList,(int)BasicUtil.endPage(categoryList).getTotal()));
+	}
+	
+
+	/**
+	 * 获取分类
+	 * @param category 分类实体
+	 */
+	@ApiOperation(value = "获取分类列表接口")
+    @ApiImplicitParam(name = "id", value = "编号", required =true,paramType="query")
+	@GetMapping("/get")
+	@ResponseBody
+	public ResultData get(@ModelAttribute @ApiIgnore CategoryEntity category,HttpServletResponse response, HttpServletRequest request,@ApiIgnore ModelMap model){
+		if(category.getId()==null) {
+			return ResultData.build().error();
+		}
+		CategoryEntity _category = (CategoryEntity)categoryBiz.getEntity(Integer.parseInt(category.getId()));
+		return ResultData.build().success(_category);
+	}
+
+}

+ 140 - 0
src/main/java/net/mingsoft/cms/action/web/ContentAction.java

@@ -0,0 +1,140 @@
+package net.mingsoft.cms.action.web;
+
+import cn.hutool.core.util.ObjectUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import net.mingsoft.base.entity.ResultData;
+import net.mingsoft.basic.bean.EUListBean;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.cms.biz.IContentBiz;
+import net.mingsoft.cms.biz.IHistoryLogBiz;
+import net.mingsoft.cms.entity.ContentEntity;
+import net.mingsoft.cms.entity.HistoryLogEntity;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.BindingResult;
+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.ResponseBody;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Date;
+import java.util.List;
+/**
+ * 文章管理控制层
+ * @author 铭飞开发团队
+ * 创建日期:2019-11-28 15:12:32<br/>
+ * 历史修订:<br/>
+ */
+@Api(value = "文章接口")
+@Controller("WebcmsContentAction")
+@RequestMapping("/cms/content")
+public class ContentAction extends net.mingsoft.cms.action.BaseAction{
+
+
+	/**
+	 * 注入文章业务层
+	 */
+	@Autowired
+	private IContentBiz contentBiz;
+
+	@Autowired
+	private IHistoryLogBiz historyLogBiz;
+
+	/**
+	 * 查询文章列表
+	 * @param content 文章实体
+	 */
+	@ApiOperation(value = "查询文章列表接口")
+	@ApiImplicitParams({
+    	@ApiImplicitParam(name = "contentTitle", value = "文章标题", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "categoryId", value = "所属栏目", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentType", value = "文章类型", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentDisplay", value = "是否显示", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentAuthor", value = "文章作者", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentSource", value = "文章来源", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentDatetime", value = "发布时间", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentSort", value = "自定义顺序", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentImg", value = "文章缩略图", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentDescription", value = "描述", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentKeyword", value = "关键字", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentDetails", value = "文章内容", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "contentUrl", value = "文章跳转链接地址", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "appid", value = "文章管理的应用id", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "createBy", value = "创建人", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "createDate", value = "创建时间", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "updateBy", value = "修改人", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "updateDate", value = "修改时间", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "del", value = "删除标记", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "id", value = "编号", required =false,paramType="query"),
+    })
+	@RequestMapping("/list")
+	@ResponseBody
+	public ResultData list(@ModelAttribute @ApiIgnore ContentEntity content,HttpServletResponse response, HttpServletRequest request,@ApiIgnore ModelMap model,BindingResult result) {
+		BasicUtil.startPage();
+		List contentList = contentBiz.query(content);
+		return ResultData.build().success(new EUListBean(contentList,(int)BasicUtil.endPage(contentList).getTotal()));
+	}
+
+
+	/**
+	 * 获取文章
+	 * @param content 文章实体
+	 */
+	@ApiOperation(value = "获取文章列表接口")
+    @ApiImplicitParam(name = "id", value = "编号", required =true,paramType="query")
+	@GetMapping("/get")
+	@ResponseBody
+	public ResultData get(@ModelAttribute @ApiIgnore ContentEntity content,HttpServletResponse response, HttpServletRequest request,@ApiIgnore ModelMap model){
+		if(content.getId()==null) {
+			return ResultData.build().error();
+		}
+		ContentEntity _content = (ContentEntity)contentBiz.getEntity(Integer.parseInt(content.getId()));
+		return ResultData.build().success(_content);
+	}
+
+	@ApiOperation(value = "查看文章点击数")
+	@ApiImplicitParam(name = "contentId", value = "文章编号", required = true,paramType="path")
+	@GetMapping(value = "/{contentId}/hit")
+	@ResponseBody
+	public String hit(@PathVariable @ApiIgnore String contentId, HttpServletRequest request, HttpServletResponse response){
+		if(StringUtils.isEmpty(contentId)){
+			return "document.write(0)";
+		}
+	 	//获取ip
+		String ip = BasicUtil.getIp();
+		//获取端口(移动/web..)
+		boolean isMobileDevice = BasicUtil.isMobileDevice();
+
+		ContentEntity content = contentBiz.getById(contentId);
+		if(content == null){
+			return "document.write(0)";
+		}
+	 	//浏览数+1
+		if(ObjectUtil.isNotEmpty(content.getContentHit())){
+			content.setContentHit(content.getContentHit()+1);
+		}else {
+			content.setContentHit(1);
+		}
+		contentBiz.updateEntity(content);
+
+		// cms_history 增加相应记录
+		HistoryLogEntity entity = new HistoryLogEntity();
+		entity.setHlIsMobile(isMobileDevice);
+		entity.setHlIp(ip);
+		entity.setContentId(content.getId());
+		entity.setCreateDate(new Date());
+		historyLogBiz.saveEntity(entity);
+
+		return "document.write(" + content.getContentHit() + ")";
+	}
+
+}

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

@@ -0,0 +1,594 @@
+/**
+ * The MIT License (MIT) * Copyright (c) 2016 铭飞科技(mingsoft.net)
+ * <p>
+ * 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:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ * <p>
+ * 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 cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.lang.Editor;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.PageUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import freemarker.core.ParseException;
+import freemarker.template.MalformedTemplateNameException;
+import freemarker.template.TemplateException;
+import freemarker.template.TemplateNotFoundException;
+import net.bytebuddy.implementation.bytecode.Throw;
+import net.mingsoft.base.constant.Const;
+import net.mingsoft.basic.exception.BusinessException;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.basic.util.StringUtil;
+import net.mingsoft.cms.bean.CategoryBean;
+import net.mingsoft.cms.bean.ContentBean;
+import net.mingsoft.cms.biz.ICategoryBiz;
+import net.mingsoft.cms.biz.IContentBiz;
+import net.mingsoft.cms.constant.e.CategoryTypeEnum;
+import net.mingsoft.cms.entity.CategoryEntity;
+import net.mingsoft.cms.entity.ContentEntity;
+import net.mingsoft.cms.util.CmsParserUtil;
+import net.mingsoft.mdiy.bean.PageBean;
+import net.mingsoft.mdiy.biz.IModelBiz;
+import net.mingsoft.mdiy.biz.IPageBiz;
+import net.mingsoft.mdiy.entity.ModelEntity;
+import net.mingsoft.mdiy.util.ParserUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.util.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 动态生成页面,需要后台配置自定义页数据
+ *
+ * @author 铭飞开源团队
+ * @date 2018年12月17日
+ */
+@Controller("dynamicPageAction")
+@RequestMapping("/mcms")
+public class MCmsAction extends net.mingsoft.cms.action.BaseAction {
+
+    /**
+     * 自定义页面业务层
+     */
+    @Autowired
+    private IPageBiz pageBiz;
+
+    /**
+     * 文章管理业务处理层
+     */
+    @Autowired
+    private IContentBiz contentBiz;
+
+    /**
+     * 栏目业务层
+     */
+    @Autowired
+    private ICategoryBiz categoryBiz;
+
+
+    /**
+     * 搜索标签;
+     */
+    public static final String SEARCH = "search";
+
+    /**
+     * 自定义模型
+     */
+    @Autowired
+    private IModelBiz modelBiz;
+
+
+    @Value("${ms.diy.html-dir:html}")
+    private String htmlDir;
+
+
+    /**
+     * 动态列表页
+     */
+    @GetMapping("/index.do")
+    @ResponseBody
+    public String index(HttpServletRequest req, HttpServletResponse resp) {
+        Map map = BasicUtil.assemblyRequestMap();
+        map.forEach((k, v) -> {
+            map.put(k, v.toString().replaceAll("('|\"|\\\\)", "\\\\$1"));
+        });
+        map.put(ParserUtil.URL, BasicUtil.getUrl());
+        //动态解析
+        map.put(ParserUtil.IS_DO, true);
+        //设置动态请求的模块路径
+        map.put(ParserUtil.MODEL_NAME, "mcms");
+        map.put(ParserUtil.HTML,htmlDir);
+        //解析后的内容
+        String content = "";
+        try {
+            //根据模板路径,参数生成
+            content = ParserUtil.rendering(ParserUtil.INDEX + ParserUtil.HTM_SUFFIX, map);
+        } catch (TemplateNotFoundException e) {
+            e.printStackTrace();
+        } catch (MalformedTemplateNameException e) {
+            e.printStackTrace();
+        } catch (ParseException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return content;
+    }
+
+    /**
+     * 动态列表页
+     *
+     * @param req
+     * @param resp
+     */
+    @ResponseBody
+    @GetMapping("/list.do")
+    public String list(HttpServletRequest req, HttpServletResponse resp) {
+        Map map = BasicUtil.assemblyRequestMap();
+        map.forEach((k, v) -> {
+            map.put(k, v.toString().replaceAll("('|\"|\\\\)", "\\\\$1"));
+        });
+        //获取栏目编号
+        int typeId = BasicUtil.getInt(ParserUtil.TYPE_ID, 0);
+        int size = BasicUtil.getInt("size", 10);
+        ContentBean contentBean = new ContentBean();
+        contentBean.setCategoryId(String.valueOf(typeId));
+        //获取文章总数
+        List<CategoryBean> columnArticles = contentBiz.queryIdsByCategoryIdForParser(contentBean);
+        //判断栏目下是否有文章
+        if (columnArticles.size() == 0) {
+            return "";
+        }
+        //设置分页类
+        PageBean page = new PageBean();
+        page.setPageNo(BasicUtil.getPageNo());
+        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.URL, BasicUtil.getUrl());
+        map.put(ParserUtil.PAGE, page);
+        //动态解析
+        map.put(ParserUtil.IS_DO, true);
+        //设置动态请求的模块路径
+        map.put(ParserUtil.MODEL_NAME, "mcms");
+        map.put(ParserUtil.HTML, htmlDir);
+        //解析后的内容
+        String content = "";
+        try {
+            //根据模板路径,参数生成
+            content = ParserUtil.rendering(columnArticles.get(0).getCategoryListUrl(), map);
+        } catch (TemplateNotFoundException e) {
+            e.printStackTrace();
+        } catch (MalformedTemplateNameException e) {
+            e.printStackTrace();
+        } catch (ParseException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return content;
+    }
+
+    /**
+     * 动态详情页
+     */
+    @GetMapping("/view.do")
+    @ResponseBody
+    public String view(String orderby, String order, HttpServletRequest req, HttpServletResponse resp) {
+        //参数文章编号
+        ContentEntity article = (ContentEntity) contentBiz.getEntity(BasicUtil.getInt(ParserUtil.ID));
+        if (ObjectUtil.isNull(article)) {
+            throw new BusinessException(this.getResString("err.empty", this.getResString("id")));
+        }
+        if (StringUtils.isNotBlank(order)) {
+            //防注入
+            if (!order.toLowerCase().equals("asc") && !order.toLowerCase().equals("desc")) {
+                throw new BusinessException(this.getResString("err.error", this.getResString("order")));
+            }
+        }
+
+        orderby = orderby.replaceAll("('|\"|\\\\)", "\\\\$1");
+        PageBean page = new PageBean();
+        //用于详情上下页获取当前文章列表对应的分类,根据文章查询只能获取自身分类
+        String typeId = BasicUtil.getString(ParserUtil.TYPE_ID, article.getCategoryId());
+        //根据文章编号查询栏目详情模版
+        CategoryEntity column = (CategoryEntity) categoryBiz.getEntity(Integer.parseInt(typeId));
+        //解析后的内容
+        String content = "";
+        Map map = BasicUtil.assemblyRequestMap();
+        map.forEach((k, v) -> {
+            //sql注入过滤
+            map.put(k, v.toString().replaceAll("('|\"|\\\\)", "\\\\$1"));
+        });
+        //动态解析
+        map.put(ParserUtil.IS_DO, true);
+        //设置栏目编号
+        map.put(ParserUtil.TYPE_ID, typeId);
+        //设置动态请求的模块路径
+        map.put(ParserUtil.MODEL_NAME, "mcms");
+        map.put(ParserUtil.URL, BasicUtil.getUrl());
+        map.put(ParserUtil.PAGE, page);
+        map.put(ParserUtil.ID, article.getId());
+        map.put(ParserUtil.HTML,htmlDir);
+
+        ContentBean contentBean = new ContentBean();
+        contentBean.setCategoryId(String.valueOf(typeId));
+        contentBean.setOrderBy(orderby);
+        contentBean.setOrder(order);
+        List<CategoryBean> articleIdList = contentBiz.queryIdsByCategoryIdForParser(contentBean);
+        Map<Object, Object> contentModelMap = new HashMap<Object, Object>();
+        ModelEntity contentModel = null;
+        for (int artId = 0; artId < articleIdList.size(); ) {
+            //如果不是当前文章则跳过
+            if (articleIdList.get(artId).getArticleId().equals(article.getId())) {
+                artId++;
+                continue;
+            }
+            // 文章的栏目路径
+            String categoryParentId = articleIdList.get(artId).getId();
+            if (StringUtils.isNotBlank(articleIdList.get(artId).getCategoryParentIds())) {
+                categoryParentId += ',' + articleIdList.get(artId).getCategoryParentIds();
+            }
+            // 文章的栏目模型编号
+            Integer columnContentModelId = articleIdList.get(artId).getMdiyModelId();
+            Map<String, Object> parserParams = new HashMap<String, Object>();
+            parserParams.put(ParserUtil.COLUMN, articleIdList.get(artId));
+            // 判断当前栏目是否有自定义模型
+            if (columnContentModelId != null && columnContentModelId > 0) {
+                // 通过当前栏目的模型编号获取,自定义模型表名
+                if (contentModelMap.containsKey(columnContentModelId)) {
+                    parserParams.put(ParserUtil.TABLE_NAME, contentModel.getModelTableName());
+                } else {
+                    // 通过栏目模型编号获取自定义模型实体
+                    contentModel = (ModelEntity) modelBiz.getEntity(columnContentModelId);
+                    // 将自定义模型编号设置为key值
+                    contentModelMap.put(columnContentModelId, contentModel.getModelTableName());
+                    parserParams.put(ParserUtil.TABLE_NAME, contentModel.getModelTableName());
+                }
+            }
+            // 第一篇文章没有上一篇
+            if (artId > 0) {
+                CategoryBean preCaBean = articleIdList.get(artId - 1);
+                page.setPreId(preCaBean.getArticleId());
+            }
+            // 最后一篇文章没有下一篇
+            if (artId + 1 < articleIdList.size()) {
+                CategoryBean nextCaBean = articleIdList.get(artId + 1);
+                page.setNextId(nextCaBean.getArticleId());
+            }
+            break;
+        }
+        try {
+            //根据模板路径,参数生成
+            content =  ParserUtil.rendering(column.getCategoryUrl(), map);
+        } catch (TemplateNotFoundException e) {
+            e.printStackTrace();
+        } catch (MalformedTemplateNameException e) {
+            e.printStackTrace();
+        } catch (ParseException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return content;
+    }
+
+
+    /**
+     * 实现前端页面的文章搜索
+     *
+     * @param request  搜索id
+     * @param response
+     */
+    @RequestMapping(value = "search")
+    @ResponseBody
+    public String search(HttpServletRequest request, HttpServletResponse response) {
+        //设置分页类
+        PageBean page = new PageBean();
+        page.setSize(ParserUtil.getPageSize(SEARCH + ParserUtil.HTM_SUFFIX, 20));
+
+        //参数集合,提供给解析使用
+        Map<String, Object> params = new HashMap<>();
+
+        // 读取请求字段
+        Map<String, Object> field = BasicUtil.assemblyRequestMap();
+
+        // 自定义字段集合
+        Map<String, String> diyFieldName = new HashMap<String, String>();
+
+        //记录自定义模型字段名
+        List filedStr = new ArrayList<>();
+        // 栏目对应字段的值
+        List<DiyModelMap> fieldValueList = new ArrayList<DiyModelMap>();
+
+        // 当前栏目
+        CategoryEntity column = null;
+        // 栏目对应模型
+        ModelEntity contentModel = null;
+
+
+        //获取栏目信息
+        String typeId = null;
+        String categoryIds = BasicUtil.getString("categoryIds");
+        List categoryIdList = CollectionUtil.newArrayList();
+        //当传递了栏目编号,但不是栏目集合
+        if (StringUtils.isNotBlank(categoryIds) && !categoryIds.contains(",")) {
+            typeId = categoryIds;
+        } else {
+            //取出所有的子栏目
+            String[] ids = categoryIds.split(",");
+            List<CategoryEntity> categoryList = categoryBiz.list(Wrappers.<CategoryEntity>lambdaQuery().ne(CategoryEntity::getCategoryType, CategoryTypeEnum.LINK.toString()));
+
+            categoryIdList = CollectionUtil.newArrayList(ids);
+            for(CategoryEntity c:categoryList) {
+                if(StringUtils.isNotEmpty(c.getParentids())) {
+                    for(String id:ids) {
+                        if(c.getParentids().indexOf(id)>-1) {
+                            categoryIdList.add(c.getId());
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        //重新组织 ID
+        categoryIds = StringUtils.join(categoryIdList, ",");
+
+
+        //根据栏目确定自定义模型
+        if (typeId != null) {
+            column = (CategoryEntity) categoryBiz.getById(typeId);
+            // 获取表单类型的id
+            if (column != null && ObjectUtil.isNotNull(column.getMdiyModelId())) {
+                contentModel = (ModelEntity) modelBiz.getEntity(column.getMdiyModelId());
+                if (contentModel != null) {
+                    // 保存自定义模型的数据
+                    Map<String, String> fieldMap = contentModel.getFieldMap();
+                    for (String s : fieldMap.keySet()) {
+                        filedStr.add(fieldMap.get(s));
+                    }
+                    // 设置自定义模型表名,方便解析的时候关联表查询
+                    params.put(ParserUtil.TABLE_NAME, contentModel.getModelTableName());
+                }
+            }
+
+            // 设置栏目,方便解析的时候关联表查询
+            params.put(ParserUtil.COLUMN, column);
+        }
+
+        // 处理读取请求字段
+        if (field != null) {
+            for (Map.Entry<String, Object> entry : field.entrySet()) {
+                if (entry != null) {
+                    //空值不处理
+                    if (ObjectUtil.isNull(entry.getValue())) {
+                        continue;
+                    }
+
+                    // 对值进行安全处理
+                    // 处理由get方法请求中文乱码问题
+                    String value = entry.getValue().toString().replaceAll("('|\"|\\\\)", "\\\\$1");
+                    //Xss过滤
+                    value = clearXss(value);
+                    // 如果是get方法需要将请求地址参数转码
+                    if (request.getMethod().equals(RequestMethod.GET)) {
+                        try {
+                            value = new String(value.getBytes("ISO-8859-1"), Const.UTF8);
+                        } catch (UnsupportedEncodingException e) {
+                            e.printStackTrace();
+                        }
+                    }
+
+                    // 保存至自定义字段集合
+                    if (StringUtils.isNotBlank(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) {
+            params.put("diyModel", fieldValueList);
+        }
+
+
+        Map<String, Object> searchMap = field;
+        searchMap.put("categoryIds",categoryIds);
+        StringBuilder urlParams = new StringBuilder();
+
+        searchMap.forEach((k, v) -> {
+            //sql注入过滤
+            if (v != null) {
+                searchMap.put(k, v.toString().replaceAll("('|\"|\\\\)", "\\\\$1"));
+                searchMap.put(k, clearXss(searchMap.get(k).toString()));
+                if (!"size".equals(k) && !"pageNo".equals(k)) {
+                    urlParams.append(k).append("=").append(searchMap.get(k)).append("&");
+                }
+            }
+        });
+
+        //查询数量
+        int count = contentBiz.getSearchCount(contentModel, fieldValueList, searchMap, BasicUtil.getApp().getAppId(), categoryIds);
+        page.setRcount(count);
+        params.put(SEARCH, searchMap);
+
+        //站点编号
+        if (BasicUtil.getWebsiteApp() != null) {
+            params.put(ParserUtil.APP_DIR, BasicUtil.getWebsiteApp().getAppDir());
+            params.put(ParserUtil.URL, BasicUtil.getWebsiteApp().getAppHostUrl());
+            params.put(ParserUtil.APP_ID, BasicUtil.getWebsiteApp().getAppId());
+        } else {
+            params.put(ParserUtil.URL, BasicUtil.getUrl());
+            params.put(ParserUtil.APP_DIR, BasicUtil.getApp().getAppDir());
+        }
+
+        params.put(ParserUtil.PAGE, page);
+        params.put(ParserUtil.HTML, htmlDir);
+        //动态解析
+        params.put(ParserUtil.IS_DO, false);
+        //设置动态请求的模块路径
+        params.put(ParserUtil.MODEL_NAME, "mcms");
+
+        searchMap.put("pageNo", 0);
+//        ParserUtil.read(SEARCH + ParserUtil.HTM_SUFFIX, map, page);
+        int total = PageUtil.totalPage(count, page.getSize());
+
+
+        int pageNo = BasicUtil.getInt("pageNo", 1);
+        if (pageNo >= total && total != 0) {
+            pageNo = total;
+        }
+        //获取总数
+        page.setTotal(total);
+
+        page.setPageNo(pageNo);
+
+        //设置分页的统一链接
+        String url = params.get(ParserUtil.URL).toString();
+        url = url + request.getServletPath() + "?" + urlParams;
+        String pageNoStr = "size=" + page.getSize() + "&pageNo=";
+        //下一页
+        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);
+
+        params.put(SEARCH, searchMap);
+        if (BasicUtil.getWebsiteApp() != null) {
+            params.put(ParserUtil.APP_DIR, BasicUtil.getWebsiteApp().getAppDir());
+        }
+        params.put(ParserUtil.PAGE, page);
+        params.put(ParserUtil.HTML, htmlDir);
+        //动态解析
+        params.put(ParserUtil.IS_DO, false);
+        //设置动态请求的模块路径
+        params.put(ParserUtil.MODEL_NAME, "mcms");
+
+        //解析后的内容
+        String content = "";
+        try {
+            //根据模板路径,参数生成
+            content = ParserUtil.rendering(SEARCH + ParserUtil.HTM_SUFFIX, params);
+        } catch (TemplateNotFoundException e) {
+            e.printStackTrace();
+        } catch (MalformedTemplateNameException e) {
+            e.printStackTrace();
+        } catch (ParseException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return content;
+    }
+
+    // 清除路径中的转义字符
+    private String clearXss(String value) {
+
+        if (value == null || "".equals(value)) {
+            return value;
+        }
+
+        value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
+        value = value.replaceAll("\\(", "&#40;").replace("\\)", "&#41;");
+        value = value.replaceAll("'", "&#39;");
+        value = value.replaceAll("eval\\((.*)\\)", "");
+        value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']",
+                "\"\"");
+        value = value.replace("script", "");
+
+        return value;
+    }
+
+    /**
+     * 存储自定义模型字段和接口参数
+     *
+     * @author 铭飞开源团队
+     * @date 2019年3月5日
+     */
+    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;
+        }
+    }
+
+
+    public static void main(String[] args) {
+
+        int[] a = PageUtil.rainbow(20, 30, 5);
+        for (int _a : a) {
+            System.out.println(_a);
+        }
+
+    }
+
+}

+ 84 - 0
src/main/java/net/mingsoft/cms/aop/ContentAop.java

@@ -0,0 +1,84 @@
+package net.mingsoft.cms.aop;
+
+import net.mingsoft.basic.aop.BaseAop;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.cms.biz.IContentBiz;
+import net.mingsoft.cms.biz.IHistoryLogBiz;
+import net.mingsoft.cms.entity.ContentEntity;
+import net.mingsoft.cms.entity.HistoryLogEntity;
+import org.apache.commons.lang3.StringUtils;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+/**
+ * @author 铭飞开源团队
+ * @date 2019/12/23
+ */
+@Component
+@Aspect
+public class ContentAop extends BaseAop {
+
+    /**
+     * 注入文章业务
+     */
+    @Autowired
+    private IContentBiz contentBiz;
+
+    /**
+     * 注入浏览记录业务
+     */
+    @Autowired
+    private IHistoryLogBiz historyLogBiz;
+
+    /**
+     * 文章浏览记录,
+     * 如果该文章该ip已经记录过,则不在重复记录
+     * @param pjp
+     * @return
+     * @throws Throwable
+     */
+    @Around("execution(* net.mingsoft.cms.action.web.ContentAction.get(..))")
+    public Object get(ProceedingJoinPoint pjp) throws Throwable{
+
+//        获取方法参数
+        ContentEntity content = getType(pjp, ContentEntity.class);
+//        如果id为空则直接发行
+        if(content.getId()==null) {
+            return pjp.proceed();
+        }
+        content = (ContentEntity)contentBiz.getEntity(Integer.parseInt(content.getId()));
+        //如果文章不存在则直接发行
+        if(content == null){
+            return pjp.proceed();
+        }
+
+        //查询判断该ip是否已经有浏览记录了
+        HistoryLogEntity historyLog = new HistoryLogEntity();
+        historyLog.setContentId(content.getId());
+        historyLog.setHlIp(BasicUtil.getIp());
+        historyLog.setHlIsMobile(BasicUtil.isMobileDevice());
+        HistoryLogEntity _historyLog = (HistoryLogEntity)historyLogBiz.getEntity(historyLog);
+        //如果该ip该文章没有浏览记录则保存浏览记录
+        //并且更新点击数
+        if(_historyLog == null || StringUtils.isBlank(_historyLog.getId())){
+            historyLog.setCreateDate(new Date());
+            historyLogBiz.saveEntity(historyLog);
+            //更新点击数
+            ContentEntity updateContent = new ContentEntity();
+            updateContent.setId(content.getId());
+            if(content.getContentHit() == null){
+                updateContent.setContentHit(1);
+            }else{
+                updateContent.setContentHit(content.getContentHit()+1);
+            }
+            contentBiz.updateEntity(updateContent);
+        }
+
+        return pjp.proceed();
+    }
+}

+ 28 - 0
src/main/java/net/mingsoft/cms/bean/CategoryBean.java

@@ -0,0 +1,28 @@
+package net.mingsoft.cms.bean;
+
+import net.mingsoft.cms.entity.CategoryEntity;
+
+/**
+* 文章实体
+* @author 铭飞开发团队
+* 创建日期:2019-11-28 15:12:32<br/>
+* 历史修订:<br/>
+*/
+public class CategoryBean extends CategoryEntity {
+
+	/**
+	 * 文章编号
+	 */
+	private String articleId;
+
+
+
+
+	public String getArticleId() {
+		return articleId;
+	}
+
+	public void setArticleId(String articleId) {
+		this.articleId = articleId;
+	}
+}

+ 73 - 0
src/main/java/net/mingsoft/cms/bean/ContentBean.java

@@ -0,0 +1,73 @@
+package net.mingsoft.cms.bean;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import net.mingsoft.cms.entity.ContentEntity;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+/**
+ * 文章实体bean
+ */
+public class ContentBean extends ContentEntity {
+
+//    /**
+//     * 静态化地址
+//     */
+//    private String staticUrl;
+
+    /**
+     * 开始时间
+     */
+    private String beginTime;
+
+    /**
+     * 结束时间
+     */
+    private String endTime;
+
+    /**
+     * 属性标记
+     */
+    private String flag;
+
+    /**
+     * 不包含属性标记
+     */
+    private String noflag;
+
+
+
+    public String getBeginTime() {
+        return beginTime;
+    }
+
+    public void setBeginTime(String beginTime) {
+        this.beginTime = beginTime;
+    }
+
+    public String getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(String endTime) {
+        this.endTime = endTime;
+    }
+
+    public String getFlag() {
+        return flag;
+    }
+
+    public void setFlag(String flag) {
+        this.flag = flag;
+    }
+
+    public String getNoflag() {
+        return noflag;
+    }
+
+    public void setNoflag(String noflag) {
+        this.noflag = noflag;
+    }
+}

+ 39 - 0
src/main/java/net/mingsoft/cms/biz/ICategoryBiz.java

@@ -0,0 +1,39 @@
+package net.mingsoft.cms.biz;
+
+import net.mingsoft.base.biz.IBaseBiz;
+import net.mingsoft.cms.entity.CategoryEntity;
+
+import java.util.List;
+
+
+/**
+ * 分类业务
+ * @author 铭飞开发团队
+ * 创建日期:2019-11-28 15:12:32<br/>
+ * 历史修订:<br/>
+ */
+public interface ICategoryBiz extends IBaseBiz<CategoryEntity> {
+
+    /**
+     * 查询当前分类下的所有子分类
+     * @param category
+     * @return
+     */
+    List<CategoryEntity> queryChilds(CategoryEntity category);
+
+    void saveEntity(CategoryEntity entity);
+
+    /**更新父级及子集
+     * @param entity
+     */
+    void updateEntity(CategoryEntity entity);
+
+    /**只更新自身
+     * @param entity
+     */
+    void update(CategoryEntity entity);
+
+    void delete(String categoryId);
+
+    void copyCategory(CategoryEntity entity);
+}

+ 29 - 0
src/main/java/net/mingsoft/cms/biz/IContentBiz.java

@@ -0,0 +1,29 @@
+package net.mingsoft.cms.biz;
+
+import net.mingsoft.base.biz.IBaseBiz;
+import net.mingsoft.cms.bean.CategoryBean;
+import net.mingsoft.cms.bean.ContentBean;
+import net.mingsoft.cms.entity.ContentEntity;
+import net.mingsoft.mdiy.entity.ModelEntity;
+
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * 文章业务
+ * @author 铭飞开发团队
+ * 创建日期:2019-11-28 15:12:32<br/>
+ * 历史修订:<br/>
+ */
+public interface IContentBiz extends IBaseBiz<ContentEntity> {
+
+    /**
+     * 根据文章属性查询
+     * @param contentBean
+     * @return
+     */
+    List<CategoryBean> queryIdsByCategoryIdForParser(ContentBean contentBean);
+
+    int getSearchCount(ModelEntity contentModel, List diyList, Map whereMap, int appId, String categoryIds);
+}

+ 14 - 0
src/main/java/net/mingsoft/cms/biz/IHistoryLogBiz.java

@@ -0,0 +1,14 @@
+package net.mingsoft.cms.biz;
+
+import net.mingsoft.base.biz.IBaseBiz;
+
+
+/**
+ * 文章浏览记录业务
+ * @author 铭飞开发团队
+ * 创建日期:2019-12-23 9:24:03<br/>
+ * 历史修订:<br/>
+ */
+public interface IHistoryLogBiz extends IBaseBiz {
+
+}

+ 284 - 0
src/main/java/net/mingsoft/cms/biz/impl/CategoryBizImpl.java

@@ -0,0 +1,284 @@
+/**
+The MIT License (MIT) * Copyright (c) 2019 铭飞科技
+
+ * 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 cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import net.mingsoft.base.biz.impl.BaseBizImpl;
+import net.mingsoft.base.dao.IBaseDao;
+import net.mingsoft.basic.util.PinYinUtil;
+import net.mingsoft.cms.biz.ICategoryBiz;
+import net.mingsoft.cms.dao.ICategoryDao;
+import net.mingsoft.cms.dao.IContentDao;
+import net.mingsoft.cms.entity.CategoryEntity;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 分类管理持久化层
+ * @author 铭飞开发团队
+ * 创建日期:2019-11-28 15:12:32<br/>
+ * 历史修订:<br/>
+ */
+ @Service("cmscategoryBizImpl")
+ @Transactional(rollbackFor = RuntimeException.class)
+public class CategoryBizImpl extends BaseBizImpl<ICategoryDao, CategoryEntity> implements ICategoryBiz {
+
+
+	@Autowired
+	private ICategoryDao categoryDao;
+
+	@Autowired
+	private IContentDao contentDao;
+
+
+	@Override
+	protected IBaseDao getDao() {
+		// TODO Auto-generated method stub
+		return categoryDao;
+	}
+
+	@Override
+	public List<CategoryEntity> queryChilds(CategoryEntity category) {
+		// TODO Auto-generated method stub
+		return categoryDao.queryChildren(category);
+	}
+	@Override
+	public void saveEntity(CategoryEntity categoryEntity) {
+		// TODO Auto-generated method stub
+		String pingYin = PinYinUtil.getPingYin(categoryEntity.getCategoryTitle());
+		//如果用户自己填入了拼音则使用用户的
+		if (StrUtil.isNotBlank(categoryEntity.getCategoryPinyin())) {
+			pingYin = categoryEntity.getCategoryPinyin();
+		}
+		CategoryEntity category=new CategoryEntity();
+		category.setCategoryPinyin(pingYin);
+		Object categoryBizEntity = getEntity(category);
+		setParentId(categoryEntity);
+		categoryEntity.setCategoryPinyin(pingYin);
+		//更新新的父级
+		if(StrUtil.isNotBlank(categoryEntity.getCategoryId())&&!"0".equals(categoryEntity.getCategoryId())){
+			CategoryEntity parent = getById(categoryEntity.getCategoryId());
+			//如果之前是叶子节点就更新
+			if(parent.getLeaf()){
+				parent.setLeaf(false);
+				updateById(parent);
+			}
+		}
+		categoryEntity.setLeaf(false);
+		//如果是新增栏目一定是叶子节点
+		if (StrUtil.isEmpty(categoryEntity.getId())) {
+			categoryEntity.setLeaf(true);
+		}
+		super.save(categoryEntity);
+		//拼音存在则拼接id
+		if(categoryBizEntity!=null){
+			categoryEntity.setCategoryPinyin(pingYin+categoryEntity.getId());
+		}
+		CategoryEntity parentCategory = null;
+		if (StringUtils.isNotBlank(categoryEntity.getCategoryId())) {
+			parentCategory = (CategoryEntity)getById(categoryEntity.getCategoryId());
+		}
+		//保存链接地址
+		String path=ObjectUtil.isNotNull(parentCategory)?parentCategory.getCategoryPath():"";
+		categoryEntity.setCategoryPath( path+"/" + categoryEntity.getCategoryPinyin());
+		setTopId(categoryEntity);
+		super.updateById(categoryEntity);
+	}
+
+	private void setParentId(CategoryEntity categoryEntity) {
+		String path = "";
+		if(StringUtils.isNotEmpty(categoryEntity.getCategoryId())&&Long.parseLong(categoryEntity.getCategoryId())>0) {
+			CategoryEntity category = (CategoryEntity)getById(categoryEntity.getCategoryId());
+			path = category.getCategoryPath();
+			if(StringUtils.isEmpty(category.getCategoryParentIds())) {
+				categoryEntity.setCategoryParentIds(category.getId());
+			} else {
+				categoryEntity.setCategoryParentIds(category.getCategoryParentIds()+","+category.getId());
+			}
+		}else {
+			categoryEntity.setCategoryParentIds(null);
+		}
+		//保存时先保存再修改链接地址,修改时直接修改
+		if(StringUtils.isNotBlank(categoryEntity.getId())) {
+			categoryEntity.setCategoryPath(path+ "/" + categoryEntity.getCategoryPinyin());
+		}
+
+	}
+	private void setChildParentId(CategoryEntity categoryEntity) {
+		CategoryEntity category=new CategoryEntity();
+		category.setCategoryId(categoryEntity.getId());
+		List<CategoryEntity> list = categoryDao.query(category);
+		list.forEach(x->{
+			if(StringUtils.isEmpty(categoryEntity.getCategoryParentIds())) {
+				x.setCategoryParentIds(categoryEntity.getId());
+			} else {
+				x.setCategoryParentIds(categoryEntity.getCategoryParentIds()+","+categoryEntity.getId());
+			}
+			String path=categoryEntity.getCategoryPath();
+			//判断是否有parentIds
+			x.setCategoryPath(path+"/"+x.getCategoryPinyin());
+			//去除多余的/符号
+			super.updateEntity(x);
+			setChildParentId(x);
+		});
+	}
+
+	@Override
+	public void updateEntity(CategoryEntity entity) {
+		setParentId(entity);
+		String pingYin =entity.getCategoryPinyin();
+	if(StrUtil.isNotBlank(pingYin)){
+		CategoryEntity category=new CategoryEntity();
+		category.setCategoryPinyin(pingYin);
+		CategoryEntity categoryBizEntity = (CategoryEntity)getEntity(category);
+		//拼音存在则拼接id
+		if(categoryBizEntity!=null&&!categoryBizEntity.getId().equals(entity.getId())){
+			entity.setCategoryPinyin(pingYin+entity.getId());
+		}
+	}
+		setParentLeaf(entity);
+		setTopId(entity);
+		super.updateById(entity);
+		setChildParentId(entity);
+	}
+
+
+	@Override
+	public void update(CategoryEntity entity) {
+		super.updateEntity(entity);
+	}
+
+	@Override
+	public void delete(String categoryId) {
+		// TODO Auto-generated method stub
+		CategoryEntity category = (CategoryEntity) categoryDao.selectById(categoryId);
+		//删除父类
+		if(category != null){
+			category.setCategoryParentIds(null);
+			List<CategoryEntity> childrenList = categoryDao.queryChildren(category);
+			List<String> ids = new ArrayList<>();
+			for(int i = 0; i < childrenList.size(); i++){
+				//删除子类
+				ids.add(childrenList.get(i).getId());
+			}
+			categoryDao.deleteBatchIds(ids);
+			// 删除文章
+			contentDao.deleteEntityByCategoryIds(ids.toArray(new String[ids.size()]));
+		}
+	}
+
+	/**
+	 * 设置父级叶子节点
+	 * @param entity
+	 */
+	private void setParentLeaf(CategoryEntity entity){
+		Assert.notNull(entity);
+		CategoryEntity categoryEntity = getById(entity.getId());
+		//如果父级不为空并且修改了父级则需要更新父级
+		if(entity.getCategoryId() != null && !entity.getCategoryId().equals(categoryEntity.getCategoryId())){
+			//更新旧的父级
+			if(StrUtil.isNotBlank(categoryEntity.getCategoryId())&&!"0".equals(categoryEntity.getCategoryId())){
+				CategoryEntity parent = getById(categoryEntity.getCategoryId());
+				//如果修改了父级则需要判断父级是否还有子节点
+				boolean leaf = parent.getLeaf();
+				//查找不等于当前更新的分类子集,有则不是叶子节点
+				QueryWrapper<CategoryEntity> queryWrapper = new QueryWrapper<>();
+				parent.setLeaf(count(queryWrapper.eq("category_id",parent.getId()).ne("id",entity.getId()))==0);
+				if(leaf!=parent.getLeaf()){
+					updateById(parent);
+				}
+
+			}
+			//更新新的父级
+			if(StrUtil.isNotBlank(entity.getCategoryId())&&!"0".equals(entity.getCategoryId())){
+				CategoryEntity parent = getById(entity.getCategoryId());
+				//如果之前是叶子节点就更新
+				if(parent.getLeaf()){
+					parent.setLeaf(false);
+					updateById(parent);
+				}
+			}
+		}
+	}
+
+	/**
+	 * 设置顶级id
+	 * @param entity
+	 */
+	private void setTopId(CategoryEntity entity){
+		String categoryParentId = entity.getCategoryParentIds();
+		if(StrUtil.isNotBlank(categoryParentId)){
+			String[] ids = categoryParentId.split(",");
+			//如果有ParentId就取第一个
+			if(ids.length>0){
+				entity.setTopId(ids[0]);
+				return;
+			}
+		}
+		entity.setTopId("0");
+	}
+
+	@Override
+	public void copyCategory(CategoryEntity category) {
+		String oldId = category.getId();
+		//先保存被复制第一层栏目,因为第一层栏目不需要变更父级栏目
+		category = getById(oldId);
+		//id、拼音和路径按照原来的业务逻辑生成
+		category.setId(null);
+		category.setCategoryPinyin(null);
+		category.setCategoryPath(null);
+		saveEntity(category);
+		//传入简要被复制子栏目的id和复制后的生成的id,复制的子栏目全部使用
+		recursionCopyChilds(oldId, category.getId());
+	}
+
+	/*
+	* 递归复制子栏目
+	* @param oldParentId:被复制的父级栏目id(需要数据库原来存在该数据)
+	* @param newParentId:复制栏目后新父级的id(新插入数据的id)
+	* */
+	private void recursionCopyChilds(String oldParentId, String newParentId) {
+		CategoryEntity _category = new CategoryEntity();
+		_category.setCategoryId(oldParentId);
+		List<CategoryEntity> childs = query(_category);
+		for (CategoryEntity child : childs) {
+			String childId = child.getId();
+			//id、拼音和路径按照原来的业务逻辑生成
+			child.setId(null);
+			child.setCategoryPinyin(null);
+			child.setCategoryPath(null);
+			child.setCategoryId(newParentId);
+			saveEntity(child);
+			//如果该栏目下还有子栏目则继续复制该栏目里的子栏目
+			recursionCopyChilds(childId, child.getId());
+		}
+	}
+
+}

+ 102 - 0
src/main/java/net/mingsoft/cms/biz/impl/ContentBizImpl.java

@@ -0,0 +1,102 @@
+/**
+The MIT License (MIT) * Copyright (c) 2019 铭飞科技
+
+ * 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 cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.bean.copier.CopyOptions;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.io.FileUtil;
+import net.mingsoft.basic.constant.Const;
+import net.mingsoft.basic.holder.DataHolder;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.cms.bean.CategoryBean;
+import net.mingsoft.cms.bean.ContentBean;
+import net.mingsoft.cms.constant.e.CategoryTypeEnum;
+import net.mingsoft.cms.dao.ICategoryDao;
+import net.mingsoft.cms.entity.CategoryEntity;
+import net.mingsoft.cms.entity.ContentEntity;
+import net.mingsoft.cms.util.CmsParserUtil;
+import net.mingsoft.mdiy.bean.PageBean;
+import net.mingsoft.mdiy.entity.ModelEntity;
+import net.mingsoft.mdiy.util.ParserUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import net.mingsoft.base.biz.impl.BaseBizImpl;
+import net.mingsoft.base.dao.IBaseDao;
+
+import java.io.IOException;
+import java.util.*;
+
+import net.mingsoft.cms.biz.IContentBiz;
+import net.mingsoft.cms.dao.IContentDao;
+
+/**
+ * 文章管理持久化层
+ * @author 铭飞开发团队
+ * 创建日期:2019-11-28 15:12:32<br/>
+ * 历史修订:<br/>
+ */
+ @Service("cmscontentBizImpl")
+public class ContentBizImpl  extends BaseBizImpl<IContentDao, ContentEntity> implements IContentBiz {
+
+	/*
+	 * log4j日志记录
+	 */
+	protected final Logger LOG = LoggerFactory.getLogger(this.getClass());
+
+	@Autowired
+	private IContentDao contentDao;
+	/**
+	 * 栏目管理业务层
+	 */
+	@Autowired
+	private ICategoryDao categoryDao;
+
+	@Value("${ms.diy.html-dir:html}")
+	private String htmlDir;
+
+
+	@Override
+	protected IBaseDao getDao() {
+		// TODO Auto-generated method stub
+		return contentDao;
+	}
+
+	@Override
+	public List<CategoryBean> queryIdsByCategoryIdForParser(ContentBean contentBean) {
+		return this.contentDao.queryIdsByCategoryIdForParser(contentBean);
+	}
+
+	@Override
+	public int getSearchCount(ModelEntity contentModel, List diyList, Map whereMap, int appId, String categoryIds) {
+		if (contentModel!=null) {
+			return contentDao.getSearchCount(contentModel.getModelTableName(),diyList,whereMap, appId,categoryIds);
+		}
+		return contentDao.getSearchCount(null,null,whereMap, appId,categoryIds);
+	}
+
+
+}

+ 50 - 0
src/main/java/net/mingsoft/cms/biz/impl/HistoryLogBizImpl.java

@@ -0,0 +1,50 @@
+/**
+The MIT License (MIT) * Copyright (c) 2019 铭飞科技
+
+ * 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 net.mingsoft.cms.biz.IHistoryLogBiz;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import net.mingsoft.base.biz.impl.BaseBizImpl;
+import net.mingsoft.base.dao.IBaseDao;
+import net.mingsoft.cms.dao.ICmsHistoryLogDao;
+
+/**
+ * 文章浏览记录管理持久化层
+ * @author 铭飞开发团队
+ * 创建日期:2019-12-23 9:24:03<br/>
+ * 历史修订:<br/>
+ */
+ @Service("cmshistoryLogBizImpl")
+public class HistoryLogBizImpl extends BaseBizImpl implements IHistoryLogBiz {
+
+	
+	@Autowired
+	private ICmsHistoryLogDao historyLogDao;
+	
+	
+	@Override
+	protected IBaseDao getDao() {
+		// TODO Auto-generated method stub
+		return historyLogDao;
+	} 
+}

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

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

+ 70 - 0
src/main/java/net/mingsoft/cms/constant/e/CategoryTypeEnum.java

@@ -0,0 +1,70 @@
+/**
+ * The MIT License (MIT) * Copyright (c) 2020 铭软科技(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;
+
+/**
+ * @Author: 铭飞团队
+ * @Description:
+ * @Date: Create in 2020/06/23 14:18
+ */
+public enum CategoryTypeEnum implements BaseEnum {
+
+    /**
+     * 列表
+     */
+    LIST("1"),
+    /**
+     * 封面
+     */
+    COVER("2"),
+    /**
+     * 链接
+     */
+    LINK("3");
+
+
+    CategoryTypeEnum(String type) {
+        this.type = type;
+    }
+
+    private String type;
+
+    public static CategoryTypeEnum get(String type) {
+        for (CategoryTypeEnum e : CategoryTypeEnum.values()) {
+            if (e.type.equals(type)) {
+                return e;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public int toInt() {
+        return Integer.parseInt(type);
+    }
+
+    @Override
+    public String toString() {
+        return type;
+    }
+}

+ 25 - 0
src/main/java/net/mingsoft/cms/dao/ICategoryDao.java

@@ -0,0 +1,25 @@
+package net.mingsoft.cms.dao;
+
+import net.mingsoft.base.dao.IBaseDao;
+import net.mingsoft.cms.entity.CategoryEntity;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * 分类持久层
+ * @author 铭飞开发团队
+ * 创建日期:2019-11-28 15:12:32<br/>
+ * 历史修订:<br/>
+ */
+@Component("cmsCategoryDao")
+public interface ICategoryDao extends IBaseDao<CategoryEntity> {
+
+    /**
+     * 查询当前分类下面的所有子分类
+     * @param category 必须存在categoryId categoryParentId
+     * @return
+     */
+    public List<CategoryEntity> queryChildren(CategoryEntity category);
+
+}

+ 222 - 0
src/main/java/net/mingsoft/cms/dao/ICategoryDao.xml

@@ -0,0 +1,222 @@
+<?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.ICategoryDao">
+
+	<resultMap id="resultMap" type="net.mingsoft.cms.entity.CategoryEntity">
+			<id column="id" property="id" /><!--编号 -->
+				<result column="category_title" property="categoryTitle" /><!--栏目管理名称 -->
+				<result column="category_pinyin" property="categoryPinyin" /><!--栏目管理名称 -->
+				<result column="category_id" property="categoryId" /><!--所属栏目 -->
+				<result column="category_type" property="categoryType" /><!--栏目管理属性 -->
+				<result column="category_sort" property="categorySort" /><!--自定义顺序 -->
+				<result column="category_list_url" property="categoryListUrl" /><!--列表模板 -->
+				<result column="category_url" property="categoryUrl" /><!--内容模板 -->
+				<result column="category_keyword" property="categoryKeyword" /><!--栏目管理关键字 -->
+				<result column="category_descrip" property="categoryDescrip" /><!--栏目管理描述 -->
+				<result column="category_img" property="categoryImg" /><!--缩略图 -->
+				<result column="category_diy_url" property="categoryDiyUrl" /><!--自定义链接 -->
+				<result column="mdiy_model_id" property="mdiyModelId" /><!--栏目管理的内容模型id -->
+				<result column="category_datetime" property="categoryDatetime" /><!--类别发布时间 -->
+				<result column="dict_id" property="dictId" /><!--字典对应编号 -->
+				<result column="category_flag" property="categoryFlag" /><!--栏目属性 -->
+				<result column="category_path" property="categoryPath" /><!--栏目路径 -->
+				<result column="category_parent_ids" property="categoryParentIds" /><!--父类型编号 -->
+				<result column="create_by" property="createBy" /><!--创建人 -->
+				<result column="create_date" property="createDate" /><!--创建时间 -->
+				<result column="update_by" property="updateBy" /><!--修改人 -->
+				<result column="update_date" property="updateDate" /><!--修改时间 -->
+				<result column="del" property="del" /><!--删除标记 -->
+	</resultMap>
+
+	<!--保存-->
+	<insert id="saveEntity" useGeneratedKeys="true" keyProperty="id"
+			parameterType="net.mingsoft.cms.entity.CategoryEntity" >
+		insert into cms_category
+		<trim prefix="(" suffix=")" suffixOverrides=",">
+				<if test="categoryTitle != null and categoryTitle != ''">category_title,</if>
+				<if test="categoryPinyin != null and categoryPinyin != ''">category_pinyin,</if>
+				<if test="categoryId != null and categoryId != ''">category_id,</if>
+				<if test="categoryType != null and categoryType != ''">category_type,</if>
+				<if test="categorySort != null">category_sort,</if>
+				<if test="categoryListUrl != null and categoryListUrl != ''">category_list_url,</if>
+				<if test="categoryUrl != null and categoryUrl != ''">category_url,</if>
+				<if test="categoryKeyword != null and categoryKeyword != ''">category_keyword,</if>
+				<if test="categoryDescrip != null and categoryDescrip != ''">category_descrip,</if>
+				<if test="categoryImg != null and categoryImg != ''">category_img,</if>
+				<if test="categoryDiyUrl != null and categoryDiyUrl != ''">category_diy_url,</if>
+				<if test="mdiyModelId != null and mdiyModelId != ''">mdiy_model_id,</if>
+				<if test="categoryDatetime != null">category_datetime,</if>
+				<if test="dictId != null">dict_id,</if>
+				<if test="categoryFlag != null">category_flag,</if>
+				<if test="categoryPath != null and categoryPath != ''">category_path,</if>
+				<if test="categoryParentIds != null and categoryParentIds != ''">category_parent_ids,</if>
+				<if test="createBy &gt; 0">create_by,</if>
+				<if test="createDate != null">create_date,</if>
+				<if test="updateBy &gt; 0">update_by,</if>
+				<if test="updateDate != null">update_date,</if>
+				<if test="del != null">del,</if>
+		</trim>
+		<trim prefix="values (" suffix=")" suffixOverrides=",">
+				<if test="categoryTitle != null and categoryTitle != ''">#{categoryTitle},</if>
+				<if test="categoryPinyin != null and categoryPinyin != ''">#{categoryPinyin},</if>
+				<if test="categoryId != null and categoryId != ''">#{categoryId},</if>
+				<if test="categoryType != null and categoryType != ''">#{categoryType},</if>
+				<if test="categorySort != null">#{categorySort},</if>
+				<if test="categoryListUrl != null and categoryListUrl != ''">#{categoryListUrl},</if>
+				<if test="categoryUrl != null and categoryUrl != ''">#{categoryUrl},</if>
+				<if test="categoryKeyword != null and categoryKeyword != ''">#{categoryKeyword},</if>
+				<if test="categoryDescrip != null and categoryDescrip != ''">#{categoryDescrip},</if>
+				<if test="categoryImg != null and categoryImg != ''">#{categoryImg},</if>
+				<if test="categoryDiyUrl != null and categoryDiyUrl != ''">#{categoryDiyUrl},</if>
+				<if test="mdiyModelId != null and mdiyModelId != ''">#{mdiyModelId},</if>
+				<if test="categoryDatetime != null">#{categoryDatetime},</if>
+				<if test="dictId != null">#{dictId},</if>
+				<if test="categoryFlag != null ">#{categoryFlag},</if>
+				<if test="categoryPath != null and categoryPath != ''">#{categoryPath},</if>
+				<if test="categoryParentId != null and categoryParentId != ''">#{categoryParentId},</if>
+				<if test="createBy &gt; 0">#{createBy},</if>
+				<if test="createDate != null">#{createDate},</if>
+				<if test="updateBy &gt; 0">#{updateBy},</if>
+				<if test="updateDate != null">#{updateDate},</if>
+				<if test="del != null">#{del},</if>
+		</trim>
+	</insert>
+
+		<!--更新-->
+		<update id="updateEntity" parameterType="net.mingsoft.cms.entity.CategoryEntity">
+			update cms_category
+			<set>
+				<if test="categoryTitle != null and categoryTitle != ''">category_title=#{categoryTitle},</if>
+				<if test="categoryPinyin != null and categoryPinyin != ''">category_pinyin=#{categoryPinyin},</if>
+				category_id=#{categoryId},
+				category_parent_ids=#{categoryParentIds},
+				<if test="categoryType != null and categoryType != ''">category_type=#{categoryType},</if>
+				<if test="categorySort != null">category_sort=#{categorySort},</if>
+				<if test="categoryListUrl != null and categoryListUrl != ''">category_list_url=#{categoryListUrl},</if>
+				<if test="categoryUrl != null and categoryUrl != ''">category_url=#{categoryUrl},</if>
+				<if test="categoryKeyword != null ">category_keyword=#{categoryKeyword},</if>
+				<if test="categoryDescrip != null ">category_descrip=#{categoryDescrip},</if>
+				<if test="categoryImg != null and categoryImg != ''">category_img=#{categoryImg},</if>
+				<if test="categoryDiyUrl != null">category_diy_url=#{categoryDiyUrl},</if>
+				<if test="mdiyModelId != null and mdiyModelId != ''">mdiy_model_id=#{mdiyModelId},</if>
+				<if test="categoryDatetime != null">category_datetime=#{categoryDatetime},</if>
+				<if test="dictId != null">dict_id=#{dictId},</if>
+				<if test="categoryFlag != null ">category_flag=#{categoryFlag},</if>
+				<if test="categoryPath != null and categoryPath != ''">category_path=#{categoryPath},</if>
+				<if test="createBy &gt; 0">create_by=#{createBy},</if>
+				<if test="createDate != null">create_date=#{createDate},</if>
+				<if test="updateBy &gt; 0">update_by=#{updateBy},</if>
+				<if test="updateDate != null">update_date=#{updateDate},</if>
+				<if test="del != null">del=#{del},</if>
+			</set>
+			where id = #{id}
+		</update>
+
+	<!--根据id获取-->
+		<select id="getEntity" resultMap="resultMap" parameterType="int">
+			select * from cms_category where id=#{id}
+		</select>
+
+		<!--根据实体获取-->
+		<select id="getByEntity" resultMap="resultMap" parameterType="net.mingsoft.cms.entity.CategoryEntity">
+			select * from cms_category
+			<where>
+				<if test="categoryTitle != null and categoryTitle != ''">and category_title=#{categoryTitle}</if>
+				<if test="categoryPinyin != null and categoryPinyin != ''">and category_pinyin=#{categoryPinyin}</if>
+				<if test="categoryId != null and categoryId != ''">and category_id=#{categoryId}</if>
+				<if test="categoryType != null and categoryType != ''">and category_type=#{categoryType}</if>
+				<if test="categorySort != null"> and category_sort=#{categorySort} </if>
+				<if test="categoryListUrl != null and categoryListUrl != ''">and category_list_url=#{categoryListUrl}</if>
+				<if test="categoryUrl != null and categoryUrl != ''">and category_url=#{categoryUrl}</if>
+				<if test="categoryKeyword != null and categoryKeyword != ''">and category_keyword=#{categoryKeyword}</if>
+				<if test="categoryDescrip != null and categoryDescrip != ''">and category_descrip=#{categoryDescrip}</if>
+				<if test="categoryImg != null and categoryImg != ''">and category_img=#{categoryImg}</if>
+				<if test="categoryDiyUrl != null and categoryDiyUrl != ''">and category_diy_url=#{categoryDiyUrl}</if>
+				<if test="mdiyModelId != null and mdiyModelId != ''">and mdiy_model_id=#{mdiyModelId}</if>
+				<if test="categoryDatetime != null"> and category_datetime=#{categoryDatetime} </if>
+				<if test="dictId != null"> and dict_id=#{dictId} </if>
+				<if test="categoryFlag != null and categoryFlag != ''">and category_flag=#{categoryFlag}</if>
+				<if test="categoryPath != null and categoryPath != ''">and category_path=#{categoryPath}</if>
+				<if test="categoryParentIds != null and categoryParentIds != ''">and category_parent_ids=#{categoryParentIds}</if>
+				<if test="createBy &gt; 0"> and create_by=#{createBy} </if>
+				<if test="createDate != null"> and create_date=#{createDate} </if>
+				<if test="updateBy &gt; 0"> and update_by=#{updateBy} </if>
+				<if test="updateDate != null"> and update_date=#{updateDate} </if>
+				<if test="del != null"> and del=#{del} </if>
+			</where>
+			limit 0,1
+		</select>
+
+	<!-- 模糊查询开始 -->
+	<select id="queryChildren" resultMap="resultMap">
+		select * from cms_category
+		<where>
+
+			<if test="dictId &gt; 0">
+				and dict_id=#{dictId}
+			</if>
+			and
+			(
+			<if test="categoryParentIds != null and categoryParentIds!=''">
+				find_in_set(#{categoryParentIds},CATEGORY_PARENT_IDS)
+			</if>
+			<if test="categoryParentIds == null or  categoryParentIds ==''">
+				find_in_set('${id}',CATEGORY_PARENT_IDS)
+			</if>
+			<if test="id != null">
+				or id=#{id}
+			</if>
+			)
+			and del=0
+		</where>
+	</select>
+
+
+		<!--删除-->
+		<delete id="deleteEntity" parameterType="int">
+			delete from cms_category  where id=#{id}
+		</delete>
+
+		<!--批量删除-->
+		<delete id="delete" >
+			delete from cms_category
+			<where>
+				id  in <foreach collection="ids" item="item" index="index"
+										 open="(" separator="," close=")">#{item}</foreach>
+			</where>
+		</delete>
+		<!--查询全部-->
+		<select id="queryAll" resultMap="resultMap">
+			select * from cms_category order by id desc
+		</select>
+	<!--条件查询-->
+	<select id="query" resultMap="resultMap">
+		select * from cms_category
+		<where>
+			<if test="categoryTitle != null and categoryTitle != ''"> and category_title=#{categoryTitle}</if>
+			<if test="categoryPinyin != null and categoryPinyin != ''">and category_pinyin=#{categoryPinyin}</if>
+			<if test="categoryId != null and categoryId != ''"> and category_id=#{categoryId}</if>
+			<if test="categoryType != null and categoryType != ''"> and category_type=#{categoryType}</if>
+			<if test="categorySort != null"> and category_sort=#{categorySort} </if>
+			<if test="categoryListUrl != null and categoryListUrl != ''"> and category_list_url=#{categoryListUrl}</if>
+			<if test="categoryUrl != null and categoryUrl != ''"> and category_url=#{categoryUrl}</if>
+			<if test="categoryKeyword != null and categoryKeyword != ''"> and category_keyword=#{categoryKeyword}</if>
+			<if test="categoryDescrip != null and categoryDescrip != ''"> and category_descrip=#{categoryDescrip}</if>
+			<if test="categoryImg != null and categoryImg != ''"> and category_img=#{categoryImg}</if>
+			<if test="categoryDiyUrl != null and categoryDiyUrl != ''"> and category_diy_url=#{categoryDiyUrl}</if>
+			<if test="mdiyModelId != null and mdiyModelId != ''"> and mdiy_model_id=#{mdiyModelId}</if>
+			<if test="categoryDatetime != null"> and category_datetime=#{categoryDatetime} </if>
+			<if test="dictId != null"> and dict_id=#{dictId} </if>
+			<if test="categoryFlag != null and categoryFlag != ''"> and category_flag=#{categoryFlag}</if>
+			<if test="categoryPath != null and categoryPath != ''"> and category_path=#{categoryPath}</if>
+			<if test="categoryParentIds != null and categoryParentIds != ''"> and  find_in_set(#{categoryParentIds},category_parent_ids)</if>
+			<if test="createBy &gt; 0"> and create_by=#{createBy} </if>
+			<if test="createDate != null"> and create_date=#{createDate} </if>
+			<if test="updateBy &gt; 0"> and update_by=#{updateBy} </if>
+			<if test="updateDate != null"> and update_date=#{updateDate} </if>
+			<if test="del != null"> and del=#{del} </if>
+			<include refid="net.mingsoft.base.dao.IBaseDao.sqlWhere"></include>
+		</where>
+	</select>
+
+</mapper>

+ 12 - 0
src/main/java/net/mingsoft/cms/dao/ICmsHistoryLogDao.java

@@ -0,0 +1,12 @@
+package net.mingsoft.cms.dao;
+
+import net.mingsoft.base.dao.IBaseDao;
+
+/**
+ * 文章浏览记录持久层
+ * @author 铭飞开发团队
+ * 创建日期:2019-12-23 9:24:03<br/>
+ * 历史修订:<br/>
+ */
+public interface ICmsHistoryLogDao extends IBaseDao {
+}

+ 121 - 0
src/main/java/net/mingsoft/cms/dao/ICmsHistoryLogDao.xml

@@ -0,0 +1,121 @@
+<?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.ICmsHistoryLogDao">
+
+	<resultMap id="resultMap" type="net.mingsoft.cms.entity.HistoryLogEntity">
+			<id column="id" property="id" /><!--编号 -->
+				<result column="content_id" property="contentId" /><!--文章编号 -->
+				<result column="hl_ip" property="hlIp" /><!--浏览ip -->
+				<result column="people_id" property="peopleId" /><!--用户id -->
+				<result column="hl_is_mobile" property="hlIsMobile" /><!--是否为移动端 -->
+				<result column="create_by" property="createBy" /><!--创建人 -->
+				<result column="create_date" property="createDate" /><!--创建时间 -->
+				<result column="update_by" property="updateBy" /><!--修改人 -->
+				<result column="update_date" property="updateDate" /><!--修改时间 -->
+				<result column="del" property="del" /><!--删除标记 -->
+	</resultMap>
+
+	<!--保存-->
+	<insert id="saveEntity" useGeneratedKeys="true" keyProperty="id"
+			parameterType="net.mingsoft.cms.entity.HistoryLogEntity" >
+		insert into cms_history_log
+		<trim prefix="(" suffix=")" suffixOverrides=",">
+				<if test="contentId != null and contentId != ''">content_id,</if>
+				<if test="hlIp != null and hlIp != ''">hl_ip,</if>
+				<if test="peopleId != null and peopleId != ''">people_id,</if>
+				<if test="hlIsMobile != null">hl_is_mobile,</if>
+				<if test="createBy &gt; 0">create_by,</if>
+				<if test="createDate != null">create_date,</if>
+				<if test="updateBy &gt; 0">update_by,</if>
+				<if test="updateDate != null">update_date,</if>
+				<if test="del != null">del,</if>
+		</trim>
+		<trim prefix="values (" suffix=")" suffixOverrides=",">
+				<if test="contentId != null and contentId != ''">#{contentId},</if>
+				<if test="hlIp != null and hlIp != ''">#{hlIp},</if>
+				<if test="peopleId != null and peopleId != ''">#{peopleId},</if>
+				<if test="hlIsMobile != null">#{hlIsMobile},</if>
+				<if test="createBy &gt; 0">#{createBy},</if>
+				<if test="createDate != null">#{createDate},</if>
+				<if test="updateBy &gt; 0">#{updateBy},</if>
+				<if test="updateDate != null">#{updateDate},</if>
+				<if test="del != null">#{del},</if>
+		</trim>
+	</insert>
+
+		<!--更新-->
+		<update id="updateEntity" parameterType="net.mingsoft.cms.entity.HistoryLogEntity">
+			update cms_history_log
+			<set>
+				<if test="contentId != null and contentId != ''">content_id=#{contentId},</if>
+				<if test="hlIp != null and hlIp != ''">hl_ip=#{hlIp},</if>
+				<if test="peopleId != null and peopleId != ''">people_id=#{peopleId},</if>
+				<if test="hlIsMobile != null">hl_is_mobile=#{hlIsMobile},</if>
+				<if test="createBy &gt; 0">create_by=#{createBy},</if>
+				<if test="createDate != null">create_date=#{createDate},</if>
+				<if test="updateBy &gt; 0">update_by=#{updateBy},</if>
+				<if test="updateDate != null">update_date=#{updateDate},</if>
+				<if test="del != null">del=#{del},</if>
+			</set>
+			where id = #{id}
+		</update>
+
+		<!--根据id获取-->
+		<select id="getEntity" resultMap="resultMap" parameterType="int">
+			select * from cms_history_log where id=#{id}
+		</select>
+
+		<!--根据实体获取-->
+		<select id="getByEntity" resultMap="resultMap" parameterType="net.mingsoft.cms.entity.HistoryLogEntity">
+			select * from cms_history_log
+			<where>
+				<if test="contentId != null and contentId != ''">and content_id=#{contentId}</if>
+				<if test="hlIp != null and hlIp != ''">and hl_ip=#{hlIp}</if>
+				<if test="peopleId != null and peopleId != ''">and people_id=#{peopleId}</if>
+				<if test="hlIsMobile != null"> and hl_is_mobile=#{hlIsMobile} </if>
+				<if test="createBy &gt; 0"> and create_by=#{createBy} </if>
+				<if test="createDate != null"> and create_date=#{createDate} </if>
+				<if test="updateBy &gt; 0"> and update_by=#{updateBy} </if>
+				<if test="updateDate != null"> and update_date=#{updateDate} </if>
+				<if test="del != null"> and del=#{del} </if>
+			</where>
+			limit 0,1
+		</select>
+
+
+		<!--删除-->
+		<delete id="deleteEntity" parameterType="int">
+			delete from cms_history_log  where id=#{id}
+		</delete>
+
+		<!--批量删除-->
+		<delete id="delete" >
+			delete from cms_history_log
+			<where>
+				id  in <foreach collection="ids" item="item" index="index"
+										 open="(" separator="," close=")">#{item}</foreach>
+			</where>
+		</delete>
+		<!--查询全部-->
+		<select id="queryAll" resultMap="resultMap">
+			select * from cms_history_log order by id desc
+		</select>
+	<!--条件查询-->
+	<select id="query" resultMap="resultMap">
+		select * from cms_history_log
+		<where>
+			<if test="contentId != null and contentId != ''"> and content_id=#{contentId}</if>
+			<if test="hlIp != null and hlIp != ''"> and hl_ip=#{hlIp}</if>
+			<if test="peopleId != null and peopleId != ''"> and people_id=#{peopleId}</if>
+			<if test="hlIsMobile != null"> and hl_is_mobile=#{hlIsMobile} </if>
+			<if test="createBy &gt; 0"> and create_by=#{createBy} </if>
+			<if test="createDate != null"> and create_date=#{createDate} </if>
+			<if test="updateBy &gt; 0"> and update_by=#{updateBy} </if>
+			<if test="updateDate != null"> and update_date=#{updateDate} </if>
+			<if test="del != null"> and del=#{del} </if>
+			<include refid="net.mingsoft.base.dao.IBaseDao.sqlWhere"></include>
+		</where>
+		order by id desc
+	</select>
+
+</mapper>

+ 45 - 0
src/main/java/net/mingsoft/cms/dao/IContentDao.java

@@ -0,0 +1,45 @@
+package net.mingsoft.cms.dao;
+
+import net.mingsoft.base.dao.IBaseDao;
+import net.mingsoft.cms.bean.CategoryBean;
+import net.mingsoft.cms.bean.ContentBean;
+import net.mingsoft.cms.entity.ContentEntity;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 文章持久层
+ * @author 铭飞开发团队
+ * 创建日期:2019-11-28 15:12:32<br/>
+ * 历史修订:<br/>
+ */
+public interface IContentDao extends IBaseDao<ContentEntity> {
+
+    /**
+     * 查询文章编号集合
+     * @contentBean
+     * @return
+     */
+    public List<CategoryBean> queryIdsByCategoryIdForParser(ContentBean contentBean);
+
+    /**
+     * 根据查询文章实体总数
+     *
+     * @param tableName
+     *            :自定义生成的表名
+     * @param map
+     *            key:字段名 value:List 字段的各种判断值 list[0]:是否为自定义字段 list[1]:是否为整形
+     *            list[2]:是否是等值查询 list[3]:字段的值
+     * @return 文章实体总数
+     */
+    int getSearchCount(@Param("tableName") String tableName, @Param("diyList") List diyList, @Param("map") Map<String, Object> map,
+                       @Param("websiteId") int websiteId, @Param("ids") String ids);
+
+    /**
+     * 分类编号删除文章
+     * @param ids
+     */
+    void deleteEntityByCategoryIds(@Param("ids") String[] ids);
+}

+ 336 - 0
src/main/java/net/mingsoft/cms/dao/IContentDao.xml

@@ -0,0 +1,336 @@
+<?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.IContentDao">
+
+	<resultMap id="resultMap" type="net.mingsoft.cms.entity.ContentEntity">
+			<id column="id" property="id" /><!--编号 -->
+				<result column="content_title" property="contentTitle" /><!--文章标题 -->
+				<result column="category_id" property="categoryId" /><!--所属栏目 -->
+				<result column="content_type" property="contentType" /><!--文章类型 -->
+				<result column="content_display" property="contentDisplay" /><!--是否显示 -->
+				<result column="content_author" property="contentAuthor" /><!--文章作者 -->
+				<result column="content_source" property="contentSource" /><!--文章来源 -->
+				<result column="content_datetime" property="contentDatetime" /><!--发布时间 -->
+				<result column="content_sort" property="contentSort" /><!--自定义顺序 -->
+				<result column="content_img" property="contentImg" /><!--文章缩略图 -->
+				<result column="content_description" property="contentDescription" /><!--描述 -->
+				<result column="content_keyword" property="contentKeyword" /><!--关键字 -->
+				<result column="content_details" property="contentDetails" /><!--文章内容 -->
+				<result column="content_url" property="contentUrl" /><!--文章跳转链接地址 -->
+				<result column="content_hit" property="contentHit" /><!--点击次数 -->
+				<result column="create_by" property="createBy" /><!--创建人 -->
+				<result column="create_date" property="createDate" /><!--创建时间 -->
+				<result column="update_by" property="updateBy" /><!--修改人 -->
+				<result column="update_date" property="updateDate" /><!--修改时间 -->
+				<result column="del" property="del" /><!--删除标记 -->
+	</resultMap>
+
+	<resultMap id="resultContentMap" type="net.mingsoft.cms.bean.ContentBean">
+		<id column="id" property="id" /><!--编号 -->
+		<result column="content_title" property="contentTitle" /><!--文章标题 -->
+		<result column="category_id" property="categoryId" /><!--所属栏目 -->
+		<result column="content_type" property="contentType" /><!--文章类型 -->
+		<result column="content_display" property="contentDisplay" /><!--是否显示 -->
+		<result column="content_author" property="contentAuthor" /><!--文章作者 -->
+		<result column="content_source" property="contentSource" /><!--文章来源 -->
+		<result column="content_datetime" property="contentDatetime" /><!--发布时间 -->
+		<result column="content_sort" property="contentSort" /><!--自定义顺序 -->
+		<result column="content_img" property="contentImg" /><!--文章缩略图 -->
+		<result column="content_description" property="contentDescription" /><!--描述 -->
+		<result column="content_keyword" property="contentKeyword" /><!--关键字 -->
+		<result column="content_details" property="contentDetails" /><!--文章内容 -->
+		<result column="content_url" property="contentUrl" /><!--文章跳转链接地址 -->
+<!--		<result column="static_url" property="staticUrl" />&lt;!&ndash;静态地址 &ndash;&gt;-->
+		<result column="content_hit" property="contentHit" /><!--点击次数 -->
+		<result column="create_by" property="createBy" /><!--创建人 -->
+		<result column="create_date" property="createDate" /><!--创建时间 -->
+		<result column="update_by" property="updateBy" /><!--修改人 -->
+		<result column="update_date" property="updateDate" /><!--修改时间 -->
+		<result column="del" property="del" /><!--删除标记 -->
+	</resultMap>
+
+	<resultMap id="resultBean" type="net.mingsoft.cms.bean.CategoryBean">
+		<id column="id" property="id" /><!--编号 -->
+		<id column="article_Id" property="articleId" /><!--编号 -->
+		<result column="category_title" property="categoryTitle" /><!--栏目管理名称 -->
+		<result column="category_id" property="categoryId" /><!--所属栏目 -->
+		<result column="category_type" property="categoryType" /><!--栏目管理属性 -->
+		<result column="category_sort" property="categorySort" /><!--自定义顺序 -->
+		<result column="category_list_url" property="categoryListUrl" /><!--列表模板 -->
+		<result column="category_url" property="categoryUrl" /><!--内容模板 -->
+		<result column="category_keyword" property="categoryKeyword" /><!--栏目管理关键字 -->
+		<result column="category_descrip" property="categoryDescrip" /><!--栏目管理描述 -->
+		<result column="category_img" property="categoryImg" /><!--缩略图 -->
+		<result column="category_diy_url" property="categoryDiyUrl" /><!--自定义链接 -->
+		<result column="mdiy_model_id" property="mdiyModelId" /><!--栏目管理的内容模型id -->
+		<result column="category_datetime" property="categoryDatetime" /><!--类别发布时间 -->
+		<result column="dict_id" property="dictId" /><!--字典对应编号 -->
+		<result column="category_flag" property="categoryFlag" /><!--栏目属性 -->
+		<result column="category_path" property="categoryPath" /><!--栏目路径 -->
+		<result column="category_parent_ids" property="categoryParentIds" /><!--父类型编号 -->
+		<result column="create_by" property="createBy" /><!--创建人 -->
+		<result column="create_date" property="createDate" /><!--创建时间 -->
+		<result column="update_by" property="updateBy" /><!--修改人 -->
+		<result column="update_date" property="updateDate" /><!--修改时间 -->
+		<result column="del" property="del" /><!--删除标记 -->
+	</resultMap>
+
+	<!--保存-->
+	<insert id="saveEntity" useGeneratedKeys="true" keyProperty="id"
+			parameterType="net.mingsoft.cms.entity.ContentEntity" >
+		insert into cms_content
+		<trim prefix="(" suffix=")" suffixOverrides=",">
+				<if test="contentTitle != null and contentTitle != ''">content_title,</if>
+				<if test="categoryId != null and categoryId != ''">category_id,</if>
+				<if test="contentType != null ">content_type,</if>
+				<if test="contentDisplay != null and contentDisplay != ''">content_display,</if>
+				<if test="contentAuthor != null and contentAuthor != ''">content_author,</if>
+				<if test="contentSource != null and contentSource != ''">content_source,</if>
+				<if test="contentDatetime != null">content_datetime,</if>
+				<if test="contentSort != null">content_sort,</if>
+				<if test="contentImg != null and contentImg != ''">content_img,</if>
+				<if test="contentDescription != null and contentDescription != ''">content_description,</if>
+				<if test="contentKeyword != null and contentKeyword != ''">content_keyword,</if>
+				<if test="contentDetails != null and contentDetails != ''">content_details,</if>
+				<if test="contentUrl != null and contentUrl != ''">content_url,</if>
+				<if test="contentHit != null">content_hit,</if>
+				<if test="createBy &gt; 0">create_by,</if>
+				<if test="createDate != null">create_date,</if>
+				<if test="updateBy &gt; 0">update_by,</if>
+				<if test="updateDate != null">update_date,</if>
+				<if test="del != null">del,</if>
+		</trim>
+		<trim prefix="values (" suffix=")" suffixOverrides=",">
+				<if test="contentTitle != null and contentTitle != ''">#{contentTitle},</if>
+				<if test="categoryId != null and categoryId != ''">#{categoryId},</if>
+				<if test="contentType != null ">#{contentType},</if>
+				<if test="contentDisplay != null and contentDisplay != ''">#{contentDisplay},</if>
+				<if test="contentAuthor != null and contentAuthor != ''">#{contentAuthor},</if>
+				<if test="contentSource != null and contentSource != ''">#{contentSource},</if>
+				<if test="contentDatetime != null">#{contentDatetime},</if>
+				<if test="contentSort != null">#{contentSort},</if>
+				<if test="contentImg != null and contentImg != ''">#{contentImg},</if>
+				<if test="contentDescription != null and contentDescription != ''">#{contentDescription},</if>
+				<if test="contentKeyword != null and contentKeyword != ''">#{contentKeyword},</if>
+				<if test="contentDetails != null and contentDetails != ''">#{contentDetails},</if>
+				<if test="contentUrl != null and contentUrl != ''">#{contentUrl},</if>
+				<if test="contentHit != null">#{contentHit},</if>
+				<if test="createBy &gt; 0">#{createBy},</if>
+				<if test="createDate != null">#{createDate},</if>
+				<if test="updateBy &gt; 0">#{updateBy},</if>
+				<if test="updateDate != null">#{updateDate},</if>
+				<if test="del != null">#{del},</if>
+		</trim>
+	</insert>
+
+		<!--更新-->
+		<update id="updateEntity" parameterType="net.mingsoft.cms.entity.ContentEntity">
+			update cms_content
+			<set>
+				<if test="contentTitle != null and contentTitle != ''">content_title=#{contentTitle},</if>
+				<if test="categoryId != null and categoryId != ''">category_id=#{categoryId},</if>
+				<if test="contentType != null ">content_type=#{contentType},</if>
+				<if test="contentDisplay != null and contentDisplay != ''">content_display=#{contentDisplay},</if>
+				<if test="contentAuthor != null ">content_author=#{contentAuthor},</if>
+				<if test="contentSource != null ">content_source=#{contentSource},</if>
+				<if test="contentDatetime != null">content_datetime=#{contentDatetime},</if>
+				<if test="contentSort != null">content_sort=#{contentSort},</if>
+				<if test="contentImg != null and contentImg != ''">content_img=#{contentImg},</if>
+				<if test="contentDescription != null ">content_description=#{contentDescription},</if>
+				<if test="contentKeyword != null ">content_keyword=#{contentKeyword},</if>
+				<if test="contentDetails != null ">content_details=#{contentDetails},</if>
+				<if test="contentUrl != null and contentUrl != ''">content_url=#{contentUrl},</if>
+				<if test="contentHit != null">content_hit=#{contentHit},</if>
+				<if test="createBy &gt; 0">create_by=#{createBy},</if>
+				<if test="createDate != null">create_date=#{createDate},</if>
+				<if test="updateBy &gt; 0">update_by=#{updateBy},</if>
+				<if test="updateDate != null">update_date=#{updateDate},</if>
+				<if test="del != null">del=#{del},</if>
+			</set>
+			where id = #{id}
+		</update>
+
+		<!--根据id获取-->
+		<select id="getEntity" resultMap="resultMap" parameterType="int">
+			select * from cms_content where id=#{id} and del=0
+		</select>
+
+		<!--根据实体获取-->
+		<select id="getByEntity" resultMap="resultMap" parameterType="net.mingsoft.cms.entity.ContentEntity">
+			select * from cms_content
+			<where>
+				del=0
+				<if test="contentTitle != null and contentTitle != ''">and  content_title like CONCAT('%',#{contentTitle},'%')</if>
+				<if test="categoryId != null and categoryId != ''">and category_id=#{categoryId}</if>
+				<if test="contentType != null and contentType != ''">and content_type=#{contentType}</if>
+				<if test="contentDisplay != null and contentDisplay != ''">and content_display=#{contentDisplay}</if>
+				<if test="contentAuthor != null and contentAuthor != ''">and content_author=#{contentAuthor}</if>
+				<if test="contentSource != null and contentSource != ''">and content_source=#{contentSource}</if>
+				<if test="contentDatetime != null"> and content_datetime=#{contentDatetime} </if>
+				<if test="contentSort != null"> and content_sort=#{contentSort} </if>
+				<if test="contentImg != null and contentImg != ''">and content_img=#{contentImg}</if>
+				<if test="contentDescription != null and contentDescription != ''">and content_description=#{contentDescription}</if>
+				<if test="contentKeyword != null and contentKeyword != ''">and content_keyword=#{contentKeyword}</if>
+				<if test="contentDetails != null and contentDetails != ''">and content_details=#{contentDetails}</if>
+				<if test="contentUrl != null and contentUrl != ''">and content_url=#{contentUrl}</if>
+				<if test="contentHit != null">and content_hit=#{contentHit}</if>
+				<if test="createBy &gt; 0"> and create_by=#{createBy} </if>
+				<if test="createDate != null"> and create_date=#{createDate} </if>
+				<if test="updateBy &gt; 0"> and update_by=#{updateBy} </if>
+				<if test="updateDate != null"> and update_date=#{updateDate} </if>
+			</where>
+			limit 0,1
+		</select>
+
+
+		<!--删除-->
+		<delete id="deleteEntity" parameterType="int">
+			update  cms_content set del=1  where id=#{id}
+		</delete>
+
+		<!--删除-->
+		<delete id="deleteEntityByCategoryIds" >
+			update  cms_content set del=1
+			<where>
+				category_id  in <foreach collection="ids" item="item" index="index"
+							open="(" separator="," close=")">#{item}</foreach>
+			</where>
+		</delete>
+
+		<!--批量删除-->
+		<delete id="delete" >
+			update  cms_content set del=1
+			<where>
+				id  in <foreach collection="ids" item="item" index="index"
+										 open="(" separator="," close=")">#{item}</foreach>
+			</where>
+		</delete>
+		<!--查询全部-->
+		<select id="queryAll" resultMap="resultMap">
+			select * from cms_content where del=0 order by id desc
+		</select>
+	<!--条件查询-->
+	<select id="query" resultMap="resultContentMap">
+		<!--,CONCAT('/html/',ct.app_id,category_path,'/',ct.id,'.html') AS static_url-->
+		select ct.* from (
+		select ct.*,cc.category_path from cms_content ct
+		join cms_category cc on ct.category_id=cc.id
+		<where>
+			ct.del=0
+			<if test="contentTitle != null and contentTitle != ''"> and  content_title like CONCAT('%',#{contentTitle},'%')</if>
+			<if test="categoryId != null and categoryId != ''"> 	and (ct.category_id=#{categoryId} or ct.category_id in
+				(select id FROM cms_category where find_in_set('${categoryId}',CATEGORY_PARENT_IDS)))</if>
+			<if test="contentType != null and contentType != ''"> and content_type LIKE CONCAT('%',#{contentType},'%')</if>
+			<if test="contentDisplay != null and contentDisplay != ''"> and content_display=#{contentDisplay}</if>
+			<if test="contentAuthor != null and contentAuthor != ''"> and content_author=#{contentAuthor}</if>
+			<if test="contentSource != null and contentSource != ''"> and content_source=#{contentSource}</if>
+			<if test="contentDatetime != null"> and content_datetime=#{contentDatetime} </if>
+			<if test="contentSort != null"> and content_sort=#{contentSort} </if>
+			<if test="contentImg != null and contentImg != ''"> and content_img=#{contentImg}</if>
+			<if test="contentDescription != null and contentDescription != ''"> and content_description=#{contentDescription}</if>
+			<if test="contentKeyword != null and contentKeyword != ''"> and content_keyword=#{contentKeyword}</if>
+			<if test="contentDetails != null and contentDetails != ''"> and content_details=#{contentDetails}</if>
+			<if test="contentUrl != null and contentUrl != ''"> and content_url=#{contentUrl}</if>
+			<if test="contentHit != null"> and content_hit=#{contentHit}</if>
+			<if test="createBy &gt; 0"> and ct.create_by=#{createBy} </if>
+			<if test="createDate != null"> and ct.create_date=#{createDate} </if>
+			<if test="updateBy &gt; 0"> and ct.update_by=#{updateBy} </if>
+			<if test="updateDate != null"> and update_date=#{updateDate} </if>
+		</where>
+		)ct ORDER BY ct.content_datetime desc,content_sort desc
+	</select>
+
+	<!-- 根据站点编号、开始、结束时间和栏目编号查询文章编号集合 -->
+	<select id="queryIdsByCategoryIdForParser" resultMap="resultBean" >
+			select
+			ct.id article_id,c.*
+			FROM cms_content ct
+			LEFT JOIN cms_category c ON ct.category_id = c.id
+			where ct.del=0
+
+			<!-- 查询子栏目数据 -->
+			<if test="categoryId &gt; 0">
+				and (ct.category_id=#{categoryId} or ct.category_id in
+				(select id FROM cms_category where find_in_set('${categoryId}',CATEGORY_PARENT_IDS)))
+			</if>
+			<if test="beginTime!=null and beginTime!=''">
+				and content_datetime &gt;= #{beginTime}
+			</if>
+			<if test="endTime!=null and endTime!=''">
+				and content_datetime &gt;= #{endTime}
+			</if>
+			<if test="flag!=null and flag!=''">
+			and ct.content_type in ( #{flag})
+			</if>
+			<if  test="noflag!=null and noflag!=''">
+			and (ct.content_type not in ( #{noflag}  ) or ct.content_type is null)
+			</if>
+			<if test="orderBy!=null  and orderBy!='' ">
+				<if test="orderBy=='date'">ORDER BY content_datetime</if>
+				<if test="orderBy=='hit'">ORDER BY content_hit</if>
+				<if test="orderBy=='sort'">ORDER BY content_sort</if>
+				<if  test="orderBy!='date' and orderBy!='hit' and orderBy!='sort'">
+					ORDER BY ct.id
+				</if>
+				<choose>
+					<when test="order!=null and order!=''">
+						${order}
+					</when>
+					<otherwise>
+						desc
+					</otherwise>
+				</choose>
+			</if>
+
+	</select>
+	<select id="getSearchCount" resultType="int">
+		select count(*) from
+		cms_content a
+		left join cms_category c
+		ON a.category_id
+		= c.id
+		<if test="tableName!=null and tableName!='' and diyMap!=null">left join ${tableName} d on d.link_id=a.id
+		</if>
+		<where>
+			a.del=0
+			<if test="ids!=null and ids!=''">
+				and FIND_IN_SET(a.category_id,#{ids})
+			</if>
+			<if test="map.content_title!=null">
+			and a.content_title like CONCAT("%",#{map.content_title},"%")
+			</if>
+			<if test="map.content_author!=null">
+			and a.content_author like CONCAT("%",#{map.content_author},"%")
+			</if>
+			<if test="map.content_source!=null">
+			and a.content_source like CONCAT("%",#{map.content_source},"%")
+			</if>
+			<if test="map.content_type!=null">
+				and <foreach item="item" index="index" collection="map.content_type.split(',')"  open="(" separator="or" close=")">
+					FIND_IN_SET('${item}',a.content_type)
+				</foreach>
+			</if>
+			<if test="map.content_description!=null">
+			and a.content_description like CONCAT("%",#{map.content_description},"%")
+			</if>
+			<if test="map.content_keyword!=null">
+			and a.content_keyword like CONCAT("%",#{map.content_keyword},"%")
+			</if>
+			<if test="map.content_details!=null">
+			and a.content_details like CONCAT("%",#{map.content_details},"%")
+			</if>
+			<if test="map.content_datetime_start!=null and map.content_datetime_end!=null">
+				and a.content_datetime between #{map.content_datetime_start} and #{map.content_datetime_end}
+			</if>
+			<if test="tableName!=null and tableName!='' and diyMap!=null">
+				<foreach item="item" index="index" collection="diyList" open=""
+						 separator="" close="">
+					and d.${field.key} like CONCAT("%",#{item.value},"%")
+				</foreach>
+			</if>
+		</where>
+
+	</select>
+
+
+</mapper>

+ 416 - 0
src/main/java/net/mingsoft/cms/entity/CategoryEntity.java

@@ -0,0 +1,416 @@
+package net.mingsoft.cms.entity;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.annotation.JSONField;
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import net.mingsoft.base.entity.BaseEntity;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+/**
+ * 分类实体
+ *
+ * @author 铭飞开发团队
+ * 创建日期:2019-11-28 15:12:32<br/>
+ * 历史修订:<br/>
+ */
+@TableName("cms_category")
+public class CategoryEntity extends BaseEntity {
+
+    private static final long serialVersionUID = 1574925152750L;
+
+    /**
+     * 栏目管理名称
+     */
+    private String categoryTitle;
+    /**
+     * 栏目别名
+     */
+    private String categoryPinyin;
+    /**
+     * 所属栏目
+     */
+    @TableField(insertStrategy = FieldStrategy.NOT_EMPTY, updateStrategy = FieldStrategy.NOT_EMPTY, whereStrategy = FieldStrategy.NOT_EMPTY)
+    private String categoryId;
+    /**
+     * 栏目管理属性
+     */
+    private String categoryType;
+    /**
+     * 自定义顺序
+     */
+    private Integer categorySort;
+    /**
+     * 列表模板
+     */
+    private String categoryListUrl;
+    /**
+     * 内容模板
+     */
+    private String categoryUrl;
+    /**
+     * 栏目管理关键字
+     */
+    private String categoryKeyword;
+    /**
+     * 栏目管理描述
+     */
+    private String categoryDescrip;
+    /**
+     * 缩略图
+     */
+    private String categoryImg;
+    /**
+     * 自定义链接
+     */
+    private String categoryDiyUrl;
+    /**
+     * 栏目管理的内容模型id
+     */
+    private Integer mdiyModelId;
+    /**
+     * 类别发布时间
+     */
+    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date categoryDatetime;
+
+    /**
+     * 字典对应编号
+     */
+    private Integer dictId;
+    /**
+     * 栏目属性
+     */
+    private String categoryFlag;
+    /**
+     * 栏目路径
+     */
+    private String categoryPath;
+    /**
+     * 父类型编号
+     */
+    private String categoryParentIds;
+
+    /**
+     * 叶子节点
+     */
+    private Boolean leaf;
+
+    /**
+     * 顶级id
+     */
+    private String topId;
+
+    public Boolean getLeaf() {
+        return leaf;
+    }
+
+    public void setLeaf(Boolean leaf) {
+        this.leaf = leaf;
+    }
+
+    public String getTopId() {
+        return topId;
+    }
+
+    public void setTopId(String topId) {
+        this.topId = topId;
+    }
+
+    /**
+     * 设置栏目管理名称
+     */
+    public void setCategoryTitle(String categoryTitle) {
+        this.categoryTitle = categoryTitle;
+    }
+
+    /**
+     * 获取栏目管理名称
+     */
+    public String getCategoryTitle() {
+        return this.categoryTitle;
+    }
+
+    /**
+     * 设置所属栏目
+     */
+    public void setCategoryId(String categoryId) {
+        this.categoryId = categoryId;
+    }
+
+    public String getCategoryPinyin() {
+        return categoryPinyin;
+    }
+
+    public void setCategoryPinyin(String categoryPinyin) {
+        this.categoryPinyin = categoryPinyin;
+    }
+
+    /**
+     * 获取所属栏目
+     */
+    public String getCategoryId() {
+        return this.categoryId;
+    }
+
+    /**
+     * 设置栏目管理属性
+     */
+    public void setCategoryType(String categoryType) {
+        this.categoryType = categoryType;
+    }
+
+    /**
+     * 获取栏目管理属性
+     */
+    public String getCategoryType() {
+        return this.categoryType;
+    }
+
+    /**
+     * 设置自定义顺序
+     */
+    public void setCategorySort(Integer categorySort) {
+        this.categorySort = categorySort;
+    }
+
+    /**
+     * 获取自定义顺序
+     */
+    public Integer getCategorySort() {
+        return this.categorySort;
+    }
+
+    /**
+     * 设置列表模板
+     */
+    public void setCategoryListUrl(String categoryListUrl) {
+        this.categoryListUrl = categoryListUrl;
+    }
+
+    /**
+     * 获取列表模板
+     */
+    public String getCategoryListUrl() {
+        return this.categoryListUrl;
+    }
+
+    /**
+     * 设置内容模板
+     */
+    public void setCategoryUrl(String categoryUrl) {
+        this.categoryUrl = categoryUrl;
+    }
+
+    /**
+     * 获取内容模板
+     */
+    public String getCategoryUrl() {
+        return this.categoryUrl;
+    }
+
+    /**
+     * 设置栏目管理关键字
+     */
+    public void setCategoryKeyword(String categoryKeyword) {
+        this.categoryKeyword = categoryKeyword;
+    }
+
+    /**
+     * 获取栏目管理关键字
+     */
+    public String getCategoryKeyword() {
+        return this.categoryKeyword;
+    }
+
+    /**
+     * 设置栏目管理描述
+     */
+    public void setCategoryDescrip(String categoryDescrip) {
+        this.categoryDescrip = categoryDescrip;
+    }
+
+    /**
+     * 获取栏目管理描述
+     */
+    public String getCategoryDescrip() {
+        return this.categoryDescrip;
+    }
+
+    /**
+     * 设置缩略图
+     */
+    public void setCategoryImg(String categoryImg) {
+        this.categoryImg = categoryImg;
+    }
+
+    /**
+     * 获取缩略图
+     */
+    public String getCategoryImg() {
+        return this.categoryImg;
+    }
+
+    /**
+     * 设置自定义链接
+     */
+    public void setCategoryDiyUrl(String categoryDiyUrl) {
+        this.categoryDiyUrl = categoryDiyUrl;
+    }
+
+    /**
+     * 获取自定义链接
+     */
+    public String getCategoryDiyUrl() {
+        return this.categoryDiyUrl;
+    }
+
+    public Integer getMdiyModelId() {
+        return mdiyModelId;
+    }
+
+    public void setMdiyModelId(Integer mdiyModelId) {
+        this.mdiyModelId = mdiyModelId;
+    }
+
+    /**
+     * 设置类别发布时间
+     */
+    public void setCategoryDatetime(Date categoryDatetime) {
+        this.categoryDatetime = categoryDatetime;
+    }
+
+    /**
+     * 获取类别发布时间
+     */
+    public Date getCategoryDatetime() {
+        return this.categoryDatetime;
+    }
+
+    /**
+     * 设置字典对应编号
+     */
+    public void setDictId(Integer dictId) {
+        this.dictId = dictId;
+    }
+
+    /**
+     * 获取字典对应编号
+     */
+    public Integer getDictId() {
+        return this.dictId;
+    }
+
+    /**
+     * 设置栏目属性
+     */
+    public void setCategoryFlag(String categoryFlag) {
+        this.categoryFlag = categoryFlag;
+    }
+
+    /**
+     * 获取栏目属性
+     */
+    public String getCategoryFlag() {
+        return this.categoryFlag;
+    }
+
+    /**
+     * 设置栏目路径
+     */
+    public void setCategoryPath(String categoryPath) {
+        this.categoryPath = categoryPath;
+    }
+
+    /**
+     * 获取栏目路径
+     */
+    public String getCategoryPath() {
+        return this.categoryPath;
+    }
+
+    /**
+     * 设置父类型编号
+     */
+    public void setCategoryParentIds(String categoryParentIds) {
+        this.categoryParentIds = categoryParentIds;
+    }
+
+    /**
+     * 获取父类型编号
+     */
+    public String getCategoryParentIds() {
+        return this.categoryParentIds;
+    }
+
+    /**
+     * 获取栏目标题 (标签使用)
+     */
+    public String getTypetitle() {
+        return this.categoryTitle;
+    }
+
+    /**
+     * 获取栏目链接 (标签使用,动态链接不考虑)
+     */
+    public String getTypelink() {
+        return "3".equals(this.categoryType) ? this.categoryDiyUrl : this.categoryPath + "/index.html";
+    }
+
+    /**
+     * 获取栏目关键字 (标签使用)
+     */
+    public String getTypekeyword() {
+        return this.categoryKeyword;
+    }
+
+    /**
+     * 获取栏目url (标签使用)
+     */
+    public String getTypeurl() {
+        return this.categoryDiyUrl;
+    }
+
+    /**
+     * 获取栏目属性 (标签使用)
+     */
+    public String getFlag() {
+        return this.categoryFlag;
+    }
+
+    /**
+     * 获取栏目父级Id (标签使用)
+     */
+    public String getParentids() {
+        return this.categoryParentIds;
+    }
+
+    /**
+     * 获取栏目描述(标签使用)
+     */
+    public String getTypedescrip() {
+        return this.categoryDescrip;
+    }
+
+    /**
+     * 获取栏目Id(标签使用)
+     */
+    public String getTypeid() {
+        return this.id;
+    }
+
+    /**
+     * 获取栏目图片 (标签使用)
+     */
+    public String getTypelitpic() {
+        return categoryImg;
+    }
+}

+ 261 - 0
src/main/java/net/mingsoft/cms/entity/ContentEntity.java

@@ -0,0 +1,261 @@
+package net.mingsoft.cms.entity;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import net.mingsoft.base.entity.BaseEntity;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+/**
+* 文章实体
+* @author 铭飞开发团队
+* 创建日期:2019-11-28 15:12:32<br/>
+* 历史修订:<br/>
+*/
+@TableName("cms_content")
+public class ContentEntity extends BaseEntity {
+
+private static final long serialVersionUID = 1574925152617L;
+
+	/**
+	* 文章标题
+	*/
+	private String contentTitle;
+	/**
+	* 所属栏目
+	*/
+	private String categoryId;
+	/**
+	* 文章类型
+	*/
+	private String contentType;
+	/**
+	* 是否显示
+	*/
+	private String contentDisplay;
+	/**
+	* 文章作者
+	*/
+	private String contentAuthor;
+	/**
+	* 文章来源
+	*/
+	private String contentSource;
+	/**
+	* 发布时间
+	*/
+	@JSONField(format = "yyyy-MM-dd HH:mm:ss")
+	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+	private Date contentDatetime;
+	/**
+	* 自定义顺序
+	*/
+	private Integer contentSort;
+	/**
+	* 文章缩略图
+	*/
+	private String contentImg;
+	/**
+	* 描述
+	*/
+	private String contentDescription;
+	/**
+	* 关键字
+	*/
+	private String contentKeyword;
+	/**
+	* 文章内容
+	*/
+	private String contentDetails;
+	/**
+	* 文章跳转链接地址
+	*/
+	private String contentUrl;
+	/**
+	* 文章管理的应用id
+	*/
+
+	/**
+	* 点击次数
+	*/
+	private Integer contentHit;
+
+	public Integer getContentHit() {
+		return contentHit;
+	}
+
+	public void setContentHit(Integer contentHit) {
+		this.contentHit = contentHit;
+	}
+
+	/**
+	* 设置文章标题
+	*/
+	public void setContentTitle(String contentTitle) {
+	this.contentTitle = contentTitle;
+	}
+
+	/**
+	* 获取文章标题
+	*/
+	public String getContentTitle() {
+	return this.contentTitle;
+	}
+
+	public String getCategoryId() {
+		return categoryId;
+	}
+
+	public void setCategoryId(String categoryId) {
+		this.categoryId = categoryId;
+	}
+
+	/**
+	* 设置文章类型
+	*/
+	public void setContentType(String contentType) {
+	this.contentType = contentType;
+	}
+
+	/**
+	* 获取文章类型
+	*/
+	public String getContentType() {
+	return this.contentType;
+	}
+	/**
+	* 设置是否显示
+	*/
+	public void setContentDisplay(String contentDisplay) {
+	this.contentDisplay = contentDisplay;
+	}
+
+	/**
+	* 获取是否显示
+	*/
+	public String getContentDisplay() {
+	return this.contentDisplay;
+	}
+	/**
+	* 设置文章作者
+	*/
+	public void setContentAuthor(String contentAuthor) {
+	this.contentAuthor = contentAuthor;
+	}
+
+	/**
+	* 获取文章作者
+	*/
+	public String getContentAuthor() {
+	return this.contentAuthor;
+	}
+	/**
+	* 设置文章来源
+	*/
+	public void setContentSource(String contentSource) {
+	this.contentSource = contentSource;
+	}
+
+	/**
+	* 获取文章来源
+	*/
+	public String getContentSource() {
+	return this.contentSource;
+	}
+	/**
+	* 设置发布时间
+	*/
+	public void setContentDatetime(Date contentDatetime) {
+	this.contentDatetime = contentDatetime;
+	}
+
+	/**
+	* 获取发布时间
+	*/
+	public Date getContentDatetime() {
+	return this.contentDatetime;
+	}
+	/**
+	* 设置自定义顺序
+	*/
+	public void setContentSort(Integer contentSort) {
+	this.contentSort = contentSort;
+	}
+
+	/**
+	* 获取自定义顺序
+	*/
+	public Integer getContentSort() {
+	return this.contentSort;
+	}
+	/**
+	* 设置文章缩略图
+	*/
+	public void setContentImg(String contentImg) {
+	this.contentImg = contentImg;
+	}
+
+	/**
+	* 获取文章缩略图
+	*/
+	public String getContentImg() {
+	return this.contentImg;
+	}
+	/**
+	* 设置描述
+	*/
+	public void setContentDescription(String contentDescription) {
+	this.contentDescription = contentDescription;
+	}
+
+	/**
+	* 获取描述
+	*/
+	public String getContentDescription() {
+	return this.contentDescription;
+	}
+	/**
+	* 设置关键字
+	*/
+	public void setContentKeyword(String contentKeyword) {
+	this.contentKeyword = contentKeyword;
+	}
+
+	/**
+	* 获取关键字
+	*/
+	public String getContentKeyword() {
+	return this.contentKeyword;
+	}
+	/**
+	* 设置文章内容
+	*/
+	public void setContentDetails(String contentDetails) {
+	this.contentDetails = contentDetails;
+	}
+
+	/**
+	* 获取文章内容
+	*/
+	public String getContentDetails() {
+	return this.contentDetails;
+	}
+	/**
+	* 设置文章跳转链接地址
+	*/
+	public void setContentUrl(String contentUrl) {
+	this.contentUrl = contentUrl;
+	}
+
+	/**
+	* 获取文章跳转链接地址
+	*/
+	public String getContentUrl() {
+	return this.contentUrl;
+	}
+
+}

+ 84 - 0
src/main/java/net/mingsoft/cms/entity/HistoryLogEntity.java

@@ -0,0 +1,84 @@
+package net.mingsoft.cms.entity;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import org.springframework.format.annotation.DateTimeFormat;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import net.mingsoft.base.entity.BaseEntity;
+import java.util.Date;
+/**
+* 文章浏览记录实体
+* @author 铭飞开发团队
+* 创建日期:2019-12-23 9:24:03<br/>
+* 历史修订:<br/>
+*/
+public class HistoryLogEntity extends BaseEntity {
+
+private static final long serialVersionUID = 1577064243576L;
+
+	/**
+	* 文章编号
+	*/
+	private String contentId;
+	/**
+	* 浏览ip
+	*/
+	private String hlIp;
+	/**
+	* 用户idp
+	*/
+	private String peopleId;
+	/**
+	* 是否为移动端
+	*/
+	private Boolean hlIsMobile;
+
+
+	/**
+	* 设置文章编号
+	*/
+	public void setContentId(String contentId) {
+	this.contentId = contentId;
+	}
+
+	/**
+	* 获取文章编号
+	*/
+	public String getContentId() {
+	return this.contentId;
+	}
+	/**
+	* 设置浏览ip
+	*/
+	public void setHlIp(String hlIp) {
+	this.hlIp = hlIp;
+	}
+
+	/**
+	* 获取浏览ip
+	*/
+	public String getHlIp() {
+	return this.hlIp;
+	}
+
+	public String getPeopleId() {
+		return peopleId;
+	}
+
+	public void setPeopleId(String peopleId) {
+		this.peopleId = peopleId;
+	}
+
+	/**
+	* 设置是否为移动端
+	*/
+	public void setHlIsMobile(Boolean hlIsMobile) {
+	this.hlIsMobile = hlIsMobile;
+	}
+
+	/**
+	* 获取是否为移动端
+	*/
+	public Boolean getHlIsMobile() {
+	return this.hlIsMobile;
+	}
+}

+ 37 - 0
src/main/java/net/mingsoft/cms/resources/resources_en_US.properties

@@ -0,0 +1,37 @@
+#
+#Thu Nov 28 15:12:32 CST 2019
+category.img=Thumbnail
+appid=The application id of article management
+content.datetime=Publishing time
+category.manager.id=Posting user id
+category.title=Column management name
+category.keyword=Column management keyword
+content.img=Article thumbnail
+category.path=Column path
+content.type=Article type
+category.url=Content template
+dict.id=Dictionary corresponding number
+content.author=Article author
+category.parent.id=Parent type number
+category.datetime=Category publication time
+category.flag =Column attribute
+content.description=Description
+content.url=Article jump link address
+category.sort=Custom order
+content.title=Article title
+content.category.id=belongingcolumn
+id=number
+app.id=application number
+category.list.url=List template
+mdiy.model.id=Content model id for column management
+content.source=The source of the article
+content.display=Whether to display
+category.type=Column management attribute
+category.descrip=Column management description
+content.details=Article content
+category.id=belonging to the column
+content.sort=custom order
+category.diy.url=custom link
+content.keyword=keyword
+templet.file=template file not found
+category.pinyin=pinyin

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

@@ -0,0 +1,37 @@
+#
+#Thu Nov 28 15:12:32 CST 2019
+category.img=\u7F29\u7565\u56FE
+appid=\u6587\u7AE0\u7BA1\u7406\u7684\u5E94\u7528id
+content.datetime=\u53D1\u5E03\u65F6\u95F4
+category.manager.id=\u53D1\u5E03\u7528\u6237id
+category.title=\u680F\u76EE\u7BA1\u7406\u540D\u79F0
+category.keyword=\u680F\u76EE\u7BA1\u7406\u5173\u952E\u5B57
+content.img=\u6587\u7AE0\u7F29\u7565\u56FE
+category.path=\u680F\u76EE\u8DEF\u5F84
+content.type=\u6587\u7AE0\u7C7B\u578B
+category.url=\u5185\u5BB9\u6A21\u677F
+dict.id=\u5B57\u5178\u5BF9\u5E94\u7F16\u53F7
+content.author=\u6587\u7AE0\u4F5C\u8005
+category.parent.id=\u7236\u7C7B\u578B\u7F16\u53F7
+category.datetime=\u7C7B\u522B\u53D1\u5E03\u65F6\u95F4
+category.flag=\u680F\u76EE\u5C5E\u6027
+content.description=\u63CF\u8FF0
+content.url=\u6587\u7AE0\u8DF3\u8F6C\u94FE\u63A5\u5730\u5740
+category.sort=\u81EA\u5B9A\u4E49\u987A\u5E8F
+content.title=\u6587\u7AE0\u6807\u9898
+content.category.id=\u6240\u5C5E\u680F\u76EE
+id=\u7F16\u53F7
+app.id=\u5E94\u7528\u7F16\u53F7
+category.list.url=\u5217\u8868\u6A21\u677F
+mdiy.model.id=\u680F\u76EE\u7BA1\u7406\u7684\u5185\u5BB9\u6A21\u578Bid
+content.source=\u6587\u7AE0\u6765\u6E90
+content.display=\u662F\u5426\u663E\u793A
+category.type=\u680F\u76EE\u7BA1\u7406\u5C5E\u6027
+category.descrip=\u680F\u76EE\u7BA1\u7406\u63CF\u8FF0
+content.details=\u6587\u7AE0\u5185\u5BB9
+category.id=\u6240\u5C5E\u680F\u76EE
+content.sort=\u81EA\u5B9A\u4E49\u987A\u5E8F
+category.diy.url=\u81EA\u5B9A\u4E49\u94FE\u63A5
+content.keyword=\u5173\u952E\u5B57
+templet.file=\u672A\u627E\u5230\u6A21\u677F\u6587\u4EF6
+category.pinyin=\u62FC\u97F3

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

@@ -0,0 +1,290 @@
+package net.mingsoft.cms.util;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.FileUtil;
+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.holder.DataHolder;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.basic.util.SpringUtil;
+import net.mingsoft.cms.bean.CategoryBean;
+import net.mingsoft.cms.constant.e.CategoryTypeEnum;
+import net.mingsoft.cms.entity.CategoryEntity;
+import net.mingsoft.mdiy.bean.PageBean;
+import net.mingsoft.mdiy.biz.IModelBiz;
+import net.mingsoft.mdiy.biz.impl.ModelBizImpl;
+import net.mingsoft.mdiy.entity.ModelEntity;
+import net.mingsoft.mdiy.util.ParserUtil;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+
+/**
+ * 文章解析工具类
+ */
+public class CmsParserUtil {
+
+
+    private final static String FIELD = "field";
+
+    /**
+     * 指定模板,指定路径进行生成静态页面,会自定识别pc与移动端
+     *
+     * @param templatePath 模板路径
+     * @param targetPath   生成后的路径,默认生成的html文件,所以不能带.html后缀,
+     * @throws IOException
+     */
+    public static void generate(String templatePath, String targetPath, String htmlDir) throws IOException {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put(ParserUtil.IS_DO, false);
+        CategoryEntity column = new CategoryEntity();
+        //内容管理栏目编码
+        map.put(ParserUtil.COLUMN, column);
+        map.put(ParserUtil.HTML, htmlDir);
+
+        //站点编号
+        if (BasicUtil.getWebsiteApp() != null) {
+            map.put(ParserUtil.APP_DIR, BasicUtil.getWebsiteApp().getAppDir());
+            map.put(ParserUtil.URL, BasicUtil.getWebsiteApp().getAppHostUrl());
+            map.put(ParserUtil.APP_ID, BasicUtil.getWebsiteApp().getAppId());
+        } else {
+            map.put(ParserUtil.URL, BasicUtil.getUrl());
+            map.put(ParserUtil.APP_DIR, BasicUtil.getApp().getAppDir());
+        }
+
+        String content = ParserUtil.rendering(templatePath, map);
+        FileUtil.writeString(content, ParserUtil.buildHtmlPath(targetPath, htmlDir, map.get(ParserUtil.APP_DIR).toString()), Const.UTF8);
+    }
+
+    /**
+     * 生成静态列表页
+     *
+     * @param column
+     * @param articleIdTotal
+     * @throws TemplateNotFoundException
+     * @throws MalformedTemplateNameException
+     * @throws ParseException
+     * @throws IOException
+     */
+    public static void generateList(CategoryEntity column, int articleIdTotal, String htmlDir)
+            throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException {
+        try {
+            // 文章的栏目模型编号
+            PageBean page = new PageBean();
+
+            //获取列表中的size
+            page.setSize(ParserUtil.getPageSize(column.getCategoryListUrl(), 20));
+            page.setRcount(articleIdTotal);
+
+            int totalPageSize = PageUtil.totalPage(articleIdTotal, page.getSize());
+            page.setTotal(totalPageSize);
+
+            //全局参数设置
+            Map<String, Object> parserParams = new HashMap<String, Object>();
+            parserParams.put(ParserUtil.IS_DO, false);
+            parserParams.put(ParserUtil.HTML, htmlDir);
+            parserParams.put(ParserUtil.PAGE, page);
+
+            //站点编号
+            if (BasicUtil.getWebsiteApp() != null) {
+                parserParams.put(ParserUtil.APP_DIR, BasicUtil.getWebsiteApp().getAppDir());
+                parserParams.put(ParserUtil.URL, BasicUtil.getWebsiteApp().getAppHostUrl());
+                parserParams.put(ParserUtil.APP_ID, BasicUtil.getWebsiteApp().getAppId());
+            } else {
+                parserParams.put(ParserUtil.URL, BasicUtil.getUrl());
+                parserParams.put(ParserUtil.APP_DIR, BasicUtil.getApp().getAppDir());
+            }
+
+            parserParams.put(ParserUtil.COLUMN, column);
+            //标签中使用field获取当前栏目
+            parserParams.put(ParserUtil.FIELD, column);
+
+
+            String columnListPath;
+            ModelEntity contentModel = null;
+            // 判断当前栏目是否有自定义模型
+            if (column.getMdiyModelId() != null) {
+                // 通过栏目模型编号获取自定义模型实体
+                contentModel = (ModelEntity) SpringUtil.getBean(ModelBizImpl.class).getEntity(column.getMdiyModelId());
+            }
+
+            if (contentModel != null) {
+                // 将自定义模型编号设置为key值
+                parserParams.put(ParserUtil.TABLE_NAME, contentModel.getModelTableName());
+            }
+
+            int pageNo = 1;
+            //文章列表页没有写文章列表标签,总数为0
+            if (totalPageSize <= 0) {
+                // 数据库中第一页是从开始0*size
+                columnListPath = ParserUtil.buildHtmlPath(column.getCategoryPath() + File.separator + ParserUtil.INDEX, htmlDir, parserParams.get(ParserUtil.APP_DIR).toString());
+                // 设置分页的起始位置
+                page.setPageNo(pageNo);
+                String read = ParserUtil.rendering(File.separator + column.getCategoryListUrl(), parserParams);
+                FileUtil.writeString(read, columnListPath, Const.UTF8);
+
+            } else {
+                // 遍历分页
+                for (int i = 0; i < totalPageSize; i++) {
+                    if (i == 0) {
+                        // 数据库中第一页是从开始0*size
+                        // 首页路径index.html
+                        columnListPath = ParserUtil
+                                .buildHtmlPath(column.getCategoryPath() + File.separator + ParserUtil.INDEX, htmlDir, parserParams.get(ParserUtil.APP_DIR).toString());
+                    } else {
+                        // 其他路径list-2.html
+                        columnListPath = ParserUtil
+                                .buildHtmlPath(column.getCategoryPath() + File.separator + ParserUtil.PAGE_LIST + pageNo, htmlDir, parserParams.get(ParserUtil.APP_DIR).toString());
+                    }
+                    // 设置分页的起始位置
+                    page.setPageNo(pageNo);
+                    String read = ParserUtil.rendering(File.separator + column.getCategoryListUrl(), parserParams);
+                    FileUtil.writeString(read, columnListPath, Const.UTF8);
+                    pageNo++;
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 生成内容
+     *
+     * @param articleIdList 文章集合
+     * @return
+     * @throws IOException
+     * @throws ParseException
+     * @throws MalformedTemplateNameException
+     * @throws TemplateNotFoundException
+     */
+    public static void generateBasic(List<CategoryBean> articleIdList, String htmlDir) {
+
+        Map<String, Object> parserParams = new HashMap<String, Object>();
+        parserParams.put(ParserUtil.IS_DO, false);
+        if (BasicUtil.getWebsiteApp() != null) {
+            parserParams.put(ParserUtil.APP_DIR, BasicUtil.getWebsiteApp().getAppDir());
+            parserParams.put(ParserUtil.URL, BasicUtil.getWebsiteApp().getAppHostUrl());
+            parserParams.put(ParserUtil.APP_ID, BasicUtil.getWebsiteApp().getAppId());
+        } else {
+            parserParams.put(ParserUtil.URL, BasicUtil.getUrl());
+            parserParams.put(ParserUtil.APP_DIR, BasicUtil.getApp().getAppDir());
+        }
+
+        parserParams.put(ParserUtil.HTML, htmlDir);
+
+
+        Map<Object, Object> contentModelMap = new HashMap<Object, Object>();
+        ModelEntity contentModel = null;
+        // 记录已经生成了文章编号
+        List<String> generateIds = new ArrayList<>();
+        // 生成文章
+        for (int artId = 0; artId < articleIdList.size(); ) {
+
+
+            CategoryBean categoryBean = articleIdList.get(artId);
+            String writePath = null;
+            //设置分页类
+            PageBean page = new PageBean();
+            // 文章编号
+            String articleId = categoryBean.getArticleId();
+            // 文章的栏目路径
+            String articleColumnPath = categoryBean.getCategoryPath();
+            // 该文章相关分类
+            String categoryParentId = categoryBean.getId();
+            if (StringUtils.isNotBlank(categoryBean.getCategoryParentIds())) {
+                categoryParentId += ',' + categoryBean.getCategoryParentIds();
+            }
+            // 文章的模板路径
+            String columnUrl = categoryBean.getCategoryUrl();
+            // 文章的栏目模型编号
+            Integer columnContentModelId = null;
+            if (articleIdList.get(artId).getMdiyModelId() != null && categoryBean.getMdiyModelId() > 0) {
+                columnContentModelId = categoryBean.getMdiyModelId();
+            }
+
+            // 文章是否已经生成了,生成了就跳过
+            if (generateIds.contains(articleId)) {
+                artId++;
+                continue;
+            }
+
+            // 判断文件是否存在,若不存在弹出返回信息
+            if (!FileUtil.exist(ParserUtil.buildTempletPath(columnUrl)) || categoryBean.getId() == null || categoryBean.getCategoryType() == null) {
+                artId++;
+                continue;
+            }
+            // 将
+            generateIds.add(articleId);
+            //如果是封面就生成index.html
+            if (categoryBean.getCategoryType().equals(CategoryTypeEnum.COVER.toString())) {
+                writePath = ParserUtil.buildHtmlPath(articleColumnPath + File.separator + ParserUtil.INDEX, htmlDir, parserParams.get(ParserUtil.APP_DIR).toString());
+            } else {
+                // 组合文章路径如:html/站点id/栏目id/文章id.html
+                writePath = ParserUtil.buildHtmlPath(articleColumnPath + File.separator + articleId, htmlDir, parserParams.get(ParserUtil.APP_DIR).toString());
+            }
+
+
+            parserParams.put(ParserUtil.COLUMN, categoryBean);
+
+
+            // 判断当前栏目是否有自定义模型
+            if (columnContentModelId != null) {
+                // 通过当前栏目的模型编号获取,自定义模型表名
+                if (contentModelMap.containsKey(columnContentModelId)) {
+                    parserParams.put(ParserUtil.TABLE_NAME, contentModel.getModelTableName());
+                } else {
+                    // 通过栏目模型编号获取自定义模型实体
+                    contentModel = (ModelEntity) SpringUtil.getBean(IModelBiz.class)
+                            .getEntity(columnContentModelId);
+                    // 将自定义模型编号设置为key值
+                    contentModelMap.put(columnContentModelId, contentModel.getModelTableName());
+                    parserParams.put(ParserUtil.TABLE_NAME, contentModel.getModelTableName());
+                }
+            }
+
+            parserParams.put(ParserUtil.ID, articleId);
+            // 第一篇文章没有上一篇
+            if (artId > 0) {
+                CategoryBean preCaBean = articleIdList.get(artId - 1);
+                //判断当前文档是否与上一页文章在同一栏目下,并且不能使用父栏目字符串,因为父栏目中没有所属栏目编号
+//				if( categoryParentId.contains(preCaBean.getCategoryId()+"")){
+                page.setPreId(preCaBean.getArticleId());
+//				}
+            }
+            // 最后一篇文章没有下一篇
+            if (artId + 1 < articleIdList.size()) {
+                CategoryBean nextCaBean = articleIdList.get(artId + 1);
+                //判断当前文档是否与下一页文章在同一栏目下并且不能使用父栏目字符串,因为父栏目中没有所属栏目编号
+//				if(categoryParentId.contains(nextCaBean.getCategoryId()+"")){
+                page.setNextId(nextCaBean.getArticleId());
+//				}
+            }
+
+
+            parserParams.put(ParserUtil.PAGE, page);
+            String finalWritePath = writePath;
+            HashMap<Object, Object> cloneMap = CollUtil.newHashMap();
+            cloneMap.putAll(parserParams);
+            HttpServletRequest request = SpringUtil.getRequest();
+            String content = null;
+            try {
+                content = ParserUtil.rendering(columnUrl, cloneMap);
+                FileUtil.writeString(content, finalWritePath, Const.UTF8);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            artId++;
+        }
+    }
+}