mingsoft 2 anni fa
parent
commit
f0b19de1ff

+ 45 - 6
src/main/java/net/mingsoft/cms/action/CategoryAction.java

@@ -37,7 +37,9 @@ import net.mingsoft.basic.util.BasicUtil;
 import net.mingsoft.basic.util.PinYinUtil;
 import net.mingsoft.basic.util.StringUtil;
 import net.mingsoft.cms.biz.ICategoryBiz;
+import net.mingsoft.cms.constant.e.CategoryTypeEnum;
 import net.mingsoft.cms.entity.CategoryEntity;
+import net.mingsoft.mdiy.util.ParserUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -89,9 +91,8 @@ public class CategoryAction extends BaseAction {
     @RequestMapping(value = "/list", method = {RequestMethod.GET, RequestMethod.POST})
     @ResponseBody
     public ResultData list(@ModelAttribute @ApiIgnore CategoryEntity category) {
-        BasicUtil.startPage();
         List categoryList = categoryBiz.list(new LambdaQueryWrapper<CategoryEntity>(category));
-        return ResultData.build().success(new EUListBean(categoryList, (int) BasicUtil.endPage(categoryList).getTotal()));
+        return ResultData.build().success(new EUListBean(categoryList, categoryList.size()));
     }
 
     /**
@@ -163,9 +164,16 @@ public class CategoryAction extends BaseAction {
             return ResultData.build().error(getResString("err.length", this.getResString("category.title"), "1", "100"));
         }
 
-        if (!StringUtil.checkLength(category.getCategoryPath() + "", 1, 100)) {
-            return ResultData.build().error(getResString("err.length", this.getResString("category.path"), "1", "100"));
+        // 判断前端拼音传值是否正常
+        if (!StringUtil.checkLength(category.getCategoryPinyin() + "", 0, 100)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.pinyin"), "1", "100"));
         }
+
+        // 过滤非法路径
+        if (category.getCategoryPinyin().contains("../") || category.getCategoryPinyin().contains("..\\")) {
+            return ResultData.build().error(this.getResString("err.error",this.getResString("category.pinyin")));
+        }
+
         if (!StringUtil.checkLength(category.getCategoryParentIds() + "", 1, 100)) {
             return ResultData.build().error(getResString("err.length", this.getResString("category.parent.id"), "1", "100"));
         }
@@ -240,6 +248,9 @@ public class CategoryAction extends BaseAction {
         if (category.getCategoryImg() == null || !category.getCategoryImg().matches("^\\[.{1,}]$")) {
             category.setCategoryImg("");
         }
+        if (StringUtils.isEmpty(category.getId())){
+            return ResultData.build().error(getResString("err.empty", this.getResString("category.id")));
+        }
         //验证栏目管理名称的值是否合法
         if (StringUtil.isBlank(category.getCategoryTitle())) {
             return ResultData.build().error(getResString("err.empty", this.getResString("category.title")));
@@ -248,12 +259,17 @@ public class CategoryAction extends BaseAction {
             return ResultData.build().error(getResString("err.length", this.getResString("category.title"), "1", "100"));
         }
 
-        if (!StringUtil.checkLength(category.getCategoryPath() + "", 0, 100)) {
-            return ResultData.build().error(getResString("err.length", this.getResString("category.path"), "1", "100"));
+        // 判断前端拼音传值是否正常
+        if (!StringUtil.checkLength(category.getCategoryPinyin() + "", 1, 100)) {
+            return ResultData.build().error(getResString("err.length", this.getResString("category.pinyin"), "1", "100"));
         }
         if (!StringUtil.checkLength(category.getCategoryParentIds() + "", 0, 100)) {
             return ResultData.build().error(getResString("err.length", this.getResString("category.parent.id"), "1", "100"));
         }
+        // 过滤非法路径
+        if (category.getCategoryPinyin().contains("../") || category.getCategoryPinyin().contains("..\\")) {
+            return ResultData.build().error(this.getResString("err.error",this.getResString("category.pinyin")));
+        }
         //判断拼音是否重复并且是否和原拼音相同
         if (StrUtil.isNotBlank(category.getCategoryPinyin()) && !categoryBiz.getById(category.getId()).getCategoryPinyin().equals(category.getCategoryPinyin())) {
             if (!category.getCategoryPinyin().matches("^[a-zA-Z0-9]*$")){
@@ -373,4 +389,27 @@ public class CategoryAction extends BaseAction {
         return ResultData.build().success();
     }
 
+
+    @ApiOperation(value = "强制转换类型接口")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "typeid", value = "编号", required =true,paramType="query"),
+            @ApiImplicitParam(name = "categoryType", value = "栏目类型", required =true,paramType="query")
+    })
+    @GetMapping("/changeType")
+    @ResponseBody
+    @RequiresPermissions("cms:category:update")
+    public ResultData changeType(){
+        String typeId = BasicUtil.getString(ParserUtil.TYPE_ID);
+        String categoryType = BasicUtil.getString("categoryType");
+        CategoryEntity category = categoryBiz.getById(typeId);
+        if (category == null){
+            return ResultData.build().error(getResString("err.error",getResString("id")));
+        }
+        if (CategoryTypeEnum.get(categoryType).equals(CategoryTypeEnum.UN_KNOW)){
+            return ResultData.build().error(getResString("err.error",getResString("category.type")));
+        }
+        categoryBiz.changeCategoryType(category,categoryType);
+        return ResultData.build().success(category);
+    }
+
 }

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

@@ -159,11 +159,11 @@ public class GeneraterAction extends BaseAction {
      * @param response
      * @param categoryId
      */
-    @RequestMapping(value = "/{categoryId}/genernateColumn", method = {RequestMethod.GET, RequestMethod.POST})
+    @RequestMapping(value = "/{categoryId}/generateColumn", method = {RequestMethod.GET, RequestMethod.POST})
     @LogAnn(title = "生成栏目", businessType = BusinessTypeEnum.UPDATE)
     @RequiresPermissions("cms:generate:column")
     @ResponseBody
-    public ResultData genernateColumn(HttpServletRequest request, HttpServletResponse response, @PathVariable String categoryId) throws IOException {
+    public ResultData generateColumn(HttpServletRequest request, HttpServletResponse response, @PathVariable String categoryId) throws IOException {
         // 获取站点id
         AppEntity app = BasicUtil.getApp();
 

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

@@ -74,6 +74,8 @@ public class ContentAction extends net.mingsoft.cms.action.BaseAction{
     	@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 = "flag", value = "文章类型", required =false,paramType="query"),
+    	@ApiImplicitParam(name = "noflag", 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"),

+ 15 - 3
src/main/java/net/mingsoft/cms/action/web/MCmsAction.java

@@ -35,6 +35,7 @@ import net.mingsoft.cms.entity.CategoryEntity;
 import net.mingsoft.mdiy.bean.PageBean;
 import net.mingsoft.mdiy.biz.IModelBiz;
 import net.mingsoft.mdiy.entity.ModelEntity;
+import net.mingsoft.mdiy.util.ConfigUtil;
 import net.mingsoft.mdiy.util.ParserUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -92,9 +93,7 @@ public class MCmsAction extends net.mingsoft.cms.action.BaseAction {
 
     /**
      * 实现前端页面的文章搜索
-     *
-     * @param request  搜索id
-     * @param response
+     * @return 渲染后的搜索页面
      */
     @RequestMapping(value = "search",method = {RequestMethod.GET, RequestMethod.POST},produces= MediaType.TEXT_HTML_VALUE+";charset=utf-8")
     @ResponseBody
@@ -127,6 +126,9 @@ public class MCmsAction extends net.mingsoft.cms.action.BaseAction {
         //获取栏目信息
         String typeId = null;
         String categoryIds = BasicUtil.getString("categoryIds");
+        if ("null".equals(categoryIds)){
+            categoryIds = null;
+        }
 
         //List categoryIdList = CollectionUtil.newArrayList();
 
@@ -224,6 +226,10 @@ public class MCmsAction extends net.mingsoft.cms.action.BaseAction {
 
 
         Map<String, Object> searchMap = field;
+        String contentTag = BasicUtil.getString("content_tag");
+        if (StringUtils.isNotBlank(contentTag)){
+            searchMap.put("content_tag", contentTag);
+        }
         searchMap.put("categoryIds",categoryIds);
         StringBuilder urlParams = new StringBuilder();
 
@@ -244,14 +250,20 @@ public class MCmsAction extends net.mingsoft.cms.action.BaseAction {
         params.put("search", searchMap);
 
         //站点编号
+        Boolean shortSwitch = ConfigUtil.getBoolean("短链配置", "shortLinkSwitch");
         if (BasicUtil.getWebsiteApp() != null) {
             params.put(ParserUtil.APP_DIR, BasicUtil.getWebsiteApp().getAppDir());
             params.put(ParserUtil.URL, BasicUtil.getWebsiteApp().getAppHostUrl());
             params.put(ParserUtil.APP_ID, BasicUtil.getWebsiteApp().getAppId());
+        } else if (shortSwitch){
+            params.put(ParserUtil.URL, BasicUtil.getUrl());
+            params.put(ParserUtil.APP_DIR, "");
         } else {
             params.put(ParserUtil.URL, BasicUtil.getUrl());
             params.put(ParserUtil.APP_DIR, BasicUtil.getApp().getAppDir());
         }
+        params.put(ParserUtil.SHORT_SWITCH, shortSwitch);
+
         //对项目名预处理
         String contextPath = BasicUtil.getContextPath();
         if (StringUtils.isNotBlank(contextPath) && "/".equalsIgnoreCase(contextPath) ){

+ 28 - 5
src/main/java/net/mingsoft/cms/aop/CategoryAop.java

@@ -14,6 +14,7 @@ import net.mingsoft.base.entity.ResultData;
 import net.mingsoft.basic.exception.BusinessException;
 import net.mingsoft.basic.util.BasicUtil;
 import net.mingsoft.cms.constant.e.CategoryDisplayEnum;
+import net.mingsoft.cms.constant.e.CategoryIsSearchEnum;
 import net.mingsoft.cms.constant.e.CategoryTypeEnum;
 import net.mingsoft.cms.dao.ICategoryDao;
 import net.mingsoft.cms.dao.IContentDao;
@@ -78,18 +79,35 @@ public class CategoryAop extends net.mingsoft.basic.aop.BaseAop {
             throw new BusinessException("栏目不存在!");
         }
 
+        // 获取返回值
+        Object obj = pjp.proceed(pjp.getArgs());
+        ResultData resultData = JSONUtil.toBean(JSONUtil.toJsonStr(obj), ResultData.class);
+        category = resultData.getData(CategoryEntity.class);
+
+        if (category == null) {
+            return resultData;
+        }
+
         // 如果栏目被设置为不显示,将栏目下所有子栏目也设置为不显示
         if (CategoryDisplayEnum.DISABLE.toString().equalsIgnoreCase(category.getCategoryDisplay())){
             List<String> ids = categoryDao.queryChildren(category).stream().map(CategoryEntity::getId).collect(Collectors.toList());
             LambdaUpdateWrapper<CategoryEntity> wrapper = new UpdateWrapper<CategoryEntity>().lambda();
             wrapper.set(CategoryEntity::getCategoryDisplay,CategoryDisplayEnum.DISABLE.toString());
             wrapper.in(CategoryEntity::getId,ids);
-            categoryDao.update(new CategoryEntity(),wrapper);
+            categoryDao.update(null,wrapper);
 
         }
-        // 获取返回值
-        Object obj = pjp.proceed(pjp.getArgs());
-        ResultData resultData = JSONUtil.toBean(JSONUtil.toJsonStr(obj), ResultData.class);
+
+        // 如果栏目被设置为不被搜索,将栏目下所有子栏目也设置为不被搜索
+        if (CategoryIsSearchEnum.DISABLE.toString().equalsIgnoreCase(category.getCategoryIsSearch())){
+            List<String> ids = categoryDao.queryChildren(category).stream().map(CategoryEntity::getId).collect(Collectors.toList());
+            LambdaUpdateWrapper<CategoryEntity> wrapper = new UpdateWrapper<CategoryEntity>().lambda();
+            wrapper.set(CategoryEntity::getCategoryIsSearch,CategoryIsSearchEnum.DISABLE.toString());
+            wrapper.in(CategoryEntity::getId,ids);
+            categoryDao.update(null,wrapper);
+
+        }
+
         CategoryEntity parent = categoryDao.selectById(category.getCategoryId());
         if (parent == null) {
             return resultData;
@@ -97,7 +115,7 @@ public class CategoryAop extends net.mingsoft.basic.aop.BaseAop {
 
         // 用于判断父级栏目之前是否是子栏目
         // 只有父节点之前为子节点 && 父栏目类型为列表 && 子栏目为列表
-        boolean flag = parent.getLeaf() && StringUtils.equals(parent.getCategoryType(), CategoryTypeEnum.LIST.toString());
+        boolean flag = !parent.getLeaf() && StringUtils.equals(parent.getCategoryType(), CategoryTypeEnum.LIST.toString());
         if (flag) {
             // 将父栏目的内容模板清空
             parent.setCategoryUrl("");
@@ -144,6 +162,11 @@ public class CategoryAop extends net.mingsoft.basic.aop.BaseAop {
      *                     删除栏目静态文件
      */
     public void deleteCategoryHtml(String categoryPath) {
+        // 过滤非法路径
+        if (StringUtils.isEmpty(categoryPath) || categoryPath.contains("../") || categoryPath.contains("..\\")) {
+            LOG.error("非法路径:{}", categoryPath);
+            throw new BusinessException("非法路径");
+        }
         // html真实路径
         String htmlPath = BasicUtil.getRealPath(htmlDir);
         // appDir

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

@@ -58,4 +58,11 @@ public interface ICategoryBiz extends IBaseBiz<CategoryEntity> {
     void delete(String categoryId);
 
     void copyCategory(CategoryEntity entity);
+
+    /**
+     * 强转栏目类型
+     * @param categoryEntity 栏目实体
+     * @param targetCategoryType 目标栏目类型
+     */
+    void changeCategoryType(CategoryEntity categoryEntity,String targetCategoryType);
 }

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

@@ -24,17 +24,21 @@
 
 package net.mingsoft.cms.biz.impl;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import net.mingsoft.base.biz.impl.BaseBizImpl;
 import net.mingsoft.base.dao.IBaseDao;
 import net.mingsoft.basic.util.PinYinUtil;
 import net.mingsoft.cms.biz.ICategoryBiz;
+import net.mingsoft.cms.constant.e.CategoryTypeEnum;
 import net.mingsoft.cms.dao.ICategoryDao;
 import net.mingsoft.cms.dao.IContentDao;
 import net.mingsoft.cms.entity.CategoryEntity;
+import net.mingsoft.cms.entity.ContentEntity;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -42,6 +46,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * 分类管理持久化层
@@ -111,7 +116,8 @@ public class CategoryBizImpl extends BaseBizImpl<ICategoryDao, CategoryEntity> i
         }
         //保存链接地址
         String path = ObjectUtil.isNotNull(parentCategory) ? parentCategory.getCategoryPath() : "";
-        categoryEntity.setCategoryPath(path + "/" + categoryEntity.getCategoryPinyin());
+        String newPath = StringUtils.isBlank(path) ? categoryEntity.getCategoryPinyin() : path + "/" + categoryEntity.getCategoryPinyin();
+        categoryEntity.setCategoryPath(newPath);
         setTopId(categoryEntity);
         super.updateById(categoryEntity);
     }
@@ -132,6 +138,9 @@ public class CategoryBizImpl extends BaseBizImpl<ICategoryDao, CategoryEntity> i
         //保存时先保存再修改链接地址,修改时直接修改
         if (StringUtils.isNotBlank(categoryEntity.getId())) {
             categoryEntity.setCategoryPath(path + "/" + categoryEntity.getCategoryPinyin());
+            if (StringUtils.isBlank(path)){
+                categoryEntity.setCategoryPath(categoryEntity.getCategoryPinyin());
+            }
         }
 
     }
@@ -179,7 +188,8 @@ public class CategoryBizImpl extends BaseBizImpl<ICategoryDao, CategoryEntity> i
         if (StringUtils.isEmpty(entity.getCategoryParentIds())) {
             entity.setCategoryParentIds(null);
         }
-        categoryDao.updateEntity(entity);
+//        categoryDao.updateEntity(entity);
+        categoryDao.updateById(entity);
         //更新子节点所有父节点id和topid
         //如果本节点的topid为0(顶级栏目),则把自身的id作为子栏目的topid,非0所有的子栏目和本栏目使用同一个topid
         String topId = entity.getTopId();
@@ -315,4 +325,27 @@ public class CategoryBizImpl extends BaseBizImpl<ICategoryDao, CategoryEntity> i
         }
     }
 
+
+    @Override
+    public void changeCategoryType(CategoryEntity categoryEntity,String targetCategoryType) {
+
+        // 转换为单篇
+        if (CategoryTypeEnum.COVER.toString().equalsIgnoreCase(targetCategoryType)){
+            contentDao.deleteEntityByCategoryIds(new String[]{categoryEntity.getId()});
+            categoryEntity.setCategoryUrl(null);
+            categoryEntity.setCategoryListUrl(null);
+        // 转换为链接
+        } else if (CategoryTypeEnum.LINK.toString().equalsIgnoreCase(targetCategoryType)){
+            contentDao.deleteEntityByCategoryIds(new String[]{categoryEntity.getId()});
+            categoryEntity.setCategoryUrl(null);
+            categoryEntity.setCategoryListUrl(null);
+        } else if (CategoryTypeEnum.LIST.toString().equalsIgnoreCase(targetCategoryType)) {
+            categoryEntity.setCategoryUrl(null);
+        }
+
+        categoryEntity.setCategoryType(targetCategoryType);
+        categoryEntity.setCategoryDiyUrl(null);
+        categoryDao.updateById(categoryEntity);
+    }
+
 }

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

@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2012-present 铭软科技(mingsoft.net)
+ * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
+ * 遵循铭软科技《保密协议》
+ */
+
+package net.mingsoft.cms.constant.e;
+
+import net.mingsoft.base.constant.e.BaseEnum;
+
+/**
+ * @Author: 铭飞团队
+ * @Description: 栏目是否被搜索
+ * @Date: Create in 2023/06/20 11:18
+ */
+public enum CategoryIsSearchEnum implements BaseEnum{
+    /**
+     * 启用
+     */
+    ENABLE("enable"),
+
+    /**
+     * 禁用
+     */
+    DISABLE("disable");
+
+    CategoryIsSearchEnum(String status) {
+        this.status = status;
+    }
+
+    private String status;
+
+    @Override
+    public int toInt() {
+        return 0;
+    }
+
+    @Override
+    public String toString() {
+        return status;
+    }
+}

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

@@ -0,0 +1,36 @@
+package net.mingsoft.cms.constant.e;
+
+import net.mingsoft.base.constant.e.BaseEnum;
+
+/**
+ * 文章操作类型
+ * @author 铭软开发团队
+ * 创建日期:2023-02-17 10:19:59<br/>
+ * 历史修订:<br/>
+ */
+public enum ContentEnum implements BaseEnum {
+
+    /**
+     * 文章显示
+     */
+    DISPLAY("0"),
+
+    /**
+     * 文章不显示
+     */
+    HIDE("1");
+
+    private String isShow;
+    ContentEnum(String isShow){
+        this.isShow =isShow;
+    }
+
+    @Override
+    public int toInt() {
+        return 0;
+    }
+    @Override
+    public String toString(){
+        return this.isShow;
+    }
+}

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

@@ -15,6 +15,7 @@
 		<result column="category_keyword" property="categoryKeyword" /><!--栏目管理关键字 -->
 		<result column="category_descrip" property="categoryDescrip" /><!--栏目管理描述 -->
 		<result column="category_display" property="categoryDisplay" /><!--栏目是否显示 -->
+		<result column="category_is_search" property="categoryIsSearch" /><!--栏目是否显示 -->
 		<result column="category_img" property="categoryImg" /><!--栏目banner图 -->
 		<result column="category_ico" property="categoryIco" /><!--栏目小图 -->
 		<result column="category_diy_url" property="categoryDiyUrl" /><!--自定义链接 -->
@@ -55,6 +56,7 @@
 			<if test="categoryDescrip != null ">category_descrip=#{categoryDescrip},</if>
 			<if test="categoryImg != null and categoryImg != ''">category_img=#{categoryImg},</if>
 			<if test="categoryDisplay != null and categoryDisplay != ''">category_display=#{categoryDisplay},</if>
+			<if test="categoryIsSearch != null and categoryIsSearch != ''">category_is_search=#{categoryIsSearch},</if>
 			<if test="categoryIco != null and categoryIco != ''">category_ico=#{categoryIco},</if>
 			<if test="categoryDiyUrl != null">category_diy_url=#{categoryDiyUrl},</if>
 			<if test="dictId != null">dict_id=#{dictId},</if>

+ 28 - 1
src/main/java/net/mingsoft/cms/dao/IContentDao.xml

@@ -12,6 +12,7 @@
 				<result column="content_author" property="contentAuthor" /><!--文章作者 -->
 				<result column="content_source" property="contentSource" /><!--文章来源 -->
 				<result column="content_datetime" property="contentDatetime" /><!--发布时间 -->
+				<result column="content_tags" property="contentTags" /><!--文章标签 -->
 				<result column="content_sort" property="contentSort" /><!--自定义顺序 -->
 				<result column="content_img" property="contentImg" /><!--文章缩略图 -->
 				<result column="content_description" property="contentDescription" /><!--描述 -->
@@ -36,6 +37,7 @@
 		<result column="content_author" property="contentAuthor" /><!--文章作者 -->
 		<result column="content_source" property="contentSource" /><!--文章来源 -->
 		<result column="content_datetime" property="contentDatetime" /><!--发布时间 -->
+		<result column="content_tags" property="contentTags" /><!--文章标签 -->
 		<result column="content_sort" property="contentSort" /><!--自定义顺序 -->
 		<result column="content_img" property="contentImg" /><!--文章缩略图 -->
 		<result column="content_description" property="contentDescription" /><!--描述 -->
@@ -56,7 +58,7 @@
 		<id column="article_Id" property="articleId" /><!--编号 -->
 		<result column="content_update_date" property="contentUpdateDate" /><!--文章更新时间-->
 		<result column="category_title" property="categoryTitle" /><!--栏目管理名称 -->
-		<result column="content_short_title" property="contentShortTitle" /><!--文章副标题 -->
+		<result column="category_short_title" property="categoryShortTitle" /><!--栏目副标题 -->
 		<result column="category_id" property="categoryId" /><!--所属栏目 -->
 		<result column="category_type" property="categoryType" /><!--栏目管理属性 -->
 		<result column="category_sort" property="categorySort" /><!--自定义顺序 -->
@@ -92,6 +94,7 @@
 				<if test="contentSource != null and contentSource != ''">content_source,</if>
 				<if test="contentDatetime != null">content_datetime,</if>
 				<if test="contentSort != null">content_sort,</if>
+				<if test="contentTags != null and contentTags != ''">content_tags,</if>
 				<if test="contentImg != null and contentImg != ''">content_img,</if>
 				<if test="contentDescription != null and contentDescription != ''">content_description,</if>
 				<if test="contentKeyword != null and contentKeyword != ''">content_keyword,</if>
@@ -114,6 +117,7 @@
 				<if test="contentSource != null and contentSource != ''">#{contentSource},</if>
 				<if test="contentDatetime != null">#{contentDatetime},</if>
 				<if test="contentSort != null">#{contentSort},</if>
+				<if test="contentTags != null and contentTags != ''">#{contentTags},</if>
 				<if test="contentImg != null and contentImg != ''">#{contentImg},</if>
 				<if test="contentDescription != null and contentDescription != ''">#{contentDescription},</if>
 				<if test="contentKeyword != null and contentKeyword != ''">#{contentKeyword},</if>
@@ -141,6 +145,7 @@
 				<if test="contentSource != null ">content_source=#{contentSource},</if>
 				<if test="contentDatetime != null">content_datetime=#{contentDatetime},</if>
 				<if test="contentSort != null">content_sort=#{contentSort},</if>
+				<if test="contentTags != null and contentTags != ''">content_tags=#{contentTags},</if>
 				<if test="contentImg != null and contentImg != ''">content_img=#{contentImg},</if>
 				<if test="contentDescription != null ">content_description=#{contentDescription},</if>
 				<if test="contentKeyword != null ">content_keyword=#{contentKeyword},</if>
@@ -175,6 +180,7 @@
 				<if test="contentSource != null and contentSource != ''">and content_source=#{contentSource}</if>
 				<if test="contentDatetime != null"> and content_datetime=#{contentDatetime} </if>
 				<if test="contentSort != null"> and content_sort=#{contentSort} </if>
+				<if test="contentTags != null and contentTags != ''">and content_tags=#{contentTags}</if>
 				<if test="contentImg != null and contentImg != ''">and content_img=#{contentImg}</if>
 				<if test="contentDescription != null and contentDescription != ''">and content_description=#{contentDescription}</if>
 				<if test="contentKeyword != null and contentKeyword != ''">and content_keyword=#{contentKeyword}</if>
@@ -241,6 +247,7 @@
 			<if test="contentSource != null and contentSource != ''"> and content_source=#{contentSource}</if>
 			<if test="contentDatetime != null"> and content_datetime=#{contentDatetime} </if>
 			<if test="contentSort != null"> and content_sort=#{contentSort} </if>
+			<if test="contentTags != null and contentTags != ''">and content_tags=#{contentTags}</if>
 			<if test="contentImg != null and contentImg != ''"> and content_img=#{contentImg}</if>
 			<if test="contentDescription != null and contentDescription != ''"> and content_description=#{contentDescription}</if>
 			<if test="contentKeyword != null and contentKeyword != ''"> and content_keyword=#{contentKeyword}</if>
@@ -274,6 +281,20 @@
 					FIND_IN_SET(#{item},ct.content_type)>0
 				</foreach>
 			</if>
+			<if test="flag != null and flag != ''">
+				and
+				<foreach item="item" index="index" collection="flag.split(',')" open="(" separator="or"
+						 close=")">
+					FIND_IN_SET(#{item},ct.content_type)>0
+				</foreach>
+			</if>
+			<if test="noflag != null and noflag != ''">
+				and
+				<foreach item="item" index="index" collection="noflag.split(',')" open="(" separator="and"
+						 close=" or ct.content_type is null)">
+					FIND_IN_SET(#{item},ct.content_type)=0
+				</foreach>
+			</if>
 			<if test="contentDisplay != null and contentDisplay != ''"> and content_display=#{contentDisplay}</if>
 			<if test="contentAuthor != null and contentAuthor != ''"> and content_author=#{contentAuthor}</if>
 			<if test="contentSource != null and contentSource != ''"> and content_source=#{contentSource}</if>
@@ -412,6 +433,9 @@
 		</if>
 		<where>
 			a.del=0
+			and a.content_display=0
+			and c.category_display='enable'
+			and c.category_is_search='enable'
 			<if test="ids!=null and ids!=''">
 				and FIND_IN_SET(a.category_id,#{ids})>0
 			</if>
@@ -432,6 +456,9 @@
 			<if test="map.content_description!=null">
 			and a.content_description like CONCAT(CONCAT('%',#{map.content_description}),'%')
 			</if>
+			<if test="map.content_tag!=null">
+				and a.content_tags like CONCAT(CONCAT('%',#{map.content_tag}),'%')
+			</if>
 			<if test="map.content_keyword!=null">
 			and a.content_keyword like CONCAT(CONCAT('%',#{map.content_keyword}),'%')
 			</if>

+ 24 - 41
src/main/java/net/mingsoft/cms/entity/CategoryEntity.java

@@ -22,13 +22,13 @@
 
 package net.mingsoft.cms.entity;
 
+import cn.hutool.core.util.BooleanUtil;
+import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.annotation.*;
 import net.mingsoft.base.entity.BaseEntity;
 import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.cms.constant.e.CategoryTypeEnum;
 import net.mingsoft.config.MSProperties;
-import net.mingsoft.mdiy.util.ConfigUtil;
-
-import java.io.File;
 
 /**
  * 分类实体
@@ -42,8 +42,6 @@ public class CategoryEntity extends BaseEntity {
 
     private static final long serialVersionUID = 1574925152750L;
 
-    private static Boolean shortLinkSwitch = null;
-
     @TableId(type = IdType.ASSIGN_ID)
     private String id;
 
@@ -64,6 +62,7 @@ public class CategoryEntity extends BaseEntity {
     /**
      * 栏目副标题
      */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
     private String categoryShortTitle;
     /**
      * 栏目别名
@@ -112,6 +111,12 @@ public class CategoryEntity extends BaseEntity {
      * 是否显示
      */
     private String categoryDisplay;
+
+    /**
+     * 是否搜索
+     */
+    private String categoryIsSearch;
+
     /**
      * 自定义链接
      */
@@ -155,21 +160,6 @@ public class CategoryEntity extends BaseEntity {
      */
     private String topId;
 
-    /**
-     * 路径url
-     */
-    @TableField(exist = false)
-    private String url;
-
-    /**
-     * 设置url路径
-     *
-     * @param url 路径的字符串
-     */
-    public void setUrl(String url) {
-        this.url = url;
-    }
-
     public Boolean getLeaf() {
         return leaf;
     }
@@ -357,6 +347,13 @@ public class CategoryEntity extends BaseEntity {
     }
 
     /**
+     * 设置是否搜索
+     */
+    public String getCategoryIsSearch() { return categoryIsSearch; }
+
+    public void setCategoryIsSearch(String categoryIsSearch) { this.categoryIsSearch = categoryIsSearch; }
+
+    /**
      * 设置自定义链接
      */
     public void setCategoryDiyUrl(String categoryDiyUrl) {
@@ -445,7 +442,7 @@ public class CategoryEntity extends BaseEntity {
      * 获取栏目链接 (标签使用,动态链接不考虑)
      */
     public String getTypelink() {
-        return "3".equals(this.categoryType) ? this.categoryDiyUrl : this.categoryPath + "/index.html";
+        return CategoryTypeEnum.LINK.toString().equals(this.categoryType) ? this.categoryDiyUrl : this.categoryPath + "/index.html";
     }
 
     /**
@@ -497,10 +494,10 @@ public class CategoryEntity extends BaseEntity {
     }
 
     /**
-     * 获取栏目Id(标签使用)
+     * 获取栏目是否是叶子节点(标签使用) 1 是叶子(子栏目) 0 不是叶子(顶级栏目)
      */
-    public Boolean getTypeleaf() {
-        return this.leaf;
+    public Integer getTypeleaf() {
+        return ObjectUtil.isNotNull(this.leaf)? BooleanUtil.toInt(this.leaf):0;
     }
 
 
@@ -554,24 +551,10 @@ public class CategoryEntity extends BaseEntity {
     }
 
     /**
-     * 获取url路径
-     *
-     * @return url路径的字符串
+     * 获取栏目预览路径
+     * @return 栏目预览路径
      */
     public String getUrl() {
-        if (shortLinkSwitch == null) {
-            shortLinkSwitch = ConfigUtil.getBoolean("短链配置", "shortLinkSwitch", false);
-        }
-        String appDir = "";
-        String htmlDir = MSProperties.diy.htmlDir;
-        String categoryPath = this.getCategoryPath();
-        String categoryPinyin = this.getCategoryPinyin();
-        if (!shortLinkSwitch) {
-            //未开启短链
-            appDir = "/" + BasicUtil.getApp().getAppDir();
-            return url = "/" + htmlDir + appDir + categoryPath + "/index.html";
-        }
-        //开启短链后的url拼接
-        return url = "/" + htmlDir + appDir + "/" + categoryPinyin + ".html";
+        return "/" + MSProperties.diy.htmlDir + "/" + BasicUtil.getApp().getAppDir() + "/" +this.getCategoryPath() + "/index.html";
     }
 }

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

@@ -27,6 +27,8 @@ import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import net.mingsoft.base.entity.BaseEntity;
+import net.mingsoft.basic.util.BasicUtil;
+import net.mingsoft.config.MSProperties;
 import org.springframework.format.annotation.DateTimeFormat;
 
 import java.util.Date;
@@ -94,6 +96,10 @@ private static final long serialVersionUID = 1574925152617L;
 	*/
 	private Integer contentSort;
 	/**
+	 * 文章标签
+	 */
+	private String contentTags;
+	/**
 	* 文章缩略图
 	*/
 	private String contentImg;
@@ -118,6 +124,16 @@ private static final long serialVersionUID = 1574925152617L;
 	*/
 	private Integer contentHit;
 
+	/**
+	 * 文章是否被静态化
+	 */
+	private Integer hasDetailHtml;
+
+	/**
+	 * 栏目是否被静态化
+	 */
+	private Integer hasListHtml;
+
 	public Integer getContentHit() {
 		return contentHit;
 	}
@@ -299,4 +315,55 @@ private static final long serialVersionUID = 1574925152617L;
 	public String getContentOutLink() {
 		return this.contentOutLink;
 	}
+
+	/**
+	 * 设置文章标签
+	 */
+	public String getContentTags() {
+		return contentTags;
+	}
+
+	/**
+	 * 获取文章标签
+	 */
+	public void setContentTags(String contentTags) {
+		this.contentTags = contentTags;
+	}
+
+	/**
+	 * 获取文章静态化标识
+	 * @return
+	 */
+	public Integer getHasDetailHtml() {
+		return hasDetailHtml;
+	}
+
+	/**
+	 * 设置文章静态化标识
+	 * @param hasDetailHtml
+	 */
+	public void setHasDetailHtml(Integer hasDetailHtml) {
+		this.hasDetailHtml = hasDetailHtml;
+	}
+
+	/**
+	 * 获取栏目静态化标识
+	 * @return
+	 */
+	public Integer getHasListHtml() {
+		return hasListHtml;
+	}
+
+	/**
+	 * 设置栏目静态化标识
+	 * @param hasListHtml
+	 */
+	public void setHasListHtml(Integer hasListHtml) {
+		this.hasListHtml = hasListHtml;
+	}
+
+	public String getUrl(){
+		// categoryPath 做占位符
+		return "/" + MSProperties.diy.htmlDir + "/" + BasicUtil.getApp().getAppDir() + "/categoryPath/" + id+".html";
+	}
 }

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

@@ -173,7 +173,7 @@ public class WebConfig implements WebMvcConfigurer {
      */
     @Override
     public void addViewControllers(ViewControllerRegistry registry) {
-        registry.addViewController("/").setViewName("forward:/index");
+        registry.addViewController("/").setViewName("forward:/msIndex");
         registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
         WebMvcConfigurer.super.addViewControllers(registry);
     }

+ 8 - 6
src/main/webapp/WEB-INF/manager/cms/category/index.ftl

@@ -46,7 +46,9 @@
                           @click="copyContent(true)">{{scope.row.id}}</span>
                 </template>
             </el-table-column>
-            <el-table-column label="标题" align="left" prop="categoryTitle">
+            <el-table-column label="标题" align="left" prop="categoryTitle" :show-overflow-tooltip="true">
+            </el-table-column>
+            <el-table-column label="副标题" align="left" prop="categoryShortTitle" width="120" :show-overflow-tooltip="true">
             </el-table-column>
             <el-table-column label="类型" align="center" prop="categoryType" :formatter="categoryTypeFormat" width="70">
             </el-table-column>
@@ -55,8 +57,8 @@
             <el-table-column label="链接地址" align="left" prop="categoryPath" min-width="200" show-overflow-tooltip>
                 <template slot-scope="scope">
                     <span v-if="scope.row.categoryType == '1' || scope.row.categoryType == '2'" style="cursor: pointer"
-						  class="copyBtn" :data-clipboard-text="'{ms:global.url/}'+scope.row.url"
-						  @click="copyContent">{{"{ms:global.url/}"+scope.row.url}}</span>
+                          class="copyBtn" :data-clipboard-text="scope.row.url"
+                          @click="copyContent">{{scope.row.url}}</span>
                     <span v-if="scope.row.categoryType == '3'" style="cursor: pointer" class="copyBtn"
                           :data-clipboard-text="scope.row.categoryDiyUrl" @click="copyContent">{{scope.row.categoryDiyUrl}}</span>
                 </template>
@@ -133,6 +135,8 @@
             form: {
                 // 栏目管理名称
                 categoryTitle: '',
+                // 栏目管理名称
+                categoryShortTitle: '',
                 // 所属栏目
                 categoryId: '',
                 // 栏目管理属性
@@ -221,9 +225,7 @@
                 var that = this;
                 this.loadState = false;
                 this.loading = true;
-                ms.http.get(ms.manager + "/cms/category/list.do", {
-                    pageSize: 999
-                }).then(function (res) {
+                ms.http.get(ms.manager + "/cms/category/list.do").then(function (res) {
                     if (that.loadState) {
                         that.loading = false;
                     } else {

+ 165 - 24
src/main/webapp/WEB-INF/manager/cms/content/form.ftl

@@ -20,7 +20,9 @@
                     <el-button type="primary" icon="iconfont icon-baocun" size="mini" @click="save()" :loading="saveDisabled">保存
                     </el-button>
                 </@shiro.hasPermission>
-                <el-button size="mini" icon="iconfont icon-fanhui" plain onclick="javascript:history.go(-1)">返回
+                <el-button v-if="categoryType==1" size="mini" icon="iconfont icon-fanhui" plain onclick="javascript:history.go(-1)">返回
+                </el-button>
+                <el-button v-if="categoryType==2" size="mini" type="danger" icon="el-icon-delete" @click="del()">删除
                 </el-button>
             </el-col>
         </el-row>
@@ -33,7 +35,7 @@
                     <el-form v-if="item.title=='文章编辑'" ref="form" :model="form" :rules="rules" label-width="120px"
                              size="mini">
                         <el-row :gutter="0" justify="start" align="top">
-                            <el-col :span="returnIsShow?'12':'24'">
+                            <el-col :span="12">
                                 <el-form-item label="文章标题" prop="contentTitle">
                                     <el-input v-model="form.contentTitle"
                                               :disabled="false"
@@ -64,11 +66,24 @@
                                     </div>
                                 </el-form-item>
                             </el-col>
+                            <el-col :span="12" v-else>
+                                <el-form-item label="文章副标题" prop="contentShortTitle">
+                                    <el-input v-model="form.contentShortTitle"
+                                              :disabled="false"
+                                              :style="{width:  '100%'}"
+                                              :clearable="true"
+                                              placeholder="请输入文章副标题">
+                                    </el-input>
+                                    <div class="ms-form-tip">
+                                        标签:<a href="http://doc.mingsoft.net/mcms/biao-qian/wen-zhang-lie-biao-ms-arclist.html" target="_blank">${'$'}{field.shorttitle}</a>
+                                    </div>
+                                </el-form-item>
+                            </el-col>
                         </el-row>
                         <el-row
                                 gutter="0"
-                                justify="start" align="top">
-                            <el-col :span="returnIsShow?'12':'24'">
+                                justify="start" align="top" v-if="returnIsShow">
+                            <el-col :span="12">
                                 <el-form-item label="文章副标题" prop="contentShortTitle">
                                     <el-input v-model="form.contentShortTitle"
                                               :disabled="false"
@@ -143,6 +158,43 @@
                                 gutter="0"
                                 justify="start" align="top">
                             <el-col span="12">
+                                <el-form-item label="文章标签" prop="contentTags">
+                                    <el-select v-model="form.contentTags"
+                                               :style="{width: '100%'}"
+                                               :filterable="false"
+                                               :disabled="false"
+                                               filterable
+                                               :multiple="true" :clearable="true"
+                                               placeholder="请选择文章标签">
+                                        <el-option v-for='item in contentTagsOptions' :key="item.dictValue"
+                                                   :value="item.dictValue"
+                                                   :label="item.dictLabel"></el-option>
+                                    </el-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.tags}</a>
+                                        通过自定义字典可扩展数据
+                                    </div>
+                                </el-form-item>
+                            </el-col>
+                            <el-col span="12" v-if="!returnIsShow">
+                                <el-form-item label="文章外链接" prop="contentOutLink">
+                                    <el-input v-model="form.contentOutLink"
+                                              :disabled="false"
+                                              :style="{width:  '100%'}"
+                                              :clearable="true"
+                                              placeholder="请输入文章外链接">
+                                    </el-input>
+                                    <div class="ms-form-tip">
+                                        标签:<a href="http://doc.mingsoft.net/mcms/biao-qian/wen-zhang-lie-biao-ms-arclist.html"
+                                              target="_blank">${'$'}{field.outlink}</a> 文章外链接必须以http或者https等开头
+                                    </div>
+                                </el-form-item>
+                            </el-col>
+                        </el-row>
+                        <el-row
+                                gutter="0"
+                                justify="start" align="top">
+                            <el-col span="12">
                                 <el-form-item label="文章作者" prop="contentAuthor">
                                     <el-input v-model="form.contentAuthor"
                                               :disabled="false"
@@ -213,6 +265,7 @@
                                     :disabled="false"
                                     :data="{uploadPath:'/cms/content','isRename':true ,'appId':true}"
                                     :on-success="contentImgSuccess"
+                                    :on-error="contentImgError"
                                     accept="image/*"
                                     list-type="picture-card">
                                 <i class="el-icon-plus"></i>
@@ -266,6 +319,12 @@
     var formVue = new Vue({
         el: '#form',
         data: function () {
+            var checkTags = function (rule, value, callback){
+                if (value.length > 5){
+                    return callback(new Error('文章标签最多选择5个'));
+                }
+                callback();
+            }
             return {
                 saveDisabled: false,
                 activeName: 'form',
@@ -297,6 +356,8 @@
                     contentSource: '',
                     // 自定义顺序
                     contentSort: 0,
+                    // 文章标签
+                    contentTags: [],
                     // 文章缩略图
                     contentImg: [],
                     // 描述
@@ -311,6 +372,7 @@
                 },
                 categoryType: '1',
                 contentTypeOptions: [],
+                contentTagsOptions: [],
                 categoryIdOptions: [],
                 contentDisplayOptions: [{
                     "value": "0",
@@ -333,6 +395,9 @@
                     categoryId: [{
                         "required": true,
                         "message": "所属栏目不能为空"
+                    }],
+                    contentTags: [{
+                        validator: checkTags, trigger: 'blur'
                     }]
                 }
             };
@@ -352,8 +417,12 @@
                 var that = this; //自定义模型需要验证
 
                 var model = null;
-                if (that.currCategory.mdiyModelId && String(that.currCategory.mdiyModelId )!="0"){
-                    model = ms.mdiy.model.modelForm();
+                if (that.currCategory && that.currCategory.mdiyModelId && String(that.currCategory.mdiyModelId )!="0"){
+                    try {
+                        model = ms.mdiy.model.modelForm();
+                    } catch (e) {
+                        console.log(e)
+                    }
                 }
                 if (model && !model.validate()) {
                     this.activeName = 'custom-name';
@@ -374,9 +443,21 @@
                         that.saveDisabled = true; //判断
 
                         var data = JSON.parse(JSON.stringify(that.form));
-
+                        // 固定属性顺序为字典顺序
                         if (data.contentType) {
-                            data.contentType = data.contentType.join(',');
+                            var orderTypes = [];
+                            that.contentTypeOptions.forEach(function (dict) {
+                                var orderType = data.contentType.find(function (type) {
+                                    return type==dict.dictValue
+                                })
+                                if (orderType){
+                                    orderTypes.push(orderType)
+                                }
+                            })
+                            data.contentType = orderTypes.join(',');
+                        }
+                        if (data.contentTags) {
+                            data.contentTags = data.contentTags.join(',');
                         }
                         if (data.contentImg == []) {
                             data.contentImg = ""
@@ -422,16 +503,39 @@
                     }
                 });
             },
-            removeModel: function () {
+            //删除
+            del: function () {
                 var that = this;
-                var model = document.getElementById('model1');
-                var custom = document.getElementById('c_model');
-
-                if (custom) {
-                    model.removeChild(custom);
-                }
-
-                that.model = undefined;
+                that.$confirm('此操作将永久删除所选内容, 是否继续?', '提示', {
+                    confirmButtonText: '确定',
+                    cancelButtonText: '取消',
+                    type: 'warning'
+                }).then(function () {
+                    var formData = that.form;
+                    formData.contentType = ""
+                    formData.contentImg = ""
+                    ms.http.post(ms.manager + "/cms/content/delete.do",  [formData], {
+                        headers: {
+                            'Content-Type': 'application/json'
+                        }
+                    }).then(function (res) {
+                        if (res.result) {
+                            that.$notify({
+                                title:'成功',
+                                type: 'success',
+                                message: '删除成功!'
+                            });
+                            //	刷新列表
+                            window.parent.location.reload();
+                        } else {
+                            that.$notify({
+                                title: '失败',
+                                message: res.msg,
+                                type: 'warning'
+                            });
+                        }
+                    });
+                })
             },
             categoryChange: function () {
                 this.changeModel();
@@ -449,14 +553,17 @@
             rederModel: function (modelId) {
                 var that = this;
                 that.editableTabs.push({
-                    title: '',
+                    title: '加载中...',
                     name: 'custom-name'
                 });
-                ms.mdiy.model.extend("model1", {id:modelId},{ linkId: that.form.id },true).then(function(obj) {
-                    that.model = obj;
-                    that.editableTabs[1].title = obj.modelName
+                this.$nextTick(function () {
+                    ms.mdiy.model.extend("model1", {id:modelId},{ linkId: that.form.id },true).then(function(obj) {
+                        that.model = obj;
+                        that.editableTabs[1].title = obj.modelName
+                    });
                 });
 
+
             },
             getValue: function (data) {
                 this.form.categoryId = data.id;
@@ -474,6 +581,12 @@
                             res.data.contentType = [];
                         }
 
+                        if (res.data.contentTags && res.data.contentTags != '') {
+                            res.data.contentTags = res.data.contentTags.split(',');
+                        } else {
+                            res.data.contentTags = [];
+                        }
+
                         if (res.data.contentImg && res.data.contentImg != '') {
                             res.data.contentImg = JSON.parse(res.data.contentImg);
                             res.data.contentImg.forEach(function (value) {
@@ -521,6 +634,12 @@
                                 res.data.contentImg = [];
                             }
 
+                            if (res.data.contentTags && res.data.contentTags != '') {
+                                res.data.contentTags = res.data.contentTags.split(',');
+                            } else {
+                                res.data.contentTags = [];
+                            }
+
                             that.form = res.data;
                             var category = that.categoryIdOptions.filter(function (f) {
                                 return f['id'] == that.form.categoryId;
@@ -546,9 +665,7 @@
             //获取contentCategoryId数据源
             contentCategoryIdOptionsGet: function () {
                 var that = this;
-                ms.http.get(ms.manager + "/cms/category/list.do", {
-                    pageSize: 9999
-                }).then(function (res) {
+                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') {
@@ -576,6 +693,19 @@
                     }
                 });
             },
+            //获取contentType数据源
+            contentTagsOptionsGet: 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.contentTagsOptions = data.rows;
+                    }
+                });
+            },
             //contentImg文件上传完成回调
             contentImgSuccess: function (response, file, fileList) {
                 if(response.result){
@@ -594,6 +724,16 @@
                 }
 
             },
+            //contentImg文件上传失败回调
+            contentImgError: function (response, file, fileList) {
+                response = response.toString().replace("Error: ","")
+                response = JSON.parse(response);
+                this.$notify({
+                    title: '失败',
+                    message: response.msg,
+                    type: 'warning'
+                });
+            },
             contentImghandleRemove: function (file, files) {
                 var index = -1;
                 index = this.form.contentImg.findIndex(function (text) {
@@ -679,6 +819,7 @@
         created: function () {
             this.contentCategoryIdOptionsGet();
             this.contentTypeOptionsGet();
+            this.contentTagsOptionsGet();
         }
     });
 </script>

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

@@ -37,16 +37,18 @@
 <script>
 	var indexVue = new Vue({
 		el: "#index",
-		data: {
-			action: "",
-			//跳转页面
-			defaultProps: {
-				children: 'children',
-				label: 'categoryTitle'
-			},
-			treeData: [],
-			loading: true,
-			emptyText: ''
+		data: function () {
+			return {
+				action: "",
+				//跳转页面
+				defaultProps: {
+					children: 'children',
+					label: 'categoryTitle'
+				},
+				treeData: [],
+				loading: true,
+				emptyText: ''
+			}
 		},
 		methods: {
 			handleNodeClick: function (data) {
@@ -63,9 +65,7 @@
 				var that = this;
 				this.loadState = false;
 				this.loading = true;
-				ms.http.get(ms.manager + "/cms/category/list.do", {
-					pageSize: 999
-				}).then(function (res) {
+				ms.http.get(ms.manager + "/cms/category/list.do").then(function (res) {
 					if (that.loadState) {
 						that.loading = false;
 					} else {

+ 178 - 151
src/main/webapp/WEB-INF/manager/cms/content/main.ftl

@@ -72,6 +72,10 @@
             </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">
@@ -119,153 +123,162 @@
 <script>
     var indexVue = new Vue({
         el: '#main',
-        data: {
-            conditionList: [{
-                action: 'and',
-                field: 'content_title',
-                el: 'eq',
-                model: 'contentTitle',
-                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: ''
-            },
-            leaf:true
+        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: ''
+                },
+                leaf: true
+            }
         },
         methods: {
             //查询列表
@@ -379,7 +392,7 @@
                     }
                 }
             },
-            //表格数据转换
+            // 表格数据转换 id->name
             contentCategoryIdFormat: function (row, column, cellValue, index) {
                 var value = "";
 
@@ -395,6 +408,22 @@
 
                 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');
@@ -442,9 +471,7 @@
             //获取contentCategoryId数据源
             contentCategoryIdOptionsGet: function () {
                 var that = this;
-                ms.http.get(ms.manager + "/cms/category/list.do", {
-                    pageSize: 9999
-                }).then(function (res) {
+                ms.http.get(ms.manager + "/cms/category/list.do").then(function (res) {
                     if (res.result) {
                         that.contentCategoryIdOptions = res.data.rows;
                     }else {

+ 23 - 21
src/main/webapp/WEB-INF/manager/cms/generate/index.ftl

@@ -130,25 +130,27 @@
     var app = new Vue({
         el: '#app',
         watch: {},
-        data: {
-            homeLoading: false,
-            articleLoading: false,
-            columnLoading: false,
-            template: '',
-            //主题模板
-            templateOptions: [],
-            position: 'index',
-            //位置
-            contentSection: '0',
-            //文章栏目
-            section: '0',
-            //栏目
-            time: ms.util.date.fmt(new Date(), "yyyy-MM-dd"),
-            treeList: [{
-                id: '0',
-                categoryTitle: '顶级栏目',
-                children: []
-            }]
+        data: function () {
+            return {
+                homeLoading: false,
+                articleLoading: false,
+                columnLoading: false,
+                template: '',
+                //主题模板
+                templateOptions: [],
+                position: 'index',
+                //位置
+                contentSection: '0',
+                //文章栏目
+                section: '0',
+                //栏目
+                time: ms.util.date.fmt(new Date(), "yyyy-MM-dd"),
+                treeList: [{
+                    id: '0',
+                    categoryTitle: '顶级栏目',
+                    children: []
+                }]
+            }
         },
         methods: {
             //更新主页
@@ -176,7 +178,7 @@
                     } else {
                         that.$notify({
                             title: '失败',
-                            message: "更新失败!",
+                            message: data.msg,
                             type: 'error'
                         });
                     }
@@ -200,7 +202,7 @@
             updateColumn: function () {
                 var that = this;
                 that.columnLoading = true;
-                ms.http.get(ms.manager + '/cms/generate/' + (that.section ? that.section : 0) + '/genernateColumn.do').then(function (data) {
+                ms.http.get(ms.manager + '/cms/generate/' + (that.section ? that.section : 0) + '/generateColumn.do').then(function (data) {
                     if (data.result) {
                         that.$notify({
                             title: '成功',