Browse Source

up:5.4.0

Signed-off-by: mingsoft <killfen@126.com>
mingsoft 1 year ago
parent
commit
0475cf95c5

File diff suppressed because it is too large
+ 0 - 29
doc/5.3.5-up-5.3.6.sql


+ 1 - 27
doc/mcms-5.3.6.sql → doc/mcms-5.4.0.sql

@@ -32,7 +32,7 @@ CREATE TABLE `app` (
 -- Records of app
 -- ----------------------------
 BEGIN;
-INSERT INTO `app` (`id`, `app_name`, `app_url`, `app_logo`, `app_keyword`, `app_copyright`, `app_style`, `app_description`, `app_pay`, `app_state`, `app_datetime`, `app_pay_date`, `app_dir`, `update_date`, `update_by`, `create_date`, `create_by`, `del`) VALUES ('1', '5.3.6 铭飞MCMS', 'http://localhost:8081/', '[{\"url\":\"/upload/1/appLogo/1609397756549.png\",\"name\":\"logo_small.png\",\"path\":\"/upload/1/appLogo/1609397756549.png\",\"uid\":1685699633311,\"status\":\"success\"}]', 'CMS,免费CMS,免费开源Java CMS,CMS系统,Java CMS,CMS内容管理系统,企业CMS,HTML网页模板,CMS模板,CMS源码,网站源码,信创系统软件,安可系统,网站建设,模板网站,建站模板,建站工具,建站平台,建站工具', '站点版权信息,可配置', 'default', '基于java开发的一套java cms,也是轻量级开源内容管理系统,CMS简洁、安全、开源、免费,可运行在Linux、Windows、MacOSX、Solaris等各种平台上,专注为公司企业、个人站长快速建站提供解决方案,铭飞MS平台为您提供各类cms网站模板下载,公司网站、企业网站模板、网站后台系统模板、免费网站模板,10年建站公司老品牌值得信赖的cms!', '', 0, NULL, '2019-11-17 00:00:00', 'web', '2024-02-01 16:29:30', '57', NULL, '', 0);
+INSERT INTO `app` (`id`, `app_name`, `app_url`, `app_logo`, `app_keyword`, `app_copyright`, `app_style`, `app_description`, `app_pay`, `app_state`, `app_datetime`, `app_pay_date`, `app_dir`, `update_date`, `update_by`, `create_date`, `create_by`, `del`) VALUES ('1', '5.4.0 铭飞MCMS', 'http://localhost:8081/', '[{\"url\":\"/upload/1/appLogo/1609397756549.png\",\"name\":\"logo_small.png\",\"path\":\"/upload/1/appLogo/1609397756549.png\",\"uid\":1685699633311,\"status\":\"success\"}]', 'CMS,免费CMS,免费开源Java CMS,CMS系统,Java CMS,CMS内容管理系统,企业CMS,HTML网页模板,CMS模板,CMS源码,网站源码,信创系统软件,安可系统,网站建设,模板网站,建站模板,建站工具,建站平台,建站工具', '站点版权信息,可配置', 'default', '基于java开发的一套java cms,也是轻量级开源内容管理系统,CMS简洁、安全、开源、免费,可运行在Linux、Windows、MacOSX、Solaris等各种平台上,专注为公司企业、个人站长快速建站提供解决方案,铭飞MS平台为您提供各类cms网站模板下载,公司网站、企业网站模板、网站后台系统模板、免费网站模板,10年建站公司老品牌值得信赖的cms!', '', 0, NULL, '2019-11-17 00:00:00', 'web', '2024-02-01 16:29:30', '57', NULL, '', 0);
 COMMIT;
 
 -- ----------------------------
@@ -342,32 +342,6 @@ INSERT INTO `mdiy_dict` (`id`, `dict_value`, `dict_label`, `dict_type`, `dict_de
 INSERT INTO `mdiy_dict` (`id`, `dict_value`, `dict_label`, `dict_type`, `dict_description`, `is_child`, `dict_enable`, `dict_remarks`, `dict_sort`, `UPDATE_BY`, `UPDATE_DATE`, `CREATE_BY`, `CREATE_DATE`, `DEL`, `NOT_DEL`) VALUES (650, '时政热点', '时政热点', '文章标签', NULL, NULL, '1', NULL, 0, '57', '2023-09-28 16:27:43', '106', '2023-06-08 15:13:13', 0, 0);
 COMMIT;
 
--- ----------------------------
--- Table structure for mdiy_form_test
--- ----------------------------
-DROP TABLE IF EXISTS `mdiy_form_test`;
-CREATE TABLE `mdiy_form_test` (
-  `id` varchar(19) NOT NULL,
-  `TEXTAREA_C` varchar(255) DEFAULT NULL COMMENT '多行文本',
-  `input_1700029713000_79971` varchar(255) DEFAULT NULL COMMENT '单行文本',
-  `SELECT_C` varchar(255) DEFAULT NULL COMMENT '下拉选择框',
-  `TEXTAREA_CDD` varchar(255) DEFAULT NULL COMMENT '多行文本',
-  `MONEY_A` decimal(11,3) DEFAULT NULL COMMENT '金钱',
-  `INPUT_C` varchar(255) DEFAULT NULL COMMENT '单行文本',
-  `LINK_ID` bigint(20) DEFAULT NULL,
-  `CREATE_DATE` datetime DEFAULT NULL COMMENT '创建时间',
-  `CREATE_BY` varchar(50) DEFAULT NULL COMMENT '创建人',
-  `UPDATE_DATE` datetime DEFAULT NULL COMMENT '修改时间',
-  `UPDATE_BY` varchar(50) DEFAULT NULL COMMENT '修改人',
-  `DEL` int(1) DEFAULT '0' COMMENT '删除标记',
-  PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='test1';
-
--- ----------------------------
--- Records of mdiy_form_test
--- ----------------------------
-BEGIN;
-COMMIT;
 
 -- ----------------------------
 -- Table structure for mdiy_model

+ 5 - 5
pom.xml

@@ -10,7 +10,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>net.mingsoft</groupId>
     <artifactId>ms-mcms</artifactId>
-    <version>5.3.6</version>
+    <version>5.4.0</version>
     <name>${project.groupId}:${project.artifactId}</name>
     <!-- 打包war包,注意不启用(resources》resource》excludes的配置并注释掉maven-assembly-plugin 插件配置 -->
     <!--<packaging>war</packaging>-->
@@ -44,24 +44,24 @@
         <dependency>
             <groupId>net.mingsoft</groupId>
             <artifactId>ms-base</artifactId>
-            <version>2.1.26</version>
+            <version>2.2.0</version>
         </dependency>
         <dependency>
             <groupId>net.mingsoft</groupId>
             <artifactId>ms-basic</artifactId>
-            <version>2.1.26</version>
+            <version>2.2.0</version>
         </dependency>
         <dependency>
             <groupId>net.mingsoft</groupId>
             <artifactId>ms-mdiy</artifactId>
-            <version>2.1.26</version>
+            <version>2.2.0</version>
         </dependency>
 
         <!--store入口依赖(源码不开发),如果不需要MStore可以直接去掉依赖-->
         <dependency>
             <groupId>net.mingsoft</groupId>
             <artifactId>store-client</artifactId>
-            <version>2.1.26</version>
+            <version>2.2.0</version>
         </dependency>
         <dependency>
             <groupId>com.github.oshi</groupId>

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

@@ -31,6 +31,7 @@ import java.util.MissingResourceException;
 public class BaseAction extends net.mingsoft.basic.action.BaseAction{
     @Override
     protected String getResString(String key) {
+        
         // TODO Auto-generated method stub
         String str = "";
         try {

+ 106 - 13
src/main/java/net/mingsoft/cms/action/CategoryAction.java

@@ -40,7 +40,6 @@ import net.mingsoft.basic.util.StringUtil;
 import net.mingsoft.cms.biz.ICategoryBiz;
 import net.mingsoft.cms.constant.e.CategoryTypeEnum;
 import net.mingsoft.cms.entity.CategoryEntity;
-import net.mingsoft.cms.entity.ContentEntity;
 import net.mingsoft.mdiy.util.ParserUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
@@ -114,14 +113,14 @@ public class CategoryAction extends BaseAction {
      * 获取分类
      * @param category 分类实体
      */
-    @ApiOperation(value = "获取分类列表接口")
+    @ApiOperation(value = "获取分类详情接口")
     @ApiImplicitParam(name = "id", value = "编号", required = true, paramType = "query")
     @GetMapping("/get")
     @RequiresPermissions("cms:category:view")
     @ResponseBody
     public ResultData get(@ModelAttribute @ApiIgnore CategoryEntity category) {
-        if (category.getId() == null) {
-            return ResultData.build().error();
+        if (StringUtils.isBlank(category.getId())) {
+            return ResultData.build().error(getResString("err.empty",this.getResString("id")));
         }
         CategoryEntity _category = (CategoryEntity) categoryBiz.getById(category.getId());
         return ResultData.build().success(_category);
@@ -135,21 +134,23 @@ public class CategoryAction extends BaseAction {
     @ApiOperation(value = "保存分类列表接口")
     @ApiImplicitParams({
             @ApiImplicitParam(name = "categoryTitle", value = "栏目管理名称", required = true, paramType = "query"),
+            @ApiImplicitParam(name = "categoryType", value = "栏目类型,1:列表,2:单篇,3:链接", required = true, paramType = "query"),
+            @ApiImplicitParam(name = "categoryDisplay", value = "栏目是否显示,enable:显示 disable:不显示", required = true, paramType = "query"),
+            @ApiImplicitParam(name = "categoryIsSearch", value = "栏目是否可搜索,enable:可搜索 disable:不可搜索", 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 = "categoryIco", 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 = "categoryParentIds", value = "父类型编号", required = false, paramType = "query"),
     })
     @PostMapping("/save")
     @ResponseBody
@@ -167,6 +168,43 @@ public class CategoryAction extends BaseAction {
         if (!StringUtil.checkLength(category.getCategoryTitle() + "", 1, 100)) {
             return ResultData.build().error(getResString("err.length", this.getResString("category.title"), "1", "100"));
         }
+        //验证栏目描述的值是否合法
+        if (!StringUtil.checkLength(category.getCategoryDescrip() + "", 0, 500)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.descrip"), "0", "500"));
+        }
+        //验证栏目关键字的值是否合法
+        if (!StringUtil.checkLength(category.getCategoryKeyword() + "", 0, 300)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.keyword"), "0", "300"));
+        }
+        //验证栏目路径的值是否合法
+        if (!StringUtil.checkLength(category.getCategoryPath() + "", 0, 500)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.path"), "0", "500"));
+        }
+        //验证栏目列表模板的值是否合法
+        if (!StringUtil.checkLength(category.getCategoryListUrl() + "", 0, 50)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.list.url"), "0", "50"));
+        }
+        //验证栏目内容模板的值是否合法
+        if (!StringUtil.checkLength(category.getCategoryUrl() + "", 0, 50)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.url"), "0", "50"));
+        }
+
+        //验证栏目自定义链接的值是否合法
+        if (!StringUtil.checkLength(category.getCategoryDiyUrl() + "", 0, 255)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.diy.url"), "0", "255"));
+        }
+        //验证栏目属性的值是否合法
+        if (!StringUtil.checkLength(category.getCategoryFlag() + "", 0, 20)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.flag"), "0", "20"));
+        }
+        //验证栏目类型的值是否合法
+        if (!StringUtil.checkLength(category.getCategoryType() + "", 0, 1)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.type"), "0", "1"));
+        }
+        //验证栏目内容模型id的值是否合法
+        if (!StringUtil.checkLength(category.getMdiyModelId() + "", 0, 50)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("mdiy.model.id"), "0", "50"));
+        }
 
         // 判断前端拼音传值是否正常
         if (!StringUtil.checkLength(category.getCategoryPinyin() + "", 0, 100)) {
@@ -178,6 +216,7 @@ public class CategoryAction extends BaseAction {
             return ResultData.build().error(this.getResString("err.error",this.getResString("category.pinyin")));
         }
 
+        //验证栏目父ids是否正常
         if (!StringUtil.checkLength(category.getCategoryParentIds() + "", 1, 100)) {
             return ResultData.build().error(getResString("err.length", this.getResString("category.parent.id"), "1", "100"));
         }
@@ -227,21 +266,23 @@ public class CategoryAction extends BaseAction {
     @ApiImplicitParams({
             @ApiImplicitParam(name = "id", value = "编号", required = true, paramType = "query"),
             @ApiImplicitParam(name = "categoryTitle", value = "栏目管理名称", required = true, paramType = "query"),
+            @ApiImplicitParam(name = "categoryDisplay", value = "栏目是否显示,enable:显示 disable:不显示", required = true, paramType = "query"),
+            @ApiImplicitParam(name = "categoryIsSearch", value = "栏目是否可搜索,enable:可搜索 disable:不可搜索", required = true, paramType = "query"),
+            @ApiImplicitParam(name = "categoryType", value = "栏目类型,1:列表,2:单篇,3:链接", 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 = "categoryImg", value = "banner图", required = false, paramType = "query"),
+            @ApiImplicitParam(name = "categoryIco", 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 = "categoryParentIds", value = "父类型编号", required = false, paramType = "query"),
     })
     @PostMapping("/update")
     @ResponseBody
@@ -262,7 +303,43 @@ public class CategoryAction extends BaseAction {
         if (!StringUtil.checkLength(category.getCategoryTitle() + "", 1, 100)) {
             return ResultData.build().error(getResString("err.length", this.getResString("category.title"), "1", "100"));
         }
-
+        //验证栏目描述的值是否合法
+        if (!StringUtil.checkLength(category.getCategoryDescrip() + "", 0, 500)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.descrip"), "0", "500"));
+        }
+        //验证栏目关键字的值是否合法
+        if (!StringUtil.checkLength(category.getCategoryKeyword() + "", 0, 300)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.keyword"), "0", "300"));
+        }
+        //验证栏目自定义链接的值是否合法
+        if (!StringUtil.checkLength(category.getCategoryDiyUrl() + "", 0, 255)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.diy.url"), "0", "255"));
+        }
+        //验证栏目属性的值是否合法
+        if (!StringUtil.checkLength(category.getCategoryFlag() + "", 0, 20)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.flag"), "0", "20"));
+        }
+        //验证栏目列表模板的值是否合法
+        if (!StringUtil.checkLength(category.getCategoryListUrl() + "", 0, 50)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.list.url"), "0", "50"));
+        }
+        //验证栏目路径的值是否合法
+        if (!StringUtil.checkLength(category.getCategoryPath() + "", 0, 500)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.path"), "0", "500"));
+        }
+        //验证栏目类型的值是否合法
+        if (!StringUtil.checkLength(category.getCategoryType() + "", 0, 1)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.type"), "0", "1"));
+        }
+        //验证栏目内容模板的值是否合法
+        if (!StringUtil.checkLength(category.getCategoryUrl() + "", 0, 50)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.url"), "0", "50"));
+        }
+        //验证栏目内容模型id的值是否合法
+        if (!StringUtil.checkLength(category.getMdiyModelId() + "", 0, 50)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("mdiy.model.id"), "0", "50"));
+        }
+        //验证栏目父ids值是否合法
         if (!StringUtil.checkLength(category.getCategoryParentIds() + "", 0, 100)) {
             return ResultData.build().error(getResString("err.length", this.getResString("category.parent.id"), "1", "100"));
         }
@@ -328,6 +405,23 @@ public class CategoryAction extends BaseAction {
     @GetMapping("/verifyPingYin")
     @ResponseBody
     public ResultData verifyPingYin(@ModelAttribute @ApiIgnore CategoryEntity category) {
+        //验证id是否合法
+        if (StringUtils.isEmpty(category.getId())){
+            return ResultData.build().error(getResString("err.empty", this.getResString("id")));
+        }
+        if (!StringUtil.checkLength(category.getId() + "", 0, 20)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("id"), "0", "20"));
+        }
+        //验证拼音是否合法
+        if (StringUtils.isEmpty(category.getCategoryPinyin())){
+            return ResultData.build().error(getResString("err.empty", this.getResString("category.pinyin")));
+        }
+        if (FileNameUtil.containsInvalid(category.getCategoryPinyin())) {
+            return ResultData.build().error(this.getResString("err.error",this.getResString("category.pinyin")));
+        }
+        if (!StringUtil.checkLength(category.getCategoryPinyin() + "", 0, 255)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.pinyin"), "0", "255"));
+        }
         long count = categoryBiz.count(Wrappers.<CategoryEntity>lambdaQuery()
                 .ne(StrUtil.isNotBlank(category.getId()), CategoryEntity::getId, category.getId())
                 .eq(CategoryEntity::getCategoryPinyin, category.getCategoryPinyin()));
@@ -346,7 +440,6 @@ public class CategoryAction extends BaseAction {
     @ApiOperation(value = "批量更新模板")
     @ApiImplicitParams({
             @ApiImplicitParam(name = "id", value = "编号", required = true, paramType = "query"),
-            @ApiImplicitParam(name = "dictId", value = "字典", required = true, paramType = "query")
     })
     @GetMapping("/updateTemplate")
     @ResponseBody

+ 270 - 225
src/main/java/net/mingsoft/cms/action/ContentAction.java

@@ -7,10 +7,10 @@
  * 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
@@ -56,253 +56,298 @@ import java.util.Map;
 
 /**
  * 文章管理控制层
+ *
  * @author 铭飞开发团队
  * 创建日期:2019-11-28 15:12:32<br/>
  * 历史修订:<br/>
  */
-@Api(tags={"后端-内容模块接口"})
+@Api(tags = {"后端-内容模块接口"})
 @Controller("cmsContentAction")
 @RequestMapping("/${ms.manager.path}/cms/content")
 public class ContentAction extends BaseAction {
 
 
-	/**
-	 * 注入文章业务层
-	 */
-	@Autowired
-	private IContentBiz contentBiz;
+    /**
+     * 注入文章业务层
+     */
+    @Autowired
+    private IContentBiz contentBiz;
 
 
-	@Autowired
-	private ICategoryBiz categoryBiz;
+    @Autowired
+    private ICategoryBiz categoryBiz;
 
 
-	@Resource(name="mdiyModelBizImpl")
-	private IModelBiz modelBiz;
+    @Resource(name = "mdiyModelBizImpl")
+    private IModelBiz modelBiz;
 
-	/**
-	 * 返回主界面index
-	 */
-	@ApiIgnore
-	@GetMapping("/index")
-	public String index(){
-		return "/cms/content/index";
-	}
+    /**
+     * 返回主界面index
+     */
+    @ApiIgnore
+    @GetMapping("/index")
+    public String index() {
+        return "/cms/content/index";
+    }
 
-	/**
-	 * 返回主界面main
-	 */
-	@ApiIgnore
-	@GetMapping("/main")
-	public String main(){
-		return "/cms/content/main";
-	}
+    /**
+     * 返回主界面main
+     */
+    @ApiIgnore
+    @GetMapping("/main")
+    public String main() {
+        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"),
+    /**
+     * 查询文章列表
+     *
+     * @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 = "是否显示,0:显示 1:不显示", 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"),
     })
-	@RequestMapping(value = "/list",method = {RequestMethod.GET,RequestMethod.POST})
-	@ResponseBody
-	@RequiresPermissions("cms:content:view")
-	public ResultData list(@ModelAttribute @ApiIgnore ContentBean content) {
-		// 检查SQL注入
-		SqlInjectionUtil.filterContent(content.getCategoryId());
-		BasicUtil.startPage();
-		List contentList = contentBiz.queryContent(content);
-		return ResultData.build().success(new EUListBean(contentList,(int) BasicUtil.endPage(contentList).getTotal()));
-	}
-
-	/**
-	 * 返回编辑界面content_form
-	 */
-	@ApiIgnore
-	@GetMapping("/form")
-	public String form(@ModelAttribute ContentEntity content, ModelMap model){
-		model.addAttribute("appId", BasicUtil.getApp().getAppId());
-		return "/cms/content/form";
-	}
+    @RequestMapping(value = "/list", method = {RequestMethod.GET, RequestMethod.POST})
+    @ResponseBody
+    @RequiresPermissions("cms:content:view")
+    public ResultData list(@ModelAttribute @ApiIgnore ContentBean content) {
+        // 检查SQL注入
+        SqlInjectionUtil.filterContent(content.getCategoryId());
+        BasicUtil.startPage();
+        List contentList = contentBiz.queryContent(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
-	@RequiresPermissions("cms:content:view")
-	public ResultData get(@ModelAttribute @ApiIgnore ContentEntity content){
-		if(content.getId()==null) {
-			return ResultData.build().error();
-		}
-		ContentEntity _content = contentBiz.getById(content.getId());
-		return ResultData.build().success(_content);
-	}
+    /**
+     * 返回编辑界面content_form
+     */
+    @ApiIgnore
+    @GetMapping("/form")
+    public String form(@ModelAttribute ContentEntity content, ModelMap model) {
+        model.addAttribute("appId", BasicUtil.getApp().getAppId());
+        return "/cms/content/form";
+    }
 
-	/**
-	 * 获取文章
-	 * @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);
-	}
+    /**
+     * 获取文章
+     *
+     * @param content 文章实体
+     */
+    @ApiOperation(value = "获取文章详情接口")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, paramType = "query")
+    @GetMapping("/get")
+    @ResponseBody
+    @RequiresPermissions("cms:content:view")
+    public ResultData get(@ModelAttribute @ApiIgnore ContentEntity content) {
+        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 (StringUtils.isBlank(content.getCategoryId())) {
+            return ResultData.build().error(getResString("err.empty", this.getResString("category.id")));
+        }
+        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);
+    }
 
 
-	/**
-	* 保存文章
-	* @param content 文章实体
-	*/
-	@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"),
-	})
-	@PostMapping("/save")
-	@ResponseBody
-	@LogAnn(title = "保存文章", businessType = BusinessTypeEnum.INSERT)
-	@RequiresPermissions("cms:content:save")
-	public ResultData save(@ModelAttribute @ApiIgnore ContentEntity content) {
-		//验证缩略图参数值是否合法
-		if (content.getContentImg()==null || !content.getContentImg().matches("^\\[.{1,}]$")){
-			content.setContentImg("");
-		}
-		//验证文章标题的值是否合法
-		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")));
-		}
-		contentBiz.save(content);
-		return ResultData.build().success(content);
-	}
+    /**
+     * 保存文章
+     *
+     * @param content 文章实体
+     */
+    @ApiOperation(value = "保存文章列表接口")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "contentTitle", value = "文章标题", required = true, paramType = "query"),
+            @ApiImplicitParam(name = "categoryId", value = "所属栏目", required = true, paramType = "query"),
+            @ApiImplicitParam(name = "contentType", value = "文章类型", required = false, paramType = "query"),
+            @ApiImplicitParam(name = "contentDisplay", value = "是否显示,0:显示 1:不显示", required = true, 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 = "contentOutLink", value = "文章跳转链接地址", required = false, paramType = "query"),
+    })
+    @PostMapping("/save")
+    @ResponseBody
+    @LogAnn(title = "保存文章", businessType = BusinessTypeEnum.INSERT)
+    @RequiresPermissions("cms:content:save")
+    public ResultData save(@ModelAttribute @ApiIgnore ContentEntity content) {
+        //验证缩略图参数值是否合法
+        if (content.getContentImg() == null || !content.getContentImg().matches("^\\[.{1,}]$")) {
+            content.setContentImg("");
+        }
+        //验证文章标题的值是否合法
+        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.checkLength(content.getContentDescription() + "", 0, 400)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("content.description"), "0", "400"));
+        }
+        //验证文章链接的值是否合法
+        if (!StringUtil.checkLength(content.getContentOutLink() + "", 0, 255)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("content.url"), "0", "255"));
+        }
+        //验证文章显示的值是否合法
+        if (!StringUtil.checkLength(content.getContentDisplay() + "", 0, 1)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("content.display"), "0", "1"));
+        }
+        //验证文章关键字的值是否合法
+        if (!StringUtil.checkLength(content.getContentKeyword() + "", 0, 255)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("content.keyword"), "0", "255"));
+        }
+        //验证文章类型的值是否合法
+        if (!StringUtil.checkLength(content.getContentType() + "", 0, 20)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("content.type"), "0", "20"));
+        }
+        //验证发布时间的值是否合法
+        if (StringUtil.isBlank(content.getContentDatetime())) {
+            return ResultData.build().error(getResString("err.empty", this.getResString("content.datetime")));
+        }
+        contentBiz.save(content);
+        return ResultData.build().success(content);
+    }
 
-	/**
-	 * @param contents 文章实体
-	 */
-	@ApiOperation(value = "批量删除文章列表接口")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "contents", value = "文章集合", allowMultiple = true, dataType = "ContentEntity", required = true)
+    /**
+     * @param contents 文章实体
+     */
+    @ApiOperation(value = "批量删除文章列表接口")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "contents", value = "文章集合", allowMultiple = true, dataType = "ContentEntity", required = true)
 
-	})
-	@PostMapping("/delete")
-	@ResponseBody
-	@LogAnn(title = "删除文章", businessType = BusinessTypeEnum.DELETE)
-	@RequiresPermissions("cms:content:del")
-	public ResultData delete(@RequestBody List<ContentEntity> contents) {
-		List<String> ids = new ArrayList<>();
-		for(int i = 0;i<contents.size();i++){
-			ids.add(contents.get(i).getId());
-			//获取栏目实体
-			CategoryEntity categoryEntity = categoryBiz.getById(contents.get(i).getCategoryId());
-			//如果栏目绑定的模型ID为空
-			if (StringUtils.isBlank(categoryEntity.getMdiyModelId())){
-				continue;
-			}
-			//获取到配置模型实体
-			ModelEntity modelEntity = modelBiz.getById(categoryEntity.getMdiyModelId());
-			//删除模型表的数据
-			Map<String, String> map = new HashMap<>();
-			map.put("link_id", contents.get(i).getId());
-			modelBiz.deleteBySQL(modelEntity.getModelTableName(), map);
-		}
+    })
+    @PostMapping("/delete")
+    @ResponseBody
+    @LogAnn(title = "删除文章", businessType = BusinessTypeEnum.DELETE)
+    @RequiresPermissions("cms:content:del")
+    public ResultData delete(@RequestBody List<ContentEntity> contents) {
+        List<String> ids = new ArrayList<>();
+        for (int i = 0; i < contents.size(); i++) {
+            ids.add(contents.get(i).getId());
+            //获取栏目实体
+            CategoryEntity categoryEntity = categoryBiz.getById(contents.get(i).getCategoryId());
+            //如果栏目绑定的模型ID为空
+            if (StringUtils.isBlank(categoryEntity.getMdiyModelId())) {
+                continue;
+            }
+            //获取到配置模型实体
+            ModelEntity modelEntity = modelBiz.getById(categoryEntity.getMdiyModelId());
+            //删除模型表的数据
+            Map<String, String> map = new HashMap<>();
+            map.put("link_id", contents.get(i).getId());
+            modelBiz.deleteBySQL(modelEntity.getModelTableName(), map);
+        }
 
-		contentBiz.removeByIds(ids);
-		return ResultData.build().success();
-	}
+        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"),
-	})
-	@PostMapping("/update")
-	@ResponseBody
-	@LogAnn(title = "更新文章", businessType = BusinessTypeEnum.UPDATE)
-	@RequiresPermissions("cms:content:update")
-	public ResultData update(@ModelAttribute @ApiIgnore ContentEntity content) {
-		 //验证缩略图参数值是否合法
-		 if (content.getContentImg()==null || !content.getContentImg().matches("^\\[.{1,}]$")){
-			 content.setContentImg("");
-		 }
-		//验证文章标题的值是否合法
-		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")));
-		}
-		contentBiz.saveOrUpdate(content);
-		return ResultData.build().success(content);
-	}
+    /**
+     * 更新文章列表
+     *
+     * @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 = true, paramType = "query"),
+            @ApiImplicitParam(name = "contentType", value = "文章类型", required = false, paramType = "query"),
+            @ApiImplicitParam(name = "contentDisplay", value = "是否显示,0:显示 1:不显示", required = true, 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 = "contentOutLink", value = "文章跳转链接地址", required = false, paramType = "query"),
+    })
+    @PostMapping("/update")
+    @ResponseBody
+    @LogAnn(title = "更新文章", businessType = BusinessTypeEnum.UPDATE)
+    @RequiresPermissions("cms:content:update")
+    public ResultData update(@ModelAttribute @ApiIgnore ContentEntity content) {
+        //验证缩略图参数值是否合法
+        if (content.getContentImg() == null || !content.getContentImg().matches("^\\[.{1,}]$")) {
+            content.setContentImg("");
+        }
+        //验证文章标题的值是否合法
+        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.checkLength(content.getContentDescription() + "", 0, 400)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("content.description"), "0", "400"));
+        }
+        //验证文章链接的值是否合法
+        if (!StringUtil.checkLength(content.getContentOutLink() + "", 0, 255)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("content.url"), "0", "255"));
+        }
+        //验证文章显示的值是否合法
+        if (!StringUtil.checkLength(content.getContentDisplay() + "", 0, 1)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("content.display"), "0", "1"));
+        }
+        //验证文章关键字的值是否合法
+        if (!StringUtil.checkLength(content.getContentKeyword() + "", 0, 255)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("content.keyword"), "0", "255"));
+        }
+        //验证文章类型的值是否合法
+        if (!StringUtil.checkLength(content.getContentType() + "", 0, 20)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("content.type"), "0", "20"));
+        }
+        //验证发布时间的值是否合法
+        if (StringUtil.isBlank(content.getContentDatetime())) {
+            return ResultData.build().error(getResString("err.empty", this.getResString("content.datetime")));
+        }
+        contentBiz.saveOrUpdate(content);
+        return ResultData.build().success(content);
+    }
 }

+ 11 - 1
src/main/java/net/mingsoft/cms/action/GeneraterAction.java

@@ -29,6 +29,7 @@ import cn.hutool.core.bean.copier.CopyOptions;
 import cn.hutool.core.date.DateException;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.io.FileUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import net.mingsoft.base.entity.ResultData;
@@ -64,6 +65,7 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * @ClassName: GeneraterAction
@@ -263,13 +265,21 @@ public class GeneraterAction extends BaseAction {
             return ResultData.build().error(getResString("err.error",this.getResString("datetime.format")));
         }
         if ("0".equals(columnId)) {
-            categoryList = categoryBiz.list();
+            // 根据leaf进行升序排序,让叶子栏目最后静态化 保证文章上下篇关系正确
+            LambdaQueryWrapper<CategoryEntity> wrapper = new LambdaQueryWrapper<CategoryEntity>().orderByAsc(CategoryEntity::getLeaf);
+            categoryList = categoryBiz.list(wrapper);
         } else { //选择栏目更新
             CategoryEntity categoryEntity = new CategoryEntity();
             categoryEntity.setId(columnId);
             categoryList = categoryBiz.queryChildren(categoryEntity);
         }
 
+        // todo 这里延续之前的详情上下篇思路(不考虑跨栏目),只对栏目内的文章进行上下篇处理,且单篇没有上下篇;
+        // 获取叶子节点栏目
+        categoryList = categoryList.stream().filter(item->{
+            return item.getLeaf();
+        }).collect(Collectors.toList());
+
         for (CategoryEntity category : categoryList) {
             // 如果栏目被禁用则跳过
             if (CategoryDisplayEnum.DISABLE.toString().equalsIgnoreCase(category.getCategoryDisplay())){

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

@@ -23,6 +23,7 @@
 package net.mingsoft.cms.action.web;
 
 import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;

+ 0 - 1
src/main/java/net/mingsoft/cms/aop/CategoryAop.java

@@ -19,7 +19,6 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-
 package net.mingsoft.cms.aop;
 
 import cn.hutool.core.collection.CollectionUtil;

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

@@ -68,19 +68,19 @@ public class CategoryBizImpl extends BaseBizImpl<ICategoryDao, CategoryEntity> i
 
     @Override
     protected IBaseDao getDao() {
-        // TODO Auto-generated method stub
+        
         return categoryDao;
     }
 
     @Override
     public List<CategoryEntity> queryChildren(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())) {
@@ -207,7 +207,7 @@ public class CategoryBizImpl extends BaseBizImpl<ICategoryDao, CategoryEntity> i
 
     @Override
     public void delete(String categoryId) {
-        // TODO Auto-generated method stub
+        
         CategoryEntity category = (CategoryEntity) categoryDao.selectById(categoryId);
         //删除父类
         if (category != null) {

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

@@ -75,7 +75,7 @@ public class ContentBizImpl  extends BaseBizImpl<IContentDao, ContentEntity> imp
 
 	@Override
 	protected IBaseDao getDao() {
-		// TODO Auto-generated method stub
+		
 		return contentDao;
 	}
 

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

@@ -47,7 +47,7 @@ public class HistoryLogBizImpl extends BaseBizImpl implements IHistoryLogBiz {
 	
 	@Override
 	protected IBaseDao getDao() {
-		// TODO Auto-generated method stub
+		
 		return historyLogDao;
 	} 
 }

+ 0 - 1
src/main/java/net/mingsoft/cms/constant/e/CategoryIsSearchEnum.java

@@ -19,7 +19,6 @@
  * 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;

+ 0 - 2
src/main/java/net/mingsoft/cms/constant/e/ContentEnum.java

@@ -18,8 +18,6 @@
  * 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;

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

@@ -127,6 +127,8 @@
 				)
 			</if>
 		</where>
+		<!--让叶子栏目最后静态化 保证叶子栏目下文章的上下篇关系正确 不可以根据创建、更新时间进行排序-->
+		order by leaf asc
 	</select>
 
 

+ 3 - 3
src/main/java/net/mingsoft/config/WebConfig.java

@@ -133,7 +133,7 @@ public class WebConfig implements WebMvcConfigurer {
     public FilterRegistrationBean xssFilterRegistration(@Value("${ms.xss.enable:true}") boolean xssEnable,
                                                         @Value("${ms.xss.filter-url}") String filterUrl,
                                                         @Value("${ms.xss.exclude-url}") String excludeUrl,
-                                                        @Value("${ms.xss.exclude-filed}") String excludeFiled) {
+                                                        @Value("${ms.xss.exclude-field}") String excludeFiled) {
         XSSEscapeFilter xssFilter = new XSSEscapeFilter();
         Map<String, String> initParameters = new HashMap();
         FilterRegistrationBean registration = new FilterRegistrationBean();
@@ -151,7 +151,7 @@ public class WebConfig implements WebMvcConfigurer {
             xssFilter.excludes.add(MSProperties.manager.path + "/**");
         }
         if (excludeFiled != null && StrUtil.isNotBlank(excludeFiled)) {
-            xssFilter.excludesFiled.addAll(Arrays.asList(excludeFiled.split(",")));
+            XSSEscapeFilter.excludesField.addAll(Arrays.asList(excludeFiled.split(",")));
         }
         initParameters.put("isIncludeRichText", "false");
         registration.setInitParameters(initParameters);
@@ -184,7 +184,7 @@ public class WebConfig implements WebMvcConfigurer {
      */
     @Override
     public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
-        // TODO Auto-generated method stub
+        
         converters.add(mappingJackson2HttpMessageConverter);
         WebMvcConfigurer.super.configureMessageConverters(converters);
 

+ 2 - 2
src/main/resources/application.yml

@@ -29,8 +29,8 @@ ms:
     # #排除的url,多个用逗号分开,如果怕设置后台过滤麻烦,直接排除 /ms/**
     exclude-url: /ms/**,/static/**,/template/**,/file/upload.do,/static/plugins/ueditor/1.4.3.3/jsp/editor.do
     #过滤的参数名,多个用逗号分开 默认排除菜单、自定模型JSON、模版内容、文章内容,具体根据需要配置其他字段
-    exclude-filed: menuStr,modelField,modelUrl,modelJson,fileContent,contentDetails
-    # shiro-key:  #16位长度,不填写默认随机生成
+    exclude-field: menuStr,modelField,modelUrl,modelJson,fileContent,contentDetails
+  # shiro-key:  #16位长度,不填写默认随机生成
 
   diy:
     html-dir: html

+ 18 - 15
src/main/webapp/WEB-INF/manager/cms/category/form.ftl

@@ -8,10 +8,10 @@
 <div id="form" v-cloak>
     <el-header class="ms-header ms-tr" height="50px">
         <@shiro.hasPermission name="cms:category:save">
-            <el-button type="primary" class="iconfont icon-baocun" size="mini" @click="save()" :loading="saveDisabled">保存
+            <el-button type="primary" class="iconfont icon-baocun" size="default" @click="save()" :loading="saveDisabled">保存
             </el-button>
         </@shiro.hasPermission>
-        <el-button size="mini" class="iconfont icon-fanhui" plain onclick="javascript:history.go(-1)">返回</el-button>
+        <el-button size="default" class="iconfont icon-fanhui" plain onclick="javascript:history.go(-1)">返回</el-button>
     </el-header>
     <el-main class="ms-container">
 
@@ -20,7 +20,7 @@
                 <el-tab-pane style="position:relative;" v-for="(item, index) in editableTabs" :key="index"
                              :label="item.title" :name="item.name">
                     <el-form v-if="item.title=='栏目编辑'" ref="form" :model="form" :rules="rules" label-width="130px"
-                             size="mini">
+                             size="default">
                         <el-row
                                 :gutter=0
                                 justify="start" align="top">
@@ -40,11 +40,15 @@
                             </el-col>
                             <el-col :span=12>
                                 <el-form-item label="所属栏目" prop="categoryId">
-                                    <ms-tree-select  ref="tree"
-                                                     :key="treeKey"
-                                                     :props="{value: 'id',label: 'categoryTitle',children: 'children'}"
-                                                     :options="treeList" :style="{width:'100%'}"
-                                                     v-model:value="form.categoryId"></ms-tree-select>
+                                    <el-tree-select
+                                            v-model="form.categoryId"
+                                            :data="treeList"
+                                            :props="{value: 'id',label: 'categoryTitle',children: 'children'}"
+                                            :render-after-expand="false"
+                                            :check-strictly="true"
+                                            :default-expand-all="true"
+                                            filterable
+                                    ></el-tree-select>
                                     <div class="ms-form-tip">
                                         不能将父级别栏目移动到自身子级栏目
                                     </div>
@@ -299,7 +303,7 @@
                                     accept="image/*"
                                     list-type="picture-card">
                                 <i class="el-icon-plus"></i>
-                                <template slot="tip">
+                                <template #tip>
                                     <div class="ms-form-tip">
                                         只能上传1张图片
                                         标签:<a href="http://doc.mingsoft.net/mcms/biao-qian/lan-mu-lie-biao-ms-channel.html"
@@ -323,7 +327,7 @@
                                     accept="image/*"
                                     list-type="picture-card">
                                 <i class="el-icon-plus"></i>
-                                <template slot="tip">
+                                <template #tip>
                                     <div class="ms-form-tip">
                                         只能上传1张图片
                                         标签:<a href="http://doc.mingsoft.net/mcms/biao-qian/lan-mu-lie-biao-ms-channel.html"
@@ -342,7 +346,7 @@
 </body>
 </html>
 <script>
-    var form = new Vue({
+    var form = new _Vue({
         el: '#form',
         data: function () {
             var that = this
@@ -486,7 +490,7 @@
                         _this.form.categoryId = parentNode[parentNode.length - 1];
                     } else {
                         //无父栏目就恢复顶级
-                        _this.form.categoryId = '0';
+                        _this.form.categoryId = '';
                     }
                     this.$notify({
                         title: '提示',
@@ -773,7 +777,7 @@
             categoryImghandleRemove: function (file, files) {
                 var index = -1;
                 index = this.form.categoryImg.findIndex(function (text) {
-                    return text == file;
+                    return text.uid == file.uid;
                 });
 
                 if (index != -1) {
@@ -809,7 +813,7 @@
             categoryIcohandleRemove: function (file, files) {
                 var index = -1;
                 index = this.form.categoryIco.findIndex(function (text) {
-                    return text == file;
+                    return text.uid == file.uid;
                 });
 
                 if (index != -1) {
@@ -847,7 +851,6 @@
             this.categoryFlagOptionsGet();
             this.form.id = ms.util.getParameter("id");
             this.form.childId = ms.util.getParameter("childId");// 判断是否增加子栏目
-            this.form.categoryId = '0';
             // 判断三种状态,默认为新增状态
             this.categoryTypeDisabled = false;// 控制栏目分类是否可编辑
             if (this.form.id != undefined && (this.form.childId == undefined || this.form.childId == "undefined")) {

+ 14 - 12
src/main/webapp/WEB-INF/manager/cms/category/index.ftl

@@ -10,10 +10,10 @@
     <el-header class="ms-header" height="50px">
         <el-col :span=12>
             <@shiro.hasPermission name="cms:category:save">
-                <el-button type="primary" icon="el-icon-plus" size="mini" @click="save()">新增</el-button>
+                <el-button type="primary" class="el-icon-plus" size="default" @click="save()">新增</el-button>
             </@shiro.hasPermission>
             <@shiro.hasPermission name="cms:category:del">
-                <el-button type="danger" icon="el-icon-delete" size="mini" @click="del(selectionList)"
+                <el-button type="danger" class="el-icon-delete" size="default" @click="del(selectionList)"
                            :disabled="!selectionList.length">删除
                 </el-button>
             </@shiro.hasPermission>
@@ -21,7 +21,7 @@
     </el-header>
     <el-main class="ms-container">
         <el-table ref="multipleTable" :indent="6"
-                  height="calc(100vh - 20px)"
+                  height="calc(100vh - 100px)"
                   border :data="dataList"
                   row-key="id"
                   v-loading="loading"
@@ -29,19 +29,21 @@
                   :tree-props="{children: 'children'}"
                   tooltip-effect="dark"
                   @selection-change="handleSelectionChange">
-            <template slot="empty">
+            <template #empty>
                 {{emptyText}}
             </template>
             <el-table-column type="selection" width="40"></el-table-column>
             <el-table-column label="编号" width="100" prop="id" show-overflow-tooltip>
-                <template slot='header'>编号
+                <template #title>编号
                     <el-popover placement="top-start" title="提示" trigger="hover">
                         标签:<a href="http://doc.mingsoft.net/mcms/biao-qian/lan-mu-lie-biao-ms-channel.html"
                               target="_blank">${'$'}{field.id}</a>
-                        <i class="el-icon-question" slot="reference"></i>
+                        <template #reference>
+                            <i class="el-icon-question" ></i>
+                        </template>
                     </el-popover>
                 </template>
-                <template slot-scope="scope">
+                <template #default="scope">
                     <span style="cursor: pointer" class="copyBtn" :data-clipboard-text="scope.row.id"
                           @click="copyContent(true)">{{scope.row.id}}</span>
                 </template>
@@ -55,7 +57,7 @@
             <el-table-column label="排序" align="center" prop="categorySort" width="70">
             </el-table-column>
             <el-table-column label="链接地址" align="left" prop="categoryPath" min-width="200" show-overflow-tooltip>
-                <template slot-scope="scope">
+                <template #default="scope">
                     <span v-if="scope.row.categoryType == '1' || scope.row.categoryType == '2'" style="cursor: pointer"
                           class="copyBtn" :data-clipboard-text="scope.row.url"
                           @click="copyContent">{{scope.row.url}}</span>
@@ -66,18 +68,18 @@
             <el-table-column label="列表地址" align="left" prop="categoryListUrl" width="100" show-overflow-tooltip>
             </el-table-column>
             <el-table-column label="内容地址" align="left" prop="categoryUrl" width="100" show-overflow-tooltip>
-                <template slot-scope="scope">
+                <template #default="scope">
                     {{scope.row.categoryType == '1'?scope.row.categoryUrl:''}}
                     {{scope.row.categoryType == '2'?scope.row.categoryUrl:''}}
                 </template>
             </el-table-column>
             <el-table-column label="栏目属性" align="left" prop="categoryFlag" width="80" show-overflow-tooltip>
-                <template slot-scope="scope">
+                <template #default="scope">
                     {{getDictLabel(scope.row.categoryFlag)}}
                 </template>
             </el-table-column>
             <el-table-column label="操作" width="240" align="center">
-                <template slot-scope="scope">
+                <template #default="scope">
                     <el-link type="primary" :underline="false" v-if="scope.row.categoryType != '3'" @click="preview(scope.row)">预览</el-link>
                     <@shiro.hasPermission name="cms:category:save">
                         <el-link type="primary" :underline="false" @click="save(scope.row.id, scope.row.id)"><i
@@ -104,7 +106,7 @@
 <script>
     "use strict";
 
-    var indexVue = new Vue({
+    var indexVue = new _Vue({
         el: '#index',
         data: function () {
             return {

+ 172 - 166
src/main/webapp/WEB-INF/manager/cms/content/form.ftl

@@ -1,31 +1,23 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <title>文章</title>
-    <#include "../../include/head-file.ftl">
-    <script src="${base}/static/mdiy/index.js"></script>
-</head>
-<body>
+
+<template type="text/x-template" id="content-form">
 <div id="form" v-cloak>
     <el-header class="ms-header ms-tr" height="50px" >
-        <el-row type="flex" justify="space-between" align="middle">
-            <el-col :xs=12 :sm=14 :md=16 :lg=18 :xl=18 style="display:flex;align-items:center;">
-                <el-tooltip class="item" effect="dark" :content="form.id" placement="top-start">
-                    <span v-if="form.id && categoryType=='2'" style="float: left; max-width:calc(30% - 40px);" class="header-info">编号:{{form.id}}</span>
+            <el-col :span="12" style="display:flex;align-items:center;">
+                <el-tooltip v-if="form.id && categoryType=='2'" class="item" effect="dark" :content="form.id" placement="top-start">
+                    <span  style="float: left; " class="header-info">编号:{{form.id}}</span>
                 </el-tooltip>
-                <el-button v-if="form.id && categoryType=='2'" type="text" link style="float: left" icon="el-icon-document-copy" circle :data-clipboard-text="form.id" @click="copyString()" class="copyBtn"></el-button>
+                <el-button v-if="form.id && categoryType=='2'" type="primary" link style="float: left" class="el-icon-document-copy" circle :data-clipboard-text="form.id" @click="copyString()" class="copyBtn"></el-button>
             </el-col>
-            <el-col :xs=12 :sm=10 :md=8 :lg=6 :xl=6 class="ms-tr">
+            <el-col :span="12"  class="ms-tr">
                 <@shiro.hasPermission name="cms:content:save">
-                    <el-button type="primary" class="iconfont icon-baocun" size="mini" @click="save()" :loading="saveDisabled">保存
+                    <el-button type="primary" class="iconfont icon-baocun" size="default" @click="save()" :loading="saveDisabled">保存
                     </el-button>
                 </@shiro.hasPermission>
-                <el-button v-if="categoryType==1" size="mini" class="iconfont icon-fanhui" plain onclick="javascript:history.go(-1)">返回
+                <el-button v-if="categoryType==1" size="default" class="iconfont icon-fanhui" plain @click="back()">返回
                 </el-button>
-                <el-button v-if="categoryType==2" size="mini" type="danger" icon="el-icon-delete" @click="del()">删除
+                <el-button v-if="categoryType==2" size="default" type="danger" class="el-icon-delete" @click="del()" :disabled="!form.id" >删除
                 </el-button>
             </el-col>
-        </el-row>
     </el-header>
     <el-main class="ms-container" style="position:relative;">
         <el-scrollbar class="ms-scrollbar" style="height: 95vh">
@@ -33,7 +25,7 @@
                 <el-tab-pane style="position:relative;" v-for="(item, index) in editableTabs" :key="index"
                              :label="item.title" :name="item.name">
                     <el-form v-if="item.title=='文章编辑'" ref="form" :model="form" :rules="rules" label-width="120px"
-                             size="mini">
+                             size="default">
                         <el-row :gutter=0 justify="start" align="top">
                             <el-col :span=12>
                                 <el-form-item label="文章标题" prop="contentTitle">
@@ -50,18 +42,17 @@
                             </el-col>
                             <el-col :span=12 >
                                 <el-form-item label="所属栏目" prop="categoryId">
-                                    <treeselect v-model="form.categoryId"
-                                                :disabled="!returnIsShow"
-                                                :disable-branch-nodes="true"
-                                                :normalizer="function(node){
-                                                return {
-                                                    id: node.id,
-                                                    label: node.categoryTitle,
-                                                    children: node.children
-                                                }}"
-                                                @select="categoryChange"
-                                                :options="contentCategoryIdOptions" placeholder="请选择"></treeselect>
-
+                                    <el-tree-select
+                                            v-model="form.categoryId"
+                                            :disabled="!categoryChangeEnabled"
+                                            :data="contentCategoryIdOptions"
+                                            :props="{value: 'id',label: 'categoryTitle',children: 'children'}"
+                                            :render-after-expand="false"
+                                            :check-strictly="false"
+                                            :default-expand-all="false"
+                                            @change="categoryChange"
+                                            filterable
+                                    ></el-tree-select>
                                     <div class="ms-form-tip">
                                         标签:<a href="http://doc.mingsoft.net/mcms/biao-qian/wen-zhang-lie-biao-ms-arclist.html" target="_blank">${'$'}{field.typetitle}</a>
                                         不能选择封面、链接栏目类型,不能选择父栏目
@@ -132,8 +123,8 @@
                                             :disabled="false"
                                             :editable="true"
                                             :clearable="true"
-                                            format="yyyy-MM-dd HH:mm:ss"
-                                            value-format="yyyy-MM-dd HH:mm:ss"
+                                            format="YYYY-MM-DD HH:mm:ss"
+                                            value-format="YYYY-MM-DD HH:mm:ss"
                                             :style="{width:'100%'}"
                                             type="datetime">
                                     </el-date-picker>
@@ -216,7 +207,7 @@
                                             :action="ms.manager+'/file/upload.do'"
                                             :on-remove="contentImghandleRemove"
                                             :style="{width:''}"
-                                            :limit="10"
+                                            :limit="1"
                                             :on-exceed="contentImghandleExceed"
                                             :disabled="false"
                                             :data="{uploadPath:'/cms/content','isRename':true ,'appId':true}"
@@ -225,7 +216,7 @@
                                             accept="image/*"
                                             list-type="picture-card">
                                         <i class="el-icon-plus"></i>
-                                        <template slot="tip">
+                                        <template #tip>
                                             <div class="ms-form-tip">
                                                 标签:<a href="http://doc.mingsoft.net/mcms/biao-qian/wen-zhang-lie-biao-ms-arclist.html" target="_blank">${'{@ms:file field.litpic/}'}</a><br/>
                                                 最多可上传10张图片,文章缩略图,支持jpg格式;多图情况下,{@ms:file field.litpic/}会只取第一张缩略图,其他用法参考文档arclist标签
@@ -278,25 +269,31 @@
                                 标签:<a href="http://doc.mingsoft.net/mcms/biao-qian/wen-zhang-lie-biao-ms-arclist.html" target="_blank">${'$'}{field.descrip}</a>,用于SEO优化
                             </div>
                         </el-form-item>
-                        <el-form-item label="文章内容" prop="contentDetails">
-                            <vue-ueditor-wrap style="line-height: 0px" v-model="form.contentDetails"
+                        <el-form-item label="文章内容" prop="contentDetails" v-loading="editorHiden">
+                            <vue-ueditor-wrap style="line-height: 0px"
+                                              v-if="!editorHiden"
+                                              v-model="form.contentDetails"
                                               :config="editorConfig"></vue-ueditor-wrap>
                             <div class="ms-form-tip">
-                                标签:<a href="http://doc.mingsoft.net/mcms/biao-qian/wen-zhang-lie-biao-ms-arclist.html" target="_blank">${'$'}{field.content}</a>
+                                标签:<a href="http://doc.mingsoft.net/mcms/biao-qian/wen-zhang-lie-biao-ms-arclist.html" target="_blank">${'$'}{field.content}</a> <br/>
+                                温馨提示:推荐使用高级版本编辑器,<a href='http://store.mingsoft.net/#/detail?id=299&type=plugin' target="_blank">新版富文本编辑器</a>
                             </div>
                         </el-form-item>
                     </el-form>
-                    <div :id="'model'+index" v-else></div>
+                    <div :id="'model'+index" v-else>
+                        <ms-mdiy-form v-if="modelName!=null" ref="modelForm" type="model" :model-name="modelName" :model-id="modelId" :id="form.id"></ms-mdiy-form>
+                    </div>
                 </el-tab-pane>
             </el-tabs>
         </el-scrollbar>
     </el-main>
 </div>
-</body>
-</html>
+</template>
+
 <script>
-    var formVue = new Vue({
-        el: '#form',
+    var contentForm = Vue.defineComponent({
+        template: '#content-form',
+        props:["categoryId","categoryType","id"],
         data: function () {
             var checkTags = function (rule, value, callback){
                 if (value.length > 5){
@@ -305,10 +302,13 @@
                 callback();
             }
             return {
+                editorHiden:true,
                 saveDisabled: false,
                 activeName: 'form',
                 //自定义模型实例
                 model: undefined,
+                modelName:null,
+                modelId:null,
                 editableTabs: [{
                     title: '文章编辑',
                     name: 'form'
@@ -327,8 +327,8 @@
                     UEDITOR_HOME_URL: ms.base + '/static/plugins/ueditor/1.4.3.3/'
                 },
                 contentCategoryIdOptions: [],
-                returnIsShow: true,
-                type: '',
+                categoryChangeEnabled: true,
+                // type: '',
                 //表单数据
                 form: {
                     // 文章标题
@@ -361,7 +361,6 @@
                     contentOutLink: '',
                     contentDatetime: ms.util.date.fmt(Date.now(),"yyyy-MM-dd hh:mm:ss"),
                 },
-                categoryType: '1',
                 contentTypeOptions: [],
                 contentTagsOptions: [],
                 categoryIdOptions: [],
@@ -390,45 +389,56 @@
                     contentTags: [{
                         validator: checkTags, trigger: 'blur'
                     }]
-                }
+                },
+                historyKey:"cms_content_history"
             };
         },
         watch: {
+            "categoryId":function(n,o) {
+                this.activeName = "form";
+                this.$refs.form[0].resetFields();
+
+                this.contentCategoryIdOptionsGet();
+            },
 
         },
         computed: {
-            currCategory: function () {
-                var that = this;
-                return this.categoryIdOptions.find(function (value) {
-                    return value.id === that.form.categoryId;
-                });
-            }
+
         },
         methods: {
-            save: function () {
-                var _this = this;
+            back:function() {
+                if(this.$attrs.onBack) {
+                    this.$emit('back');
+                } else {
+                    this.$router.go(-1);
+                }
+            },
+
+            async save () {
                 var that = this; //自定义模型需要验证
 
-                var model = null;
-                if (that.currCategory && that.currCategory.mdiyModelId && String(that.currCategory.mdiyModelId )!="0"){
-                    try {
-                        model = ms.mdiy.model.modelForm();
-                    } catch (e) {
-                        console.log(e)
+
+
+                let formValid = false;
+
+                if(that.$refs.modelForm && that.$refs.modelForm.length > 0) {
+                    await that.$refs.modelForm[0].$refs.form.$refs.form.validate((valid,fields) => {
+                        formValid = valid;
+                    })
+
+                    if(!formValid) {
+                        this.activeName = 'custom-name';
+                        return;
                     }
                 }
-                if (model && !model.validate()) {
-                    this.activeName = 'custom-name';
-                    return;
-                }
+
                 var url = ms.manager + "/cms/content/save.do";
 
                 if (that.form.id > 0) {
                     url = ms.manager + "/cms/content/update.do";
-                }
-                //若缩略图为空则赋值为空串
-                if (that.form.contentImg.length == 0){
-                    that.form.contentImg = [];
+                } else {
+                    //新增数据重置到列表第一页
+                    sessionStorage.setItem(that.historyKey,JSON.stringify({form:{},page: {pageNo:1}}));
                 }
 
                 this.$refs.form[0].validate(function (valid) {
@@ -437,46 +447,56 @@
 
                         var data = JSON.parse(JSON.stringify(that.form));
                         // 固定属性顺序为字典顺序
-                        if (data.contentType) {
+                        if (data.contentType && data.contentType.length > 0) {
                             var orderTypes = [];
                             that.contentTypeOptions.forEach(function (dict) {
                                 var orderType = data.contentType.find(function (type) {
                                     return type==dict.dictValue
                                 })
                                 if (orderType){
-                                    orderTypes.push(orderType)
+                                    orderTypes.push(orderType);
                                 }
                             })
-                            data.contentType = orderTypes.join(',');
+                            data.contentType = orderTypes;
+                        }
+                        if (data.contentType) {
+                            data.contentType = data.contentType.join(',');
                         }
                         if (data.contentTags) {
                             data.contentTags = data.contentTags.join(',');
                         }
-                        if (data.contentImg == []) {
-                            data.contentImg = ""
-                        }else {
-                            data.contentImg = JSON.stringify(data.contentImg);
-                        }
-                        ms.http.post(url, data).then(function (data) {
-                            if (data.result) {
-                                //保存时需要赋值关联ID
-                                if (window.model) {
-                                    window.model.form.linkId = data.data.id;
-                                    window.model.save();
+
+                        data.contentImg = JSON.stringify(data.contentImg);
+                        ms.http.post(url, data).then(function (res) {
+                            if (res.result) {
+                                if(that.$refs.modelForm && that.$refs.modelForm.length > 0) {
+                                    that.$refs.modelForm[0].$refs.form.form.linkId = res.data.id;
+                                    that.$refs.modelForm[0].getForm().save(function (resModel) {
+                                        if(resModel.result){
+                                            //模型保存成功
+                                        }else {
+                                            //模型保存失败
+                                        }
+                                    });
                                 }
+
+
                                 that.$notify({
                                     title: '成功',
                                     message: '保存成功',
                                     type: 'success',
                                     duration: 1000,
                                     onClose: function () {
-                                        if (that.returnIsShow) {
-                                            javascript: history.go(-1);
-                                        } else {
-                                            //如果是顶级封面或封面,则重新加载,避免文章和自定义模型重复保存
-                                            location.reload();
+                                        if (that.categoryChangeEnabled) { //如果列表新增就需要返回的列表
+                                            that.$emit("back");
                                         }
                                         that.saveDisabled = false;
+                                        //为了让上传控件不显示类型警告
+                                        if(res.data.contentImg=="") {
+                                            res.data.contentImg =[];
+                                        }
+                                        that.form = res.data;
+
                                     }
                                 });
 
@@ -491,7 +511,7 @@
 
                         });
                     } else {
-                        _this.activeName = 'form';
+                        that.activeName = 'form';
                         return false;
                     }
                 });
@@ -504,7 +524,7 @@
                     cancelButtonText: '取消',
                     type: 'warning'
                 }).then(function () {
-                    var formData = that.form;
+                    var formData = JSON.parse(JSON.stringify(that.form));
                     formData.contentType = ""
                     formData.contentImg = ""
                     formData.contentTags = ""
@@ -519,8 +539,12 @@
                                 type: 'success',
                                 message: '删除成功!'
                             });
-                            //	刷新列表
-                            window.parent.location.reload();
+                            // 单篇删除 保留所属栏目
+                            var categoryId = that.form.categoryId;
+                            that.$refs.form[0].resetFields();
+                            that.form.id = "";
+                            that.form.categoryId = categoryId;
+                            that.activeName = "form";
                         } else {
                             that.$notify({
                                 title: '失败',
@@ -531,35 +555,32 @@
                     });
                 })
             },
-            categoryChange: function () {
-                this.changeModel();
+            categoryChange: function (node) {
+                // 新组件node就是节点id
+                this.changeModel(node);
             },
-            changeModel: function () {
+            changeModel: function (categoryId) {
                 var that = this;
                 that.editableTabs = [that.editableTabs[0]];
 
-                if (this.currCategory) {
-                    if (this.currCategory.mdiyModelId) {
-                        that.rederModel(this.currCategory.mdiyModelId)
-                    }
-                }
-            },
-            rederModel: function (modelId) {
-                var that = this;
-                that.editableTabs.push({
-                    title: '加载中...',
-                    name: 'custom-name'
-                });
-                window.formVue = this;
-                this.$nextTick(function () {
-                    ms.mdiy.model.extend("model1", {id:modelId},{ linkId: that.form.id },true).then(function(obj) {
-                        window.model = obj;
-                        that.editableTabs[1].title = obj.modelName
-                    });
-                });
+                var _category = this.categoryIdOptions.filter(function (value) {
+                    return value.id === categoryId;
+                })
 
 
+                //如果存在自定义模型
+                if(_category.length == 1 && _category[0].mdiyModelId) {
+                    ms.http.get(ms.manager + "/mdiy/model/get.do", {id: _category[0].mdiyModelId}).then(function (res) {
+                        if (res.result && res.data) {
+                            that.editableTabs.push({title: '加载中...',name: 'custom-name'});
+                            that.modelId = res.data.id;
+                            that.modelName = res.data.modelName;
+                            that.editableTabs[1].title = res.data.modelName
+                        }
+                    });
+                }
             },
+
             getValue: function (data) {
                 this.form.categoryId = data.id;
             },
@@ -597,18 +618,16 @@
                         });
 
                         if (category.length > 0) {
-                            that.categoryType = category[0].categoryType
-                            if (category[0].categoryType == '2' || category[0].categoryType == '3') {
-                                that.returnIsShow = false;
-                            }
+                            that.changeModel(category[0].id);
                         }
-                        that.changeModel();
+
                     }
                 });
             },
             //根据封面获取当前文章
             getFromFengMian: function (categoryId) {
                 var that = this;
+
                 ms.http.get(ms.manager + "/cms/content/getFromFengMian.do", {
                     "categoryId": categoryId
                 }).then(function (res) {
@@ -620,7 +639,7 @@
                                 res.data.contentType = [];
                             }
 
-                            if (res.data.contentImg && res.data.contentImg != '') {
+                            if (res.data.contentImg) {
                                 res.data.contentImg = JSON.parse(res.data.contentImg);
                                 res.data.contentImg.forEach(function (value) {
                                     value.url = ms.base + value.path;
@@ -636,18 +655,17 @@
                             }
 
                             that.form = res.data;
-                            var category = that.categoryIdOptions.filter(function (f) {
-                                return f['id'] == that.form.categoryId;
-                            });
 
-                            if (category.length > 0) {
-                                that.categoryType = category[0].categoryType
-                                if (category[0].categoryType == '2') {
-                                    that.returnIsShow = false;
-                                }
-                            }
                         }
-                        that.changeModel();
+                        // 左侧树选择单篇
+                        var category = that.categoryIdOptions.filter(function (f) {
+                            return f['id'] == that.form.categoryId;
+                        });
+                        if (category.length > 0) {
+                            that.categoryChangeEnabled = false;
+                            that.changeModel(category[0].id);
+                        }
+
                     } else {
                         that.$notify({
                             title: '失败',
@@ -655,6 +673,8 @@
                             type: 'warning'
                         });
                     }
+            }).catch(function (err) {
+                console.log(err);
                 });
             },
             //获取contentCategoryId数据源
@@ -663,9 +683,9 @@
                 ms.http.get(ms.manager + "/cms/category/list.do").then(function (res) {
                     if (res.result) {
                         res.data.rows.forEach(function (item) {
-                            // 栏目为单篇或链接且无子栏目 则不可选
-                            if ( (item.categoryType == '2' || item.categoryType == '3') && item.leaf) {
-                                item.isDisabled = true;
+                            // 单篇和链接类型的叶子栏目不可被选择
+                            if (item.categoryType == '2' || item.categoryType == '3') {
+                                item.disabled = true;
                             }
                         });
                         that.contentCategoryIdOptions = ms.util.treeData(res.data.rows, 'id', 'categoryId', 'children');
@@ -674,6 +694,8 @@
                         //获取到栏目数据之后再进行初始化
                         that.init();
                     }
+            }).catch(function (err) {
+                console.log(err);
                 });
             },
             //获取contentType数据源
@@ -687,6 +709,8 @@
                         data = data.data;
                         that.contentTypeOptions = data.rows;
                     }
+            }).catch(function (err) {
+                console.log(err);
                 });
             },
             //获取contentTag数据源
@@ -711,6 +735,7 @@
                         path: response.data,
                         uid: file.uid
                     });
+
                 }else {
                     this.$notify({
                         title: '失败',
@@ -733,7 +758,7 @@
             contentImghandleRemove: function (file, files) {
                 var index = -1;
                 index = this.form.contentImg.findIndex(function (text) {
-                    return text == file;
+                    return text.uid == file.uid;
                 });
 
                 if (index != -1) {
@@ -748,55 +773,35 @@
                     type: 'warning'
                 });
             },
-            //查询列表
-            list: function (categoryId) {
-                var that = this;
-                ms.http.post(ms.manager + "/cms/content/list.do", {
-                    categoryId: categoryId
-                }).then(function (res) {
-                    if (res.result && res.data.total > 0) {
-                        if (res.data.rows[0].contentType) {
-                            res.data.rows[0].contentType = res.data.rows[0].contentType.split(',');
-                        }
-
-                        if (res.data.rows[0].contentImg && res.data.rows[0].contentImg != '') {
-                            res.data.rows[0].contentImg = JSON.parse(res.data.rows[0].contentImg);
-                            res.data.rows[0].contentImg.forEach(function (value) {
-                                value.url = ms.base + value.path;
-                            });
-                        } else {
-                            res.data.rows[0].contentImg = [];
-                        }
-
-                        that.form = res.data.rows[0];
-                    }
-                });
-            },
             //只有在渲染完栏目数据之后才会初始化
             init: function () {
-                this.form.id = ms.util.getParameter("id");
-                this.type = ms.util.getParameter("type");
+                var that = this;
+                this.form.id = this.id;
+                that.editorHiden = true;
 
                 //在指定栏目下新增或编辑文章时
-                var categoryId = ms.util.getParameter("categoryId");
-                if (categoryId) {
-                    this.form.categoryId = categoryId;
+                if (this.categoryId) {
+                    this.form.categoryId = this.categoryId;
                     //如果是封面栏目直接跳转
-                    if (this.type) {
+                    if (this.categoryType=="2") { //封面
                         this.getFromFengMian(this.form.categoryId);
-                        this.returnIsShow = false;
+                        this.categoryChangeEnabled = false;
                         //指定非封面栏目编辑文章
                     }else if (this.form.id) {
                         this.get(this.form.id);
                         //指定栏目新增文章渲染自定义模型
                     }else {
-                        this.changeModel();
+                        this.changeModel(this.categoryId);
                     }
                     //不指定栏目编辑文章
                 }else if (this.form.id) {
                     this.get(this.form.id);
                 }//else 如果即不指定栏目新增文章,又不是编辑文章就不渲染自定义模型
 
+                setTimeout(()=>{
+                    //显示编辑器
+                    that.editorHiden = false;
+                },200)
             },
             //复制文章id
             copyString: function () {
@@ -830,6 +835,7 @@
 
     #form {
         overflow: hidden;
+        flex: 1;
     }
     .el-scrollbar__bar.is-vertical{
         width: 6px!important;

+ 50 - 22
src/main/webapp/WEB-INF/manager/cms/content/index.ftl

@@ -4,6 +4,8 @@
 	<meta charset="UTF-8">
 	<title>文章</title>
 	<#include "../../include/head-file.ftl">
+	<#include "/cms/content/form.ftl">
+	<#include "/cms/content/list.ftl">
 </head>
 <body style="overflow: hidden">
 <div id="index"  v-cloak>
@@ -22,7 +24,7 @@
 						:props="defaultProps"
 						@node-click="handleNodeClick"
 						style="padding: 10px;height: 100%;">
-						<template slot-scope="{ node, data }" >
+						<template #default="{ node, data }" >
 							<span class="custom-tree-node" >
 								<span :style="data.categoryType == '3' ? 'color: #dcdfe6' : ''" :title="data.categoryTitle">{{ data.categoryTitle }}</span>
 							</span>
@@ -30,40 +32,64 @@
 				</el-tree>
 			</el-scrollbar>
 		</div>
-		<iframe :src="action" :key="iframeKey" class="ms-iframe-style" style="background:url('${base}/static/images/loading.gif') no-repeat center;">
-		</iframe>
+		<content-list v-if="action=='list'" :category-id="categoryId" :leaf=leaf @form="form"></content-list>
+		<content-form v-else :category-id="categoryId" :category-type="categoryType" :id="id" @back="back"></content-form>
 	</el-container>
 </div>
 </body>
 </html>
 <script>
-	var indexVue = new Vue({
+	var indexVue = new _Vue({
 		el: "#index",
+		components:{
+			"content-list": contentList,
+			"content-form": contentForm
+		},
 		data: function () {
 			return {
-				iframeKey:'',
-				action: "",
-				//跳转页面
+				action: 'list',
+				categoryId:'', //栏目id
+				categoryType:'2', //1列表,2单篇
+				leaf:true, //true子栏目
+				id:null,//文章编号
 				defaultProps: {
 					children: 'children',
 					label: 'categoryTitle'
 				},
 				treeData: [],
 				loading: true,
-				emptyText: ''
+				emptyText: '',
+				historyKey:"cms_content_history"
 			}
 		},
+		watch:{
+        },
 		methods: {
 			handleNodeClick: function (data) {
-				this.iframeKey = new Date().getTime();
-				if (data.categoryType == '1') {
-					this.action = ms.manager + "/cms/content/main.do?categoryId=" + data.id+"&leaf="+data.leaf;
-				} else if (data.categoryType == '2') {
-					this.action = ms.manager + "/cms/content/form.do?categoryId=" + data.id + "&type=2";
-					//id=0时为最顶级节点全部节点
-				} else if (data.id == 0){
-					this.action = ms.manager + "/cms/content/main.do?leaf=false";
+				if(data.id == 0) { //全部
+					this.action = 'list';
+					this.categoryId = 0;
+					this.leaf = true;
+				} else if (data.categoryType == '1') {
+					this.action = 'list';
+					this.categoryId = data.id;
+					this.leaf = data.leaf;
+				} else {
+
+					this.action = 'form';
+					this.categoryId = data.id;
+					this.categoryType = data.categoryType;
 				}
+				//新增数据重置到列表第一页
+				sessionStorage.setItem(this.historyKey,JSON.stringify({form:{}, page: {pageNo:1}}));
+			},
+			form: function(id) {
+				this.action = 'form';
+				this.id = id;
+				this.categoryType = "1"; //列表
+			},
+			back: function(id) {
+				this.action = 'list';
 			},
 			treeList: function () {
 				var that = this;
@@ -101,12 +127,15 @@
 			}
 		},
 		mounted: function () {
-			this.action = ms.manager + "/cms/content/main.do";
 			this.treeList();
-		}
+		},
+		created:function (){
+			//默认列表第一页
+			sessionStorage.setItem(this.historyKey,JSON.stringify({form:{}, page: {pageNo:1}}));
+		},
 	});
 </script>
-<style>
+<style scoped>
 	#index .index-menu {
 		height: 100vh;
 		min-height: 100vh;
@@ -127,14 +156,13 @@
 		height: 100vh;
 	}
 
-	#index .index-menu .el-main {
-		padding: 0;
-	}
+
 	#index .left-tree{
 		min-height: 100vh;
 		background: #fff;
 		width: 220px;
 		border-right: solid 1px #e6e6e6;
+		flex-shrink: 0;
 	}
 
 	#index .index-menu .el-main .index-menu-menu .el-menu-item {

+ 554 - 0
src/main/webapp/WEB-INF/manager/cms/content/list.ftl

@@ -0,0 +1,554 @@
+
+<template type="text/x-template" id="content-main">
+<div id="main" class="ms-index"  v-cloak>
+    <ms-search ref="search" @search="search" :condition-data="conditionList" :conditions="conditions"></ms-search>
+    <el-header class="ms-header" height="50px">
+        <el-col :span=12>
+            <@shiro.hasPermission name="cms:content:save">
+                <el-button v-if="isLeaf==true" type="primary" class="el-icon-plus" size="default" @click="openForm()">新增</el-button>
+            </@shiro.hasPermission>
+            <@shiro.hasPermission name="cms:content:del">
+                <el-button type="danger" class="el-icon-delete" size="default" @click="del(selectionList)"  :disabled="!selectionList.length">删除</el-button>
+            </@shiro.hasPermission>
+        </el-col>
+    </el-header>
+    <div class="ms-search">
+        <el-row>
+            <el-form :model="form"  ref="searchForm"  label-width="120px" size="default">
+                <el-row>
+                    <el-col :span=8>
+                        <el-form-item  label="文章标题" prop="contentTitle">
+                            <el-input v-model="form.contentTitle"
+                                      :disabled="false"
+                                      :style="{width:  '100%'}"
+                                      :clearable="true"
+                                      placeholder="请输入文章标题">
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span=8>
+                        <el-form-item  label="文章类型" prop="contentType">
+                            <el-select v-model="form.contentType"
+                                       :style="{width: '100%'}"
+                                       :filterable="false"
+                                       :disabled="false"
+                                       :multiple="true" :clearable="true"
+                                       placeholder="请选择文章类型">
+                                <el-option v-for='item in contentTypeOptions' :key="item.dictValue" :value="item.dictValue"
+                                           :label="item.dictLabel"></el-option>
+                            </el-select>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span=8 style="text-align: right;padding-right: 10px;">
+                        <el-button type="primary" class="el-icon-search" size="default" @click="form.sqlWhere=null;currentPage=1;list()">查询</el-button>
+                        <el-button @click="rest"  class="el-icon-refresh" size="default">重置</el-button>
+                        <el-button type="primary" class="el-icon-s-operation" size="default" @click="$refs.search.open()">筛选</el-button>
+                    </el-col>
+                </el-row>
+            </el-form>
+        </el-row>
+    </div>
+    <el-main class="ms-container">
+        <el-table v-loading="loading" ref="multipleTable" class="ms-table-pagination" border :data="dataList" tooltip-effect="dark" @selection-change="handleSelectionChange">
+            <template #empty>
+                {{emptyText}}
+            </template>
+            <el-table-column type="selection" width="40"></el-table-column>
+            <el-table-column label="编号" width="200" prop="id">
+                <template #header>编号
+                    <el-popover placement="top-start" title="提示" trigger="hover" >
+                        标签:<a href="http://doc.mingsoft.net/mcms/biao-qian/wen-zhang-lie-biao-ms-arclist.html#%E6%96%87%E7%AB%A0%E5%88%97%E8%A1%A8-msarclist" target="_blank">${'$'}{field.id}</a>
+                        <template #reference>
+                            <i class="el-icon-question"></i>
+                        </template>
+                    </el-popover>
+                </template>
+            </el-table-column>
+            <el-table-column label="栏目名" align="left" prop="categoryId" :formatter="contentCategoryIdFormat" width="180">
+            </el-table-column>
+            <el-table-column label="文章标题" align="left" prop="contentTitle" show-overflow-tooltip>
+            </el-table-column>
+            <el-table-column label="文章副标题" align="left" prop="contentShortTitle" show-overflow-tooltip>
+            </el-table-column>
+            <el-table-column label="文章链接" align="left" prop="categoryId" :formatter="contentCategoryPathFormat" width="240">
+            </el-table-column>
+            <el-table-column label="作者" align="left" prop="contentAuthor" width="100" show-overflow-tooltip>
+            </el-table-column>
+            <el-table-column label="排序" width="55" align="right" prop="contentSort">
+            </el-table-column>
+            <el-table-column label="点击量" width="90" align="right" prop="contentHit">
+                <template #header>点击量
+                    <el-popover placement="top-start" title="提示" trigger="hover" >
+                        标签:<a href="http://doc.mingsoft.net/mcms/biao-qian/wen-zhang-lie-biao-ms-arclist.html#%E6%96%87%E7%AB%A0%E5%88%97%E8%A1%A8-msarclist" target="_blank">${'$'}{field.hit}</a>
+                        <template #reference>
+                            <i class="el-icon-question"></i>
+                        </template>
+                    </el-popover>
+                </template>
+                <template #default="scope">
+                    {{scope.row.contentHit?scope.row.contentHit:0}}
+                </template>
+            </el-table-column>
+            <el-table-column label="发布时间" align="center" prop="contentDatetime" :formatter="dateFormat" width="120">
+            </el-table-column>
+            <el-table-column label="操作" width="120" align="center"   fixed="right">
+                <template #default="scope">
+                    <@shiro.hasPermission name="cms:content:update">
+                        <el-link type="primary" :underline="false" @click="openForm(scope.row.id)">编辑</el-link>
+                    </@shiro.hasPermission>
+                    <@shiro.hasPermission name="cms:content:del">
+                        <el-link type="primary" :underline="false" @click="del([scope.row])">删除</el-link>
+                    </@shiro.hasPermission>
+                </template>
+            </el-table-column>
+        </el-table>
+        <el-pagination
+                background
+                :page-sizes="[10,20,30,40,50,100]"
+                layout="total, sizes, prev, pager, next, jumper"
+                :current-page="currentPage"
+                :page-size="pageSize"
+                :total="total"
+                class="ms-pagination"
+                @current-change='currentChange'
+                @size-change="sizeChange">
+        </el-pagination>
+    </el-main>
+</div>
+</template>
+
+<script>
+    var contentList = Vue.defineComponent({
+        template: '#content-main',
+        props:["categoryId","leaf"],
+        data: function () {
+            return {
+                conditionList: [{
+                    action: 'and',
+                    field: 'content_title',
+                    el: 'eq',
+                    model: 'contentTitle',
+                    name: '文章标题',
+                    type: 'input'
+                }, {
+                    action: 'and',
+                    field: 'content_short_title',
+                    el: 'eq',
+                    model: 'contentShortTitle',
+                    name: '文章副标题',
+                    type: 'input'
+                }, {
+                    action: 'and',
+                    field: 'category_id',
+                    el: 'eq',
+                    model: 'categoryId',
+                    name: '所属栏目',
+                    key: 'id',
+                    title: 'categoryTitle',
+                    type: 'cascader',
+                    multiple: false
+                }, {
+                    action: 'and',
+                    field: 'content_type',
+                    el: 'eq',
+                    model: 'contentType',
+                    name: '文章类型',
+                    key: 'dictValue',
+                    title: 'dictLabel',
+                    type: 'checkbox',
+                    label: false,
+                    multiple: true
+                }, {
+                    action: 'and',
+                    field: 'content_display',
+                    el: 'eq',
+                    model: 'contentDisplay',
+                    name: '是否显示',
+                    key: 'value',
+                    title: 'label',
+                    type: 'radio',
+                    label: true,
+                    multiple: false
+                }, {
+                    action: 'and',
+                    field: 'content_author',
+                    el: 'eq',
+                    model: 'contentAuthor',
+                    name: '文章作者',
+                    type: 'input'
+                }, {
+                    action: 'and',
+                    field: 'content_source',
+                    el: 'eq',
+                    model: 'contentSource',
+                    name: '文章来源',
+                    type: 'input'
+                }, {
+                    action: 'and',
+                    field: 'ct.content_datetime',
+                    model: 'contentDatetime',
+                    el: 'gt',
+                    name: '发布时间',
+                    type: 'date'
+                }, {
+                    action: 'and',
+                    field: 'content_sort',
+                    el: 'eq',
+                    model: 'contentSort',
+                    name: '自定义顺序',
+                    type: 'number'
+                }, {
+                    action: 'and',
+                    field: 'content_description',
+                    el: 'eq',
+                    model: 'contentDescription',
+                    name: '描述',
+                    type: 'textarea'
+                }, {
+                    action: 'and',
+                    field: 'content_keyword',
+                    el: 'eq',
+                    model: 'contentKeyword',
+                    name: '关键字',
+                    type: 'textarea'
+                }, {
+                    action: 'and',
+                    field: 'content_details',
+                    el: 'like',
+                    model: 'contentDetails',
+                    name: '文章内容',
+                    type: 'input'
+                }, {
+                    action: 'and',
+                    field: 'content_url',
+                    el: 'eq',
+                    model: 'contentUrl',
+                    name: '文章跳转链接地址',
+                    type: 'input'
+                }, {
+                    action: 'and',
+                    field: 'ct.create_date',
+                    el: 'eq',
+                    model: 'createDate',
+                    name: '创建时间',
+                    type: 'date'
+                }, {
+                    action: 'and',
+                    field: 'ct.update_date',
+                    el: 'eq',
+                    model: 'updateDate',
+                    name: '修改时间',
+                    type: 'date'
+                }],
+                conditions: [],
+                contentCategoryIdOptions: [],
+                dataList: [],
+                //文章列表
+                selectionList: [],
+                //文章列表选中
+                total: 0,
+                //总记录数量
+                pageSize: 10,
+                //页面数量
+                currentPage: 1,
+                //初始页
+                manager: ms.manager,
+                loadState: false,
+                loading: true,
+                //加载状态
+                emptyText: '',
+                //提示文字
+                contentTypeOptions: [],
+                contentDisplayOptions: [{
+                    "value": "0",
+                    "label": "是"
+                }, {
+                    "value": "1",
+                    "label": "否"
+                }],
+                //搜索表单
+                form: {
+                    sqlWhere: null,
+                    // 文章标题
+                    contentTitle: null,
+                    // 文章类型
+                    contentType: null,
+                    categoryId: ''
+                },
+                isLeaf: true,
+                historyKey:"cms_content_history"
+            }
+        },
+        watch: {
+            "categoryId":function(n,o) {
+
+                this.list();
+            },
+            "leaf":function(n,o) {
+
+                this.isLeaf = n;
+            }
+        },
+
+        methods: {
+            //查询列表
+            list: function () {
+                var that = this;
+                that.loading = true;
+                that.loadState = false;
+                var page = {
+                    pageNo: that.currentPage,
+                    pageSize: that.pageSize
+                };
+                that.form.categoryId = this.categoryId;
+                that.isLeaf = this.leaf;
+
+                var form = JSON.parse(JSON.stringify(that.form));
+
+                if (form.contentType!=null && form.contentType.length > 0) {
+                    form.contentType = form.contentType.join(',');
+                }
+
+                for (var key in form) {
+                    if (!form[key]) {
+                        delete form[key];
+                    }
+                }
+                sessionStorage.setItem(that.historyKey,JSON.stringify({form: form, page: page}));
+                //筛选栏目类型,1=列表
+                that.form.categoryType = '1';
+                ms.http.post(ms.manager + "/cms/content/list.do", form.sqlWhere ? Object.assign({}, {
+                    categoryType: '1',
+                    sqlWhere: form.sqlWhere
+                }, page) : Object.assign({}, form, page)).then(function (res) {
+                    if (that.loadState) {
+                        that.loading = false;
+                    } else {
+                        that.loadState = true;
+                    }
+
+                    if (!res.result || res.data.total <= 0) {
+                        that.emptyText = '暂无数据';
+                        that.dataList = [];
+                        that.total = 0;
+                    } else {
+                        that.emptyText = '';
+                        that.total = res.data.total;
+                        that.dataList = res.data.rows;
+                    }
+
+                }).finally(function () {
+                    that.loading = false;
+                });
+                setTimeout(function () {
+                    if (that.loadState) {
+                        that.loading = false;
+                    } else {
+                        that.loadState = true;
+                    }
+                }, 500);
+            },
+            //文章列表选中
+            handleSelectionChange: function (val) {
+                this.selectionList = val;
+            },
+            //删除
+            del: function (row) {
+                var that = this;
+                that.$confirm('此操作将永久删除所选内容, 是否继续?', '提示', {
+                    confirmButtonText: '确定',
+                    cancelButtonText: '取消',
+                    type: 'warning'
+                }).then(function () {
+                    ms.http.post(ms.manager + "/cms/content/delete.do", row.length ? row : [row], {
+                        headers: {
+                            'Content-Type': 'application/json'
+                        }
+                    }).then(function (res) {
+                        if (res.result) {
+                            that.$notify({
+                                title:'成功',
+                                type: 'success',
+                                message: '删除成功!'
+                            }); //删除成功,刷新列表
+                            that.currentChange()
+                        } else {
+                            that.$notify({
+                                title: '失败',
+                                message: res.msg,
+                                type: 'warning'
+                            });
+                        }
+                    });
+                })
+            },
+            //新增
+            openForm: function (id) {
+                this.$emit("form",id)
+            },
+            // 表格数据转换 id->name
+            contentCategoryIdFormat: function (row, column, cellValue, index) {
+                var value = "";
+
+                if (cellValue) {
+                    var data = this.contentCategoryIdOptions.find(function (value) {
+                        return value.id == cellValue;
+                    });
+
+                    if (data && data.categoryTitle) {
+                        value = data.categoryTitle;
+                    }
+                }
+
+                return value;
+            },
+            // 表格数据转换 id->path
+            contentCategoryPathFormat: function (row, column, cellValue, index) {
+                var path = "";
+                if (cellValue) {
+                    var data = this.contentCategoryIdOptions.find(function (value) {
+                        return value.id == cellValue;
+                    });
+                    if (data && data.categoryPath) {
+                        // row.url /html/web/categoryPath/文章id.html categoryPath做占位符
+                            path = row.url.replace("categoryPath",data.categoryPath);
+                    }else {
+                        path = row.url;
+                    }
+                }
+                return path;
+            },
+            dateFormat: function (row, column, cellValue, index) {
+                if (cellValue) {
+                    return ms.util.date.fmt(cellValue, 'yyyy-MM-dd');
+                } else {
+                    return '';
+                }
+            },
+            contentDisplayFormat: function (row, column, cellValue, index) {
+                var value = "";
+
+                if (cellValue) {
+                    var data = this.contentDisplayOptions.find(function (value) {
+                        return value.value == cellValue;
+                    });
+
+                    if (data && data.label) {
+                        value = data.label;
+                    }
+                }
+
+                return value;
+            },
+            //pageSize改变时会触发
+            sizeChange: function (pagesize) {
+                this.loading = true;
+                this.pageSize = pagesize;
+                this.list();
+            },
+            //currentPage改变时会触发
+            currentChange: function (currentPage) {
+                this.loading = true;
+                this.currentPage = currentPage;
+                this.list();
+            },
+            search: function (data) {
+                this.form.sqlWhere = JSON.stringify(data);
+                this.list();
+            },
+            //重置表单
+            rest: function () {
+                this.form.sqlWhere = null;
+                this.$refs.searchForm.resetFields();
+                this.list();
+            },
+            //获取contentCategoryId数据源
+            contentCategoryIdOptionsGet: function () {
+                var that = this;
+                ms.http.get(ms.manager + "/cms/category/list.do").then(function (res) {
+                    if (res.result) {
+                        that.contentCategoryIdOptions = res.data.rows;
+                    }else {
+                        that.$notify({
+                            title: '失败',
+                            message: res.msg,
+                            type: 'warning'
+                        });
+                    }
+
+                    that.list();
+                });
+            },
+            //获取contentType数据源
+            contentTypeOptionsGet: function () {
+                var that = this;
+                ms.http.get(ms.base + '/mdiy/dict/list.do', {
+                    dictType: '文章属性',
+                    pageSize: 99999
+                }).then(function (data) {
+                    if(data.result){
+                        data = data.data;
+                        that.contentTypeOptions = data.rows;
+                    }
+                });
+            }
+        },
+        mounted: function () {
+            this.contentCategoryIdOptionsGet();
+            this.contentTypeOptionsGet();
+            //如果存在历史参数,恢复页面结果
+            if(sessionStorage.getItem(this.historyKey)) {
+                var _history = JSON.parse(sessionStorage.getItem(this.historyKey))
+                if(_history.form) {
+                    this.form = _history.form;
+                }
+                if(_history.total) {
+                    this.total = parseInt(_history.total);
+                }
+                if(_history.page.pageNo) {
+                    this.currentPage = parseInt(_history.page.pageNo);
+                }
+                if(_history.page.pageSize) {
+                    this.pageSize = parseInt(_history.page.pageSize);
+                }
+            }
+        },
+
+        created: function () {
+            //因为mounted生命周期,不能更新data对象,所以需要增加created进行处理
+            if(sessionStorage.getItem(this.historyKey)) {
+                var _history = JSON.parse(sessionStorage.getItem(this.historyKey))
+                if(_history.form) {
+                    this.form = _history.form;
+                }
+                if(_history.total) {
+                    this.total = parseInt(_history.total);
+                }
+                if(_history.page.pageNo) {
+                    this.currentPage = parseInt(_history.page.pageNo);
+                }
+                if(_history.page.pageSize) {
+                    this.pageSize = parseInt(_history.page.pageSize);
+                }
+
+            }
+        }
+        
+    });
+</script>
+<style scoped>
+    #main .ms-search {
+        padding: 20px 0 0;
+    }
+    #main .ms-container {
+        height: calc(100vh - 141px);
+    }
+    #main  {
+        height:  100vh;
+        width: calc(100% - 220px);
+    }
+    body{
+        overflow: hidden;
+    }
+
+</style>

+ 38 - 17
src/main/webapp/WEB-INF/manager/cms/generate/index.ftl

@@ -10,7 +10,18 @@
 </head>
 <body class="custom-body">
 <div id="app" class="ms-index" v-cloak>
-    <el-form ref="form" label-width="100px" size="mini">
+    <el-main class="ms-container">
+
+        <el-alert
+                class="ms-alert-tip"
+                title="提示"
+                type="info">
+             如果需要使用自动静态化的功能,即文章发布后会自动进行更新,简单的可以采用MStore 的<a href='http://store.mingsoft.net/#/detail?id=290&type=plugin' target="_blank">自动静态化插件</a>,如果需要更好的静态化性能可以考考虑选购企业级<a href="https://www.mingsoft.net/banben.html" target="_blank">版本</a>
+        </el-alert>
+
+
+    <el-form ref="form" label-width="100px" size="default">
+
         <div class="class-2" >
             <div class="class-3 panel" >
                 <div class="class-4" >
@@ -56,11 +67,16 @@
             <div class="class-13 panel" >
                 <div class="class-14" >
                     <el-form-item label="文章栏目">
-                        <ms-tree-select v-model:value="contentSection"
-                                     :props="{value: 'id',label: 'categoryTitle',children: 'children'}"
-                                     :options="treeList" :style="{width:'100%'}"
-                                     placeholder="请选择文章栏目">
-                        </ms-tree-select>
+                        <el-tree-select
+                                v-model="contentSection"
+                                :data="treeList"
+                                :props="{value: 'id',label: 'categoryTitle',children: 'children'}"
+                                :render-after-expand="false"
+                                :check-strictly="true"
+                                :default-expand-all="true"
+                                placeholder="请选择文章栏目"
+                                filterable
+                        ></el-tree-select>
                         <div class="ms-form-tip">
                             生成指定栏目下的文章内容
                         </div>
@@ -77,8 +93,8 @@
                                 :disabled="false"
                                 :editable="false"
                                 :clearable="false"
-                                format="yyyy-MM-dd"
-                                value-format="yyyy-MM-dd"
+                                format="YYYY-MM-DD"
+                                value-format="YYYY-MM-DD"
                                 :style="{width:'100%'}"
                                 type="date">
                         </el-date-picker>
@@ -99,13 +115,19 @@
             <div class="class-23 panel" >
                 <div class="class-24" >
                     <el-form-item label="生成栏目">
-                        <ms-tree-select v-model:value="section"
-                                     :props="{value: 'id',label: 'categoryTitle',children: 'children'}"
-                                     :options="treeList" :style="{width:'100%'}"
-                                     placeholder="请选择文章栏目">
-                        </ms-tree-select>
+                        <el-tree-select
+                                v-model="section"
+                                :data="treeList"
+                                :props="{value: 'id',label: 'categoryTitle',children: 'children'}"
+                                :render-after-expand="false"
+                                :check-strictly="true"
+                                :default-expand-all="true"
+                                placeholder="请选择文章栏目"
+                                filterable
+                        ></el-tree-select>
                         <div class="ms-form-tip">
-                            生成<b>栏目类型</b>为列表的数据,例如:新闻列表、产品列表
+                            生成<b>栏目类型</b>为列表的数据,例如:新闻列表、产品列表 <br>
+                            单篇栏目绑定模板后没有文章,也会生成对应html
                         </div>
                     </el-form-item>
                 </div>
@@ -121,13 +143,14 @@
             </div>
         </div>
     </el-form>
+    </el-main>
 </div>
 </body>
 </html>
 <script>
     "use strict";
 
-    var app = new Vue({
+    var app = new _Vue({
         el: '#app',
         watch: {},
         data: function () {
@@ -327,7 +350,6 @@
         background-color:#FFFFFF;
         flex-direction:column;
         display:flex;
-        margin: 12px 6px 12px 12px;
         animation-duration:1s;
         width:100%;
         padding-left:20px;
@@ -618,7 +640,6 @@
         background-color:#FFFFFF;
         flex-direction:column;
         display:flex;
-        margin: 12px 12px 12px 6px;
         animation-duration:1s;
         width:100%;
         padding-left:20px;

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