diff --git a/README.md b/README.md index 45aa346e..c1c16b6c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ChestnutCMS v1.3.21 +# ChestnutCMS v1.3.23 ### 系统简介 @@ -16,8 +16,9 @@ ChestnutCMS是前后端分离的企业级内容管理系统。项目基于[RuoYi 资讯站演示地址:(会员演示账号:xxx333@126.com / a123456) -图片站演示地址: +图片站演示地址:PC端: 移动端: +游戏站演示地址:PC端: 移动端: ### 开发环境 - JDK 17 diff --git a/chestnut-admin/pom.xml b/chestnut-admin/pom.xml index d6ce7800..973da21c 100644 --- a/chestnut-admin/pom.xml +++ b/chestnut-admin/pom.xml @@ -3,7 +3,7 @@ chestnut com.chestnut - 1.3.21 + 1.3.23 4.0.0 jar diff --git a/chestnut-admin/src/main/resources/application-dev.yml b/chestnut-admin/src/main/resources/application-dev.yml index 04b51c44..594be496 100644 --- a/chestnut-admin/src/main/resources/application-dev.yml +++ b/chestnut-admin/src/main/resources/application-dev.yml @@ -3,7 +3,7 @@ chestnut: # 名称 name: ChestnutCMS # 版本 - version: 1.3.21 + version: 1.3.23 # 版权年份 copyrightYear: 2023 system: diff --git a/chestnut-admin/src/main/resources/application-prod.yml b/chestnut-admin/src/main/resources/application-prod.yml index dafef36a..fc41cee2 100644 --- a/chestnut-admin/src/main/resources/application-prod.yml +++ b/chestnut-admin/src/main/resources/application-prod.yml @@ -3,7 +3,7 @@ chestnut: # 名称 name: ChestnutCMS # 版本 - version: 1.3.21 + version: 1.3.23 # 版权年份 copyrightYear: 2023 system: diff --git a/chestnut-admin/src/main/resources/application-test.yml b/chestnut-admin/src/main/resources/application-test.yml index 7af5db57..5b9a5bde 100644 --- a/chestnut-admin/src/main/resources/application-test.yml +++ b/chestnut-admin/src/main/resources/application-test.yml @@ -3,7 +3,7 @@ chestnut: # 名称 name: ChestnutCMS # 版本 - version: 1.3.21 + version: 1.3.23 # 版权年份 copyrightYear: 2023 system: diff --git a/chestnut-admin/src/main/resources/db/migration/mysql/V1.3.23__update.sql b/chestnut-admin/src/main/resources/db/migration/mysql/V1.3.23__update.sql new file mode 100644 index 00000000..8704f362 --- /dev/null +++ b/chestnut-admin/src/main/resources/db/migration/mysql/V1.3.23__update.sql @@ -0,0 +1,11 @@ +CREATE TABLE `cms_content_rela` ( + `rela_id` bigint NOT NULL COMMENT 'ID', + `content_id` bigint NOT NULL COMMENT '内容ID', + `rela_content_id` bigint NOT NULL COMMENT '关联内容ID', + `create_by` varchar(64) NOT NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_by` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`rela_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; \ No newline at end of file diff --git a/chestnut-cms/chestnut-cms-advertisement/pom.xml b/chestnut-cms/chestnut-cms-advertisement/pom.xml index 4804dbeb..9807f7b9 100644 --- a/chestnut-cms/chestnut-cms-advertisement/pom.xml +++ b/chestnut-cms/chestnut-cms-advertisement/pom.xml @@ -7,7 +7,7 @@ com.chestnut chestnut-cms - 1.3.21 + 1.3.23 chestnut-cms-advertisement diff --git a/chestnut-cms/chestnut-cms-article/pom.xml b/chestnut-cms/chestnut-cms-article/pom.xml index 7643eb79..6be61260 100644 --- a/chestnut-cms/chestnut-cms-article/pom.xml +++ b/chestnut-cms/chestnut-cms-article/pom.xml @@ -7,7 +7,7 @@ com.chestnut chestnut-cms - 1.3.21 + 1.3.23 chestnut-cms-article diff --git a/chestnut-cms/chestnut-cms-block/pom.xml b/chestnut-cms/chestnut-cms-block/pom.xml index aa90fc3d..8596fd92 100644 --- a/chestnut-cms/chestnut-cms-block/pom.xml +++ b/chestnut-cms/chestnut-cms-block/pom.xml @@ -7,7 +7,7 @@ com.chestnut chestnut-cms - 1.3.21 + 1.3.23 chestnut-cms-block diff --git a/chestnut-cms/chestnut-cms-comment/pom.xml b/chestnut-cms/chestnut-cms-comment/pom.xml index 9dfd1b6c..bfc774a7 100644 --- a/chestnut-cms/chestnut-cms-comment/pom.xml +++ b/chestnut-cms/chestnut-cms-comment/pom.xml @@ -6,7 +6,7 @@ com.chestnut chestnut-cms - 1.3.21 + 1.3.23 chestnut-cms-comment diff --git a/chestnut-cms/chestnut-cms-contentcore/pom.xml b/chestnut-cms/chestnut-cms-contentcore/pom.xml index c6751e33..7ab65d7a 100644 --- a/chestnut-cms/chestnut-cms-contentcore/pom.xml +++ b/chestnut-cms/chestnut-cms-contentcore/pom.xml @@ -7,7 +7,7 @@ com.chestnut chestnut-cms - 1.3.21 + 1.3.23 chestnut-cms-contentcore diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/controller/ContentRelaController.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/controller/ContentRelaController.java new file mode 100644 index 00000000..32af45e2 --- /dev/null +++ b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/controller/ContentRelaController.java @@ -0,0 +1,73 @@ +package com.chestnut.contentcore.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.chestnut.common.domain.R; +import com.chestnut.common.security.anno.Priv; +import com.chestnut.common.security.web.BaseRestController; +import com.chestnut.common.utils.IdUtils; +import com.chestnut.contentcore.domain.CmsContent; +import com.chestnut.contentcore.domain.CmsContentRela; +import com.chestnut.contentcore.mapper.CmsContentRelaMapper; +import com.chestnut.contentcore.service.IContentRelaService; +import com.chestnut.system.security.AdminUserType; +import com.chestnut.system.security.StpAdminUtil; +import jakarta.validation.constraints.NotEmpty; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.PageRequest; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 关联内容管理 + * + * @author 兮玥 + * @email 190785909@qq.com + */ +@Priv(type = AdminUserType.TYPE) +@RestController +@RequiredArgsConstructor +@RequestMapping("/cms/content/rela") +public class ContentRelaController extends BaseRestController { + + private final IContentRelaService contentRelaService; + + private final CmsContentRelaMapper contentRelaMapper; + + @GetMapping + public R getRelaContents(@RequestParam Long contentId, @RequestParam(required = false) String title) { + PageRequest pr = this.getPageRequest(); + Page page = contentRelaMapper.selectRelaContents(new Page<>(pr.getPageNumber(), pr.getPageSize(), true), + contentId, title); + return this.bindDataTable(page); + } + + @PostMapping + public R addRelaContents(@RequestParam Long contentId, @RequestBody List relaContentIds) { + List contentIds = contentRelaMapper.selectList(new LambdaQueryWrapper() + .eq(CmsContentRela::getContentId, contentId)) + .stream().map(CmsContentRela::getRelaContentId).toList(); + String operator = StpAdminUtil.getLoginUser().getUsername(); + List relaContents = relaContentIds.stream() + .filter(id -> !contentIds.contains(id)) + .map(relaContentId -> { + CmsContentRela rela = new CmsContentRela(); + rela.setRelaId(IdUtils.getSnowflakeId()); + rela.setContentId(contentId); + rela.setRelaContentId(relaContentId); + rela.createBy(operator); + return rela; + }).toList(); + this.contentRelaService.saveBatch(relaContents); + return R.ok(); + } + + @DeleteMapping + public R deleteRelaContents(@RequestParam Long contentId, @RequestBody @NotEmpty List relaContentIds) { + this.contentRelaService.remove(new LambdaQueryWrapper() + .eq(CmsContentRela::getContentId, contentId) + .in(CmsContentRela::getRelaContentId, relaContentIds)); + return R.ok(); + } +} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/domain/CmsContentRela.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/domain/CmsContentRela.java new file mode 100644 index 00000000..c42edd15 --- /dev/null +++ b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/domain/CmsContentRela.java @@ -0,0 +1,39 @@ +package com.chestnut.contentcore.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.chestnut.common.db.domain.BaseEntity; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * 关联内容表对象 [cms_content_rela] + * + * @author 兮玥 + * @email 190785909@qq.com + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@TableName(CmsContentRela.TABLE_NAME) +public class CmsContentRela extends BaseEntity { + + public static final String TABLE_NAME = "cms_content_rela"; + + @TableId(value = "rela_id", type = IdType.INPUT) + private Long relaId; + + /** + * 内容ID + */ + private Long contentId; + + /** + * 关联内容ID + */ + private Long relaContentId; +} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/domain/vo/ListContentVO.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/domain/vo/ListContentVO.java index 9c11a63e..ab81ccda 100644 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/domain/vo/ListContentVO.java +++ b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/domain/vo/ListContentVO.java @@ -3,6 +3,8 @@ package com.chestnut.contentcore.domain.vo; import java.time.LocalDateTime; import java.util.Date; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import lombok.Getter; import lombok.Setter; @@ -75,6 +77,21 @@ public class ListContentVO { */ private String[] attributes; + /* + * 关键词 + */ + private String[] keywords; + + /* + * TAGs + */ + private String[] tags; + + /* + * 摘要 + */ + private String summary; + /* * 置顶标识 */ diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/mapper/CmsContentRelaMapper.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/mapper/CmsContentRelaMapper.java new file mode 100644 index 00000000..4ed8ee37 --- /dev/null +++ b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/mapper/CmsContentRelaMapper.java @@ -0,0 +1,23 @@ +package com.chestnut.contentcore.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.chestnut.contentcore.domain.CmsContent; +import com.chestnut.contentcore.domain.CmsContentRela; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +public interface CmsContentRelaMapper extends BaseMapper { + + @Select(""" + + """) + Page selectRelaContents(IPage page, @Param("contentId") Long contentId, @Param("title") String title); +} + diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/properties/PublishedContentEditProperty.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/properties/PublishedContentEditProperty.java index 070ad68d..f82a7a4e 100644 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/properties/PublishedContentEditProperty.java +++ b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/properties/PublishedContentEditProperty.java @@ -2,6 +2,7 @@ package com.chestnut.contentcore.properties; import java.util.Map; +import com.chestnut.common.utils.StringUtils; import org.springframework.stereotype.Component; import com.chestnut.contentcore.core.IProperty; @@ -36,6 +37,10 @@ public class PublishedContentEditProperty implements IProperty { } public static boolean getValue(Map props) { - return YesOrNo.isYes(ConfigPropertyUtils.getStringValue(ID, props)); + String value = ConfigPropertyUtils.getStringValue(ID, props); + if (StringUtils.isEmpty(value)) { + return true; + } + return YesOrNo.isYes(value); } } diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/service/IContentRelaService.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/service/IContentRelaService.java new file mode 100644 index 00000000..5321f08b --- /dev/null +++ b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/service/IContentRelaService.java @@ -0,0 +1,8 @@ +package com.chestnut.contentcore.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.chestnut.contentcore.domain.CmsContentRela; + +public interface IContentRelaService extends IService { + +} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/service/impl/ContentRelaServiceImpl.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/service/impl/ContentRelaServiceImpl.java new file mode 100644 index 00000000..404cbf2c --- /dev/null +++ b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/service/impl/ContentRelaServiceImpl.java @@ -0,0 +1,14 @@ +package com.chestnut.contentcore.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.chestnut.contentcore.domain.CmsContentRela; +import com.chestnut.contentcore.mapper.CmsContentRelaMapper; +import com.chestnut.contentcore.service.IContentRelaService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ContentRelaServiceImpl extends ServiceImpl + implements IContentRelaService { +} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/template/func/ListHtmlInternalUrlFunction.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/template/func/ListHtmlInternalUrlFunction.java new file mode 100644 index 00000000..da3cf571 --- /dev/null +++ b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/template/func/ListHtmlInternalUrlFunction.java @@ -0,0 +1,60 @@ +package com.chestnut.contentcore.template.func; + +import com.chestnut.common.staticize.FreeMarkerUtils; +import com.chestnut.common.staticize.core.TemplateContext; +import com.chestnut.common.staticize.func.AbstractFunc; +import com.chestnut.common.utils.StringUtils; +import com.chestnut.contentcore.util.InternalUrlUtils; +import freemarker.core.Environment; +import freemarker.template.TemplateModelException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; + +/** + * Freemarker模板自定义函数:处理Html文本内容中的内部链接 + */ +@Component +@RequiredArgsConstructor +public class ListHtmlInternalUrlFunction extends AbstractFunc { + + static final String FUNC_NAME = "listHtmlInternalUrl"; + + private static final String DESC = "{FREEMARKER.FUNC.DESC." + FUNC_NAME + "}"; + + @Override + public String getFuncName() { + return FUNC_NAME; + } + + @Override + public String getDesc() { + return DESC; + } + + @Override + public Object exec0(Object... args) throws TemplateModelException { + if (args.length < 1) { + return StringUtils.EMPTY; + } + TemplateContext context = FreeMarkerUtils.getTemplateContext(Environment.getCurrentEnvironment()); + + String html = args[0].toString(); + Matcher matcher = InternalUrlUtils.InternalUrlTagPattern.matcher(html); + List list = new ArrayList<>(); + while (matcher.find()) { + String iurl = matcher.group(1); + String actualUrl = InternalUrlUtils.getActualUrl(iurl, context.getPublishPipeCode(), context.isPreview()); + list.add(actualUrl); + } + return list; + } + + @Override + public List getFuncArgs() { + return List.of(new FuncArg("HTML文本内容", FuncArgType.String, true, null)); + } +} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/template/tag/CmsContentRelaTag.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/template/tag/CmsContentRelaTag.java new file mode 100644 index 00000000..85a13cbd --- /dev/null +++ b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/template/tag/CmsContentRelaTag.java @@ -0,0 +1,63 @@ +package com.chestnut.contentcore.template.tag; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.chestnut.common.staticize.enums.TagAttrDataType; +import com.chestnut.common.staticize.tag.AbstractListTag; +import com.chestnut.common.staticize.tag.TagAttr; +import com.chestnut.contentcore.domain.CmsContent; +import com.chestnut.contentcore.mapper.CmsContentRelaMapper; +import freemarker.core.Environment; +import freemarker.template.TemplateException; +import lombok.RequiredArgsConstructor; +import org.apache.commons.collections4.MapUtils; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +@Component +@RequiredArgsConstructor +public class CmsContentRelaTag extends AbstractListTag { + + public final static String TAG_NAME = "cms_content_rela"; + public final static String NAME = "{FREEMARKER.TAG.NAME." + TAG_NAME + "}"; + public final static String DESC = "{FREEMARKER.TAG.DESC." + TAG_NAME + "}"; + + public final static String TagAttr_ContentId = "contentid"; + + private final CmsContentRelaMapper contentRelaMapper; + + @Override + public List getTagAttrs() { + List tagAttrs = super.getTagAttrs(); + tagAttrs.add(new TagAttr(TagAttr_ContentId, true, TagAttrDataType.INTEGER, "内容ID")); + return tagAttrs; + } + + @Override + public TagPageData prepareData(Environment env, Map attrs, boolean page, int size, int pageIndex) + throws TemplateException { + long contentId = MapUtils.getLongValue(attrs, TagAttr_ContentId); + if (contentId <= 0) { + throw new TemplateException("内容ID错误:" + contentId, env); + } + Page pageResult = contentRelaMapper + .selectRelaContents(new Page<>(pageIndex, size, page), contentId, null); + return TagPageData.of(pageResult.getRecords(), pageResult.getTotal()); + } + + @Override + public String getTagName() { + return TAG_NAME; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getDescription() { + return DESC; + } +} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/util/InternalUrlUtils.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/util/InternalUrlUtils.java index 03d4d972..12c182d3 100644 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/util/InternalUrlUtils.java +++ b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/util/InternalUrlUtils.java @@ -20,7 +20,7 @@ public class InternalUrlUtils { /** * 带iurl属性值的任意标签匹配 */ - private static final Pattern InternalUrlTagPattern = Pattern.compile("<[^>]+=\\s*['\"](iurl://[^'\"]+)['\"][^>]*>", + public static final Pattern InternalUrlTagPattern = Pattern.compile("<[^>]+=\\s*['\"](iurl://[^'\"]+)['\"][^>]*>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE); diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/resources/i18n/messages.properties b/chestnut-cms/chestnut-cms-contentcore/src/main/resources/i18n/messages.properties index 079dcbb9..cff52dd5 100644 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/resources/i18n/messages.properties +++ b/chestnut-cms/chestnut-cms-contentcore/src/main/resources/i18n/messages.properties @@ -88,6 +88,8 @@ FREEMARKER.TAG.NAME.cms_pagewidget_data=页面部件数据标签 FREEMARKER.TAG.DESC.cms_pagewidget_data=页面部件数据标签,标签体内可使用${Data.name}获取数据 FREEMARKER.TAG.NAME.cms_content_closest=内容前后篇标签 FREEMARKER.TAG.DESC.cms_content_closest=内容前后篇标签,仅支持指定内容当前栏目列表,标签体内可使用${Data.title}获取数据 +FREEMARKER.TAG.NAME.cms_content_rela=相关内容标签 +FREEMARKER.TAG.DESC.cms_content_rela=相关内容标签,内嵌<#list DataList as content>${content.name}遍历数据 # freemarker模板函数 FREEMARKER.FUNC.DESC.clearHtmlTag=清除Html标签,例如:${clearHtmlTag(ArticleContent)} @@ -103,6 +105,7 @@ FREEMARKER.FUNC.DESC.ifElse=三元表达式函数,例如:${ifElse(content.lo FREEMARKER.FUNC.DESC.dynamicPageLink=动态页面链接获取函数,例如:${dynamicPageLink('Search')} FREEMARKER.FUNC.DESC.dict=获取字典数据列表,例如:${dict('YesOrNo', 'Y')} FREEMARKER.FUNC.DESC.sysConfig=获取系统参数配置值,例如:${sysConfig('SiteApiUrl')} +FREEMARKER.FUNC.DESC.listHtmlInternalUrl=获取html文本中的iurl列表,例如:${listHtmlInternalUrl(ArticleContent)} # 校验规则 VALIDATOR.CMS.SITE.PUBLISH_PIPE_PROPS_EMPTY=发布通道配置不能为空 diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/resources/i18n/messages_en.properties b/chestnut-cms/chestnut-cms-contentcore/src/main/resources/i18n/messages_en.properties index 068a88f1..17692ad4 100644 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/resources/i18n/messages_en.properties +++ b/chestnut-cms/chestnut-cms-contentcore/src/main/resources/i18n/messages_en.properties @@ -88,6 +88,8 @@ FREEMARKER.TAG.NAME.cms_pagewidget_data=Pagewidget data tag FREEMARKER.TAG.DESC.cms_pagewidget_data=Fetch pagewidget data and use "${Data.name}" to show in template. FREEMARKER.TAG.NAME.cms_content_closest=Content closest tag FREEMARKER.TAG.DESC.cms_content_closest=Only support the content's catalog to fetch data, use <#list> in tag like "<#list DataList as content>${content.title}" to walk through the list of contents. +FREEMARKER.TAG.NAME.cms_content_rela=Related content tag +FREEMARKER.TAG.DESC.cms_content_rela=Fetch related contents by contentId, use <#list> in tag like "<#list DataList as content>${content.title}" to walk through the list of contents. # freemarker模板函数 FREEMARKER.FUNC.DESC.clearHtmlTag=Use ${clearHtmlTag(ArticleContent)} in template to clear html tag. @@ -103,6 +105,7 @@ FREEMARKER.FUNC.DESC.ifElse=Use ${ifElse(Site.siteId!='','1','2')} in template t FREEMARKER.FUNC.DESC.dynamicPageLink=Use ${dynamicPageLink('Search')} in template to get the dynamic page link. FREEMARKER.FUNC.DESC.dict=Use ${dict(content.linkFlag, 'YesOrNo')} in template to get the dict data label. FREEMARKER.FUNC.DESC.sysConfig=Use ${sysConfig('SiteApiUrl')} in template to get the system config value. +FREEMARKER.FUNC.DESC.listHtmlInternalUrl=Use ${listHtmlInternalUrl(ArticleContent)} in template to get the iurl list. # 校验规则 VALIDATOR.CMS.SITE.PUBLISH_PIPE_PROPS_EMPTY=The site publish pipe props cannot be empty. diff --git a/chestnut-cms/chestnut-cms-customform/pom.xml b/chestnut-cms/chestnut-cms-customform/pom.xml index 3bec22b1..da2aa42b 100644 --- a/chestnut-cms/chestnut-cms-customform/pom.xml +++ b/chestnut-cms/chestnut-cms-customform/pom.xml @@ -7,7 +7,7 @@ com.chestnut chestnut-cms - 1.3.21 + 1.3.23 chestnut-cms-customform diff --git a/chestnut-cms/chestnut-cms-exmodel/pom.xml b/chestnut-cms/chestnut-cms-exmodel/pom.xml index e2d95b40..839e095e 100644 --- a/chestnut-cms/chestnut-cms-exmodel/pom.xml +++ b/chestnut-cms/chestnut-cms-exmodel/pom.xml @@ -7,7 +7,7 @@ com.chestnut chestnut-cms - 1.3.21 + 1.3.23 chestnut-cms-exmodel diff --git a/chestnut-cms/chestnut-cms-image/pom.xml b/chestnut-cms/chestnut-cms-image/pom.xml index bddb6d4c..eb24ab9d 100644 --- a/chestnut-cms/chestnut-cms-image/pom.xml +++ b/chestnut-cms/chestnut-cms-image/pom.xml @@ -7,7 +7,7 @@ com.chestnut chestnut-cms - 1.3.21 + 1.3.23 chestnut-cms-image diff --git a/chestnut-cms/chestnut-cms-image/src/main/java/com/chestnut/cms/image/template/tag/CmsImageTag.java b/chestnut-cms/chestnut-cms-image/src/main/java/com/chestnut/cms/image/template/tag/CmsImageTag.java index 9bffdc16..74b3565a 100644 --- a/chestnut-cms/chestnut-cms-image/src/main/java/com/chestnut/cms/image/template/tag/CmsImageTag.java +++ b/chestnut-cms/chestnut-cms-image/src/main/java/com/chestnut/cms/image/template/tag/CmsImageTag.java @@ -59,6 +59,7 @@ public class CmsImageTag extends AbstractListTag { LambdaQueryWrapper q = new LambdaQueryWrapper().eq(CmsImage::getContentId, contentId); q.apply(StringUtils.isNotEmpty(condition), condition); + q.orderByAsc(CmsImage::getSortFlag); Page pageResult = this.imageService.page(new Page<>(pageIndex, size, page), q); if (pageIndex > 1 & pageResult.getRecords().size() == 0) { throw new TemplateException("内容列表页码超出上限:" + pageIndex, env); diff --git a/chestnut-cms/chestnut-cms-link/pom.xml b/chestnut-cms/chestnut-cms-link/pom.xml index a1fe96a3..162396fd 100644 --- a/chestnut-cms/chestnut-cms-link/pom.xml +++ b/chestnut-cms/chestnut-cms-link/pom.xml @@ -7,7 +7,7 @@ com.chestnut chestnut-cms - 1.3.21 + 1.3.23 chestnut-cms-link diff --git a/chestnut-cms/chestnut-cms-media/pom.xml b/chestnut-cms/chestnut-cms-media/pom.xml index 2b06d284..a3bf6b01 100644 --- a/chestnut-cms/chestnut-cms-media/pom.xml +++ b/chestnut-cms/chestnut-cms-media/pom.xml @@ -7,7 +7,7 @@ com.chestnut chestnut-cms - 1.3.21 + 1.3.23 chestnut-cms-media diff --git a/chestnut-cms/chestnut-cms-media/src/main/java/com/chestnut/media/template/tag/CmsAudioTag.java b/chestnut-cms/chestnut-cms-media/src/main/java/com/chestnut/media/template/tag/CmsAudioTag.java index 58033a92..f465b96f 100644 --- a/chestnut-cms/chestnut-cms-media/src/main/java/com/chestnut/media/template/tag/CmsAudioTag.java +++ b/chestnut-cms/chestnut-cms-media/src/main/java/com/chestnut/media/template/tag/CmsAudioTag.java @@ -1,29 +1,27 @@ package com.chestnut.media.template.tag; -import java.util.List; -import java.util.Map; - import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.chestnut.common.utils.StringUtils; -import org.apache.commons.collections4.MapUtils; -import org.springframework.stereotype.Component; - import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.chestnut.common.staticize.FreeMarkerUtils; import com.chestnut.common.staticize.core.TemplateContext; import com.chestnut.common.staticize.enums.TagAttrDataType; import com.chestnut.common.staticize.tag.AbstractListTag; import com.chestnut.common.staticize.tag.TagAttr; +import com.chestnut.common.utils.StringUtils; import com.chestnut.contentcore.domain.CmsContent; import com.chestnut.contentcore.enums.ContentCopyType; import com.chestnut.contentcore.service.IContentService; import com.chestnut.contentcore.util.InternalUrlUtils; import com.chestnut.media.domain.CmsAudio; import com.chestnut.media.service.IAudioService; - import freemarker.core.Environment; import freemarker.template.TemplateException; import lombok.RequiredArgsConstructor; +import org.apache.commons.collections4.MapUtils; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; @RequiredArgsConstructor @Component @@ -58,6 +56,7 @@ public class CmsAudioTag extends AbstractListTag { String condition = MapUtils.getString(attrs, TagAttr.AttrName_Condition); LambdaQueryWrapper q = new LambdaQueryWrapper().eq(CmsAudio::getContentId, contentId); q.apply(StringUtils.isNotEmpty(condition), condition); + q.orderByAsc(CmsAudio::getSortFlag); Page pageResult = this.audioService.page(new Page<>(pageIndex, size, page), q); if (pageIndex > 1 & pageResult.getRecords().size() == 0) { throw new TemplateException("内容列表页码超出上限:" + pageIndex, env); diff --git a/chestnut-cms/chestnut-cms-member/pom.xml b/chestnut-cms/chestnut-cms-member/pom.xml index 0e920fd6..f168f50f 100644 --- a/chestnut-cms/chestnut-cms-member/pom.xml +++ b/chestnut-cms/chestnut-cms-member/pom.xml @@ -6,7 +6,7 @@ com.chestnut chestnut-cms - 1.3.21 + 1.3.23 chestnut-cms-member diff --git a/chestnut-cms/chestnut-cms-search/pom.xml b/chestnut-cms/chestnut-cms-search/pom.xml index de79b294..2eb98624 100644 --- a/chestnut-cms/chestnut-cms-search/pom.xml +++ b/chestnut-cms/chestnut-cms-search/pom.xml @@ -7,7 +7,7 @@ com.chestnut chestnut-cms - 1.3.21 + 1.3.23 chestnut-cms-search diff --git a/chestnut-cms/chestnut-cms-stat/pom.xml b/chestnut-cms/chestnut-cms-stat/pom.xml index fad9116f..9eeecd49 100644 --- a/chestnut-cms/chestnut-cms-stat/pom.xml +++ b/chestnut-cms/chestnut-cms-stat/pom.xml @@ -7,7 +7,7 @@ com.chestnut chestnut-cms - 1.3.21 + 1.3.23 chestnut-cms-stat diff --git a/chestnut-cms/chestnut-cms-vote/pom.xml b/chestnut-cms/chestnut-cms-vote/pom.xml index 220eed0e..b09b4821 100644 --- a/chestnut-cms/chestnut-cms-vote/pom.xml +++ b/chestnut-cms/chestnut-cms-vote/pom.xml @@ -7,7 +7,7 @@ com.chestnut chestnut-cms - 1.3.21 + 1.3.23 chestnut-cms-vote diff --git a/chestnut-cms/chestnut-cms-word/pom.xml b/chestnut-cms/chestnut-cms-word/pom.xml index 0cd5cbe5..0d8acfe9 100644 --- a/chestnut-cms/chestnut-cms-word/pom.xml +++ b/chestnut-cms/chestnut-cms-word/pom.xml @@ -7,7 +7,7 @@ com.chestnut chestnut-cms - 1.3.21 + 1.3.23 chestnut-cms-word diff --git a/chestnut-cms/chestnut-cms-word/src/main/java/com/chestnut/cms/word/template/tag/CmsTagWordTag.java b/chestnut-cms/chestnut-cms-word/src/main/java/com/chestnut/cms/word/template/tag/CmsTagWordTag.java new file mode 100644 index 00000000..31160fb5 --- /dev/null +++ b/chestnut-cms/chestnut-cms-word/src/main/java/com/chestnut/cms/word/template/tag/CmsTagWordTag.java @@ -0,0 +1,75 @@ +package com.chestnut.cms.word.template.tag; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.chestnut.common.staticize.enums.TagAttrDataType; +import com.chestnut.common.staticize.tag.AbstractListTag; +import com.chestnut.common.staticize.tag.TagAttr; +import com.chestnut.common.utils.StringUtils; +import com.chestnut.word.domain.TagWord; +import com.chestnut.word.domain.TagWordGroup; +import com.chestnut.word.service.ITagWordGroupService; +import com.chestnut.word.service.ITagWordService; +import freemarker.core.Environment; +import freemarker.template.TemplateException; +import lombok.RequiredArgsConstructor; +import org.apache.commons.collections4.MapUtils; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Component +@RequiredArgsConstructor +public class CmsTagWordTag extends AbstractListTag { + + public final static String TAG_NAME = "cms_tag_word"; + public final static String NAME = "{FREEMARKER.TAG.NAME." + TAG_NAME + "}"; + public final static String DESC = "{FREEMARKER.TAG.DESC." + TAG_NAME + "}"; + + private final ITagWordGroupService tagWordGroupService; + + private final ITagWordService tagWordService; + + @Override + public List getTagAttrs() { + List tagAttrs = super.getTagAttrs(); + tagAttrs.add(new TagAttr("group", false, TagAttrDataType.STRING, "TAG词分组编码") ); + return tagAttrs; + } + + @Override + public TagPageData prepareData(Environment env, Map attrs, boolean page, int size, int pageIndex) throws TemplateException { + String group = MapUtils.getString(attrs, "group"); + Optional opt = tagWordGroupService.lambdaQuery().eq(TagWordGroup::getCode, group).oneOpt(); + if (opt.isEmpty()) { + throw new TemplateException("Tag word group not found: " + group, env); + } + TagWordGroup tagWordGroup = opt.get(); + LambdaQueryWrapper q = new LambdaQueryWrapper() + .eq(TagWord::getGroupId, tagWordGroup.getGroupId()); + + String condition = MapUtils.getString(attrs, TagAttr.AttrName_Condition); + q.apply(StringUtils.isNotEmpty(condition), condition); + q.orderByAsc(TagWord::getSortFlag); + + Page pageResult = this.tagWordService.page(new Page<>(pageIndex, size, page), q); + return TagPageData.of(pageResult.getRecords(), pageResult.getTotal()); + } + + @Override + public String getTagName() { + return TAG_NAME; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getDescription() { + return DESC; + } +} diff --git a/chestnut-cms/chestnut-cms-word/src/main/resources/i18n/messages.properties b/chestnut-cms/chestnut-cms-word/src/main/resources/i18n/messages.properties index 225f3c60..944b3f7c 100644 --- a/chestnut-cms/chestnut-cms-word/src/main/resources/i18n/messages.properties +++ b/chestnut-cms/chestnut-cms-word/src/main/resources/i18n/messages.properties @@ -1,3 +1,7 @@ # freemarker模板函数 FREEMARKER.FUNC.DESC.replaceHotWord=替换热词链接,例如:${replaceHotWord(content, 'default', '[a href='\{0\}' target='\{2\}']\{1\}[/a]')} -FREEMARKER.FUNC.DESC.replaceSensitiveWord=替换敏感词,例如:${replaceSensitiveWord(content, 'xxx')} \ No newline at end of file +FREEMARKER.FUNC.DESC.replaceSensitiveWord=替换敏感词,例如:${replaceSensitiveWord(content, 'xxx')} + +# freemarker模板标签 +FREEMARKER.TAG.NAME.cms_tag_word=TAG词列表标签 +FREEMARKER.TAG.DESC.cms_tag_word=根据TAG词分组编码获取TAG词列表,内嵌<#list DataList as tag>${tag.word}遍历数据 \ No newline at end of file diff --git a/chestnut-cms/chestnut-cms-word/src/main/resources/i18n/messages_en.properties b/chestnut-cms/chestnut-cms-word/src/main/resources/i18n/messages_en.properties index de2f0e49..432c1648 100644 --- a/chestnut-cms/chestnut-cms-word/src/main/resources/i18n/messages_en.properties +++ b/chestnut-cms/chestnut-cms-word/src/main/resources/i18n/messages_en.properties @@ -1,3 +1,6 @@ # freemarker模板函数 FREEMARKER.FUNC.DESC.replaceHotWord=Replace hot word in content argument, eg: ${replaceHotWord(content, 'default', '[a href='\{0\}' target='\{2\}']\{1\}[/a]')} -FREEMARKER.FUNC.DESC.replaceSensitiveWord=Replace sensitive word in content argument, eg: ${replaceSensitiveWord(content, 'xxx')} \ No newline at end of file +FREEMARKER.FUNC.DESC.replaceSensitiveWord=Replace sensitive word in content argument, eg: ${replaceSensitiveWord(content, 'xxx')} + +FREEMARKER.TAG.NAME.cms_link=TAG Word List Tag +FREEMARKER.TAG.DESC.cms_link=Fetch tag-word list, use <#list> in tag like "<#list DataList as tag>${tag.word}" to walk through the list of tag-words. \ No newline at end of file diff --git a/chestnut-cms/chestnut-module-seo/pom.xml b/chestnut-cms/chestnut-module-seo/pom.xml index 51f452cc..5e0b08eb 100644 --- a/chestnut-cms/chestnut-module-seo/pom.xml +++ b/chestnut-cms/chestnut-module-seo/pom.xml @@ -7,7 +7,7 @@ com.chestnut chestnut-cms - 1.3.21 + 1.3.23 chestnut-cms-seo diff --git a/chestnut-cms/chestnut-module-seo/src/main/java/com/chestnut/seo/service/BaiduSitemapService.java b/chestnut-cms/chestnut-module-seo/src/main/java/com/chestnut/seo/service/BaiduSitemapService.java index 75d14f75..25daffc0 100644 --- a/chestnut-cms/chestnut-module-seo/src/main/java/com/chestnut/seo/service/BaiduSitemapService.java +++ b/chestnut-cms/chestnut-module-seo/src/main/java/com/chestnut/seo/service/BaiduSitemapService.java @@ -18,6 +18,7 @@ import com.chestnut.contentcore.service.IPublishPipeService; import com.chestnut.contentcore.service.ISiteService; import com.chestnut.contentcore.util.SiteUtils; import com.chestnut.seo.fixed.dict.SitemapPageType; +import com.chestnut.seo.publishpipe.PublishPipeProp_EnableSitemap; import com.chestnut.seo.publishpipe.PublishPipeProp_SitemapPageType; import com.chestnut.seo.publishpipe.PublishPipeProp_SitemapUrlLimit; import com.chestnut.system.fixed.dict.YesOrNo; @@ -88,7 +89,10 @@ public class BaiduSitemapService { } public void generateSitemapXml(CmsSite site) { - List publishPipes = this.publishPipeService.getPublishPipes(site.getSiteId()); + List publishPipes = this.publishPipeService.getPublishPipes(site.getSiteId()) + .stream().filter(pp -> + PublishPipeProp_EnableSitemap.getValue(pp.getCode(), site.getPublishPipeProps()) + ).toList(); generateSitemapXml(site, publishPipes); } diff --git a/chestnut-cms/pom.xml b/chestnut-cms/pom.xml index 41a2e5dd..4174bdb0 100644 --- a/chestnut-cms/pom.xml +++ b/chestnut-cms/pom.xml @@ -5,7 +5,7 @@ com.chestnut chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-common/chestnut-common-core/pom.xml b/chestnut-common/chestnut-common-core/pom.xml index 23fd223c..0ff55280 100644 --- a/chestnut-common/chestnut-common-core/pom.xml +++ b/chestnut-common/chestnut-common-core/pom.xml @@ -5,7 +5,7 @@ chestnut-common com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-common/chestnut-common-datasource/pom.xml b/chestnut-common/chestnut-common-datasource/pom.xml index b9f05bd0..89848faa 100644 --- a/chestnut-common/chestnut-common-datasource/pom.xml +++ b/chestnut-common/chestnut-common-datasource/pom.xml @@ -5,7 +5,7 @@ chestnut-common com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-common/chestnut-common-datasource/src/main/java/com/chestnut/common/db/util/SqlBuilder.java b/chestnut-common/chestnut-common-datasource/src/main/java/com/chestnut/common/db/util/SqlBuilder.java index a34706e8..48d2ba71 100644 --- a/chestnut-common/chestnut-common-datasource/src/main/java/com/chestnut/common/db/util/SqlBuilder.java +++ b/chestnut-common/chestnut-common-datasource/src/main/java/com/chestnut/common/db/util/SqlBuilder.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.chestnut.common.db.DBErrorCode; import com.chestnut.common.utils.Assert; import com.chestnut.common.utils.StringUtils; +import com.google.common.collect.ImmutableSortedMap; import java.util.*; import java.util.stream.Stream; @@ -313,18 +314,18 @@ public class SqlBuilder { } public SqlBuilder orderBy(String field, boolean isAsc) { - return this.orderBy(Map.of(field, isAsc)); + return this.orderBy(ImmutableSortedMap.of(field, isAsc)); } public SqlBuilder orderBy(String field1, boolean isAsc1, String field2, boolean isAsc2) { - return this.orderBy(Map.of(field1, isAsc1, field2, isAsc2)); + return this.orderBy(ImmutableSortedMap.of(field1, isAsc1, field2, isAsc2)); } public SqlBuilder orderBy(String field1, boolean isAsc1, String field2, boolean isAsc2, String field3, boolean isAsc3) { - return this.orderBy(Map.of(field1, isAsc1, field2, isAsc2, field3, isAsc3)); + return this.orderBy(ImmutableSortedMap.of(field1, isAsc1, field2, isAsc2, field3, isAsc3)); } /** diff --git a/chestnut-common/chestnut-common-extend/pom.xml b/chestnut-common/chestnut-common-extend/pom.xml index c3ce28b0..68ae8514 100644 --- a/chestnut-common/chestnut-common-extend/pom.xml +++ b/chestnut-common/chestnut-common-extend/pom.xml @@ -5,7 +5,7 @@ chestnut-common com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-common/chestnut-common-log/pom.xml b/chestnut-common/chestnut-common-log/pom.xml index 4c4e1e5a..6b58b3a3 100644 --- a/chestnut-common/chestnut-common-log/pom.xml +++ b/chestnut-common/chestnut-common-log/pom.xml @@ -5,7 +5,7 @@ chestnut-common com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-common/chestnut-common-redis/pom.xml b/chestnut-common/chestnut-common-redis/pom.xml index 4ccb53fb..99216c52 100644 --- a/chestnut-common/chestnut-common-redis/pom.xml +++ b/chestnut-common/chestnut-common-redis/pom.xml @@ -5,7 +5,7 @@ chestnut-common com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-common/chestnut-common-security/pom.xml b/chestnut-common/chestnut-common-security/pom.xml index 53295108..532f6072 100644 --- a/chestnut-common/chestnut-common-security/pom.xml +++ b/chestnut-common/chestnut-common-security/pom.xml @@ -5,7 +5,7 @@ chestnut-common com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-common/chestnut-common-staticize/pom.xml b/chestnut-common/chestnut-common-staticize/pom.xml index f4605fe4..2c7ef6d3 100644 --- a/chestnut-common/chestnut-common-staticize/pom.xml +++ b/chestnut-common/chestnut-common-staticize/pom.xml @@ -5,7 +5,7 @@ chestnut-common com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/FreeMarkerUtils.java b/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/FreeMarkerUtils.java index 44d91020..937efca3 100644 --- a/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/FreeMarkerUtils.java +++ b/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/FreeMarkerUtils.java @@ -1,26 +1,18 @@ package com.chestnut.common.staticize; +import com.chestnut.common.staticize.core.TemplateContext; +import com.chestnut.common.utils.DateUtils; +import com.chestnut.common.utils.NumberUtils; +import com.chestnut.common.utils.StringUtils; +import freemarker.core.Environment; +import freemarker.template.*; + import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; -import com.chestnut.common.staticize.core.TemplateContext; -import com.chestnut.common.utils.DateUtils; -import com.chestnut.common.utils.NumberUtils; -import com.chestnut.common.utils.StringUtils; - -import freemarker.core.Environment; -import freemarker.template.AdapterTemplateModel; -import freemarker.template.TemplateBooleanModel; -import freemarker.template.TemplateDateModel; -import freemarker.template.TemplateHashModel; -import freemarker.template.TemplateModel; -import freemarker.template.TemplateModelException; -import freemarker.template.TemplateNumberModel; -import freemarker.template.TemplateScalarModel; - public class FreeMarkerUtils { /** @@ -40,6 +32,8 @@ public class FreeMarkerUtils { env.getObjectWrapper().wrap(context.getFirstFileName())); env.setGlobalVariable(StaticizeConstants.TemplateVariable_OtherPage, env.getObjectWrapper().wrap(context.getOtherFileName())); + env.setGlobalVariable(StaticizeConstants.TemplateVariable_TimeMillis, + env.getObjectWrapper().wrap(context.getTimeMillis())); } public static TemplateContext getTemplateContext(Environment env) throws TemplateModelException { diff --git a/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/StaticizeConstants.java b/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/StaticizeConstants.java index 35330d84..5020a3c1 100644 --- a/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/StaticizeConstants.java +++ b/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/StaticizeConstants.java @@ -41,4 +41,9 @@ public class StaticizeConstants { * 模板变量:自定义上下文 */ public static final String TemplateVariable_TemplateContext = "TemplateContext"; + + /** + * 模板解析时间 + */ + public static final String TemplateVariable_TimeMillis = "TimeMillis"; } diff --git a/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/StaticizeService.java b/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/StaticizeService.java index b2890367..20074d2f 100644 --- a/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/StaticizeService.java +++ b/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/StaticizeService.java @@ -1,24 +1,22 @@ package com.chestnut.common.staticize; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Writer; -import java.util.List; - -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Service; - import com.chestnut.common.staticize.core.TemplateContext; import com.chestnut.common.staticize.func.IFunction; import com.chestnut.common.staticize.tag.ITag; import com.chestnut.common.utils.Assert; - import freemarker.core.Environment; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; import freemarker.template.TemplateModelException; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.List; @Slf4j @Service @@ -29,8 +27,8 @@ public class StaticizeService { public StaticizeService(@Qualifier("staticizeConfiguration") Configuration cfg, List tags, List functions) { this.cfg = cfg; - tags.forEach(this::registTag); - functions.forEach(this::registFunction); + tags.forEach(this::registerTag); + functions.forEach(this::registerFunction); } /** @@ -40,7 +38,7 @@ public class StaticizeService { * 此方法只返回TemplateContext中制定页码的静态化结果 *

* - * @param templateContext + * @param context * @param writer * @throws TemplateException * @throws IOException @@ -50,6 +48,7 @@ public class StaticizeService { Template template = cfg.getTemplate(context.getTemplateId()); // 处理模板 long s = System.currentTimeMillis(); + context.setTimeMillis(s); Environment env = template.createProcessingEnvironment(context.getVariables(), writer); FreeMarkerUtils.addGlobalVariables(env, context); env.process(); @@ -60,7 +59,7 @@ public class StaticizeService { /** * 生成静态化文件,自动处理分页 * - * @param templateContext + * @param context * @throws TemplateException * @throws IOException */ @@ -69,6 +68,7 @@ public class StaticizeService { Template template = cfg.getTemplate(context.getTemplateId()); // 处理模板 long s = System.currentTimeMillis(); + context.setTimeMillis(s); Environment env = null; String filePath = context.getStaticizeFilePath(context.getPageIndex()); try (FileWriter writer = new FileWriter(filePath)) { @@ -102,27 +102,27 @@ public class StaticizeService { cfg.clearTemplateCache(); } - public void registTag(ITag tag) { + public void registerTag(ITag tag) { // 注册模板标签 try { Assert.isNull(cfg.getSharedVariable(tag.getTagName()), () -> new IllegalArgumentException("Freemarker directive conflict: " + tag.getTagName())); cfg.setSharedVariable(tag.getTagName(), tag); } catch (TemplateModelException e) { - log.error("Freemarker directive '<@{}>' regist failed.", tag.getTagName()); + log.error("Freemarker directive '<@{}>' register failed.", tag.getTagName()); throw new IllegalArgumentException(e); } log.info("Freemarker directive: <@{}>", tag.getTagName()); } - public void registFunction(IFunction func) { + public void registerFunction(IFunction func) { // 注册模板函数 try { Assert.isNull(cfg.getSharedVariable(func.getFuncName()), () -> new IllegalArgumentException("Freemarker function conflict: " + func.getFuncName())); cfg.setSharedVariable(func.getFuncName(), func); } catch (TemplateModelException e) { - log.error("Freemarker function '{}' regist failed.", func.getFuncName()); + log.error("Freemarker function '{}' register failed.", func.getFuncName()); throw new IllegalArgumentException(e); } log.info("Freemarker function: {}", func.getFuncName()); diff --git a/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/core/TemplateContext.java b/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/core/TemplateContext.java index 086a9f15..bfad5d53 100644 --- a/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/core/TemplateContext.java +++ b/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/core/TemplateContext.java @@ -1,14 +1,13 @@ package com.chestnut.common.staticize.core; -import java.util.HashMap; -import java.util.Map; - import com.chestnut.common.utils.StringUtils; import com.chestnut.common.utils.file.FileExUtils; - import lombok.Getter; import lombok.Setter; +import java.util.HashMap; +import java.util.Map; + /** * 模板上下文 */ @@ -80,6 +79,11 @@ public class TemplateContext { * 注意:需要生成多页面的模板中只能有一个page=true的列表标签,存在多个会覆盖掉分页属性 */ private boolean paged; + + /** + * 模板处理时间 + */ + private Long timeMillis; public TemplateContext(String templateId, boolean preview, String publishPipeCode) { this.templateId = templateId; diff --git a/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/tag/impl/PageBarTag.java b/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/tag/impl/PageBarTag.java index a119ac6e..c839dbed 100644 --- a/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/tag/impl/PageBarTag.java +++ b/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/tag/impl/PageBarTag.java @@ -91,7 +91,8 @@ public class PageBarTag extends AbstractTag { private String generatePageBar(String target, String firstPage, String lastPage, boolean withFirstAndLast, Environment env) throws TemplateException { TemplateContext context = FreeMarkerUtils.getTemplateContext(env); - int pageCount = Long.valueOf((context.getPageTotal() + context.getPageSize() - 1 ) / context.getPageSize()).intValue(); + int pageSize = context.getPageSize() == 0 ? 20 : context.getPageSize(); + int pageCount = Long.valueOf((context.getPageTotal() + pageSize - 1 ) / pageSize).intValue(); int startPage = 1; int endPage = 7; if (context.getPageIndex() > 4) { @@ -106,7 +107,7 @@ public class PageBarTag extends AbstractTag { StringBuilder sb = new StringBuilder(); sb.append("
"); if (withFirstAndLast && startPage > 1) { - sb.append(StringUtils.messageFormat(temp, firstPageLink, "", target, firstPage)); + sb.append(StringUtils.messageFormat(temp, firstPageLink, " page_first", target, firstPage)); sb.append("..."); } for (int i = startPage; i <= endPage; i++) { @@ -120,7 +121,7 @@ public class PageBarTag extends AbstractTag { } if (withFirstAndLast && endPage < pageCount) { sb.append("..."); - sb.append(StringUtils.messageFormat(temp, StringUtils.messageFormat(otherPageLink, pageCount), "", target, lastPage)); + sb.append(StringUtils.messageFormat(temp, StringUtils.messageFormat(otherPageLink, pageCount), " page_last", target, lastPage)); } sb.append("
"); return sb.toString(); diff --git a/chestnut-common/chestnut-common-storage/pom.xml b/chestnut-common/chestnut-common-storage/pom.xml index 414a84b9..2bf3dc64 100644 --- a/chestnut-common/chestnut-common-storage/pom.xml +++ b/chestnut-common/chestnut-common-storage/pom.xml @@ -5,7 +5,7 @@ chestnut-common com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-common/pom.xml b/chestnut-common/pom.xml index cfcb8f8e..a75a9e1d 100644 --- a/chestnut-common/pom.xml +++ b/chestnut-common/pom.xml @@ -5,7 +5,7 @@ com.chestnut chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-modules/chestnut-comment/pom.xml b/chestnut-modules/chestnut-comment/pom.xml index 02812000..e45d374c 100644 --- a/chestnut-modules/chestnut-comment/pom.xml +++ b/chestnut-modules/chestnut-comment/pom.xml @@ -3,7 +3,7 @@ chestnut-modules com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-modules/chestnut-generator/pom.xml b/chestnut-modules/chestnut-generator/pom.xml index 8143f4d0..4a2b6988 100644 --- a/chestnut-modules/chestnut-generator/pom.xml +++ b/chestnut-modules/chestnut-generator/pom.xml @@ -5,7 +5,7 @@ chestnut-modules com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-modules/chestnut-member/pom.xml b/chestnut-modules/chestnut-member/pom.xml index 5ad5f392..d3822da3 100644 --- a/chestnut-modules/chestnut-member/pom.xml +++ b/chestnut-modules/chestnut-member/pom.xml @@ -3,7 +3,7 @@ chestnut-modules com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-modules/chestnut-meta/pom.xml b/chestnut-modules/chestnut-meta/pom.xml index 64cfea32..e0d18c34 100644 --- a/chestnut-modules/chestnut-meta/pom.xml +++ b/chestnut-modules/chestnut-meta/pom.xml @@ -6,7 +6,7 @@ chestnut-modules com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-modules/chestnut-monitor/pom.xml b/chestnut-modules/chestnut-monitor/pom.xml index 75c07202..75d63381 100644 --- a/chestnut-modules/chestnut-monitor/pom.xml +++ b/chestnut-modules/chestnut-monitor/pom.xml @@ -6,7 +6,7 @@ com.chestnut chestnut-modules - 1.3.21 + 1.3.23 chestnut-monitor diff --git a/chestnut-modules/chestnut-search/pom.xml b/chestnut-modules/chestnut-search/pom.xml index c005ff6c..fd534381 100644 --- a/chestnut-modules/chestnut-search/pom.xml +++ b/chestnut-modules/chestnut-search/pom.xml @@ -3,7 +3,7 @@ chestnut-modules com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-modules/chestnut-stat/pom.xml b/chestnut-modules/chestnut-stat/pom.xml index b85bd989..0f3dcb2e 100644 --- a/chestnut-modules/chestnut-stat/pom.xml +++ b/chestnut-modules/chestnut-stat/pom.xml @@ -6,7 +6,7 @@ chestnut-modules com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-modules/chestnut-system/pom.xml b/chestnut-modules/chestnut-system/pom.xml index da8e1e9d..c6fd2fc2 100644 --- a/chestnut-modules/chestnut-system/pom.xml +++ b/chestnut-modules/chestnut-system/pom.xml @@ -5,7 +5,7 @@ chestnut-modules com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-modules/chestnut-vote/pom.xml b/chestnut-modules/chestnut-vote/pom.xml index 2f61584a..90f0225d 100644 --- a/chestnut-modules/chestnut-vote/pom.xml +++ b/chestnut-modules/chestnut-vote/pom.xml @@ -3,7 +3,7 @@ chestnut-modules com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-modules/chestnut-word/pom.xml b/chestnut-modules/chestnut-word/pom.xml index 13dd695c..51b40986 100644 --- a/chestnut-modules/chestnut-word/pom.xml +++ b/chestnut-modules/chestnut-word/pom.xml @@ -6,7 +6,7 @@ chestnut-modules com.chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-modules/pom.xml b/chestnut-modules/pom.xml index 7640cd1b..c9176d3d 100644 --- a/chestnut-modules/pom.xml +++ b/chestnut-modules/pom.xml @@ -5,7 +5,7 @@ com.chestnut chestnut - 1.3.21 + 1.3.23 4.0.0 diff --git a/chestnut-ui/package.json b/chestnut-ui/package.json index aa0d94c6..86ab20cb 100644 --- a/chestnut-ui/package.json +++ b/chestnut-ui/package.json @@ -1,6 +1,6 @@ { "name": "ChestnutCMS", - "version": "1.3.21", + "version": "1.3.23", "description": "ChestnutCMS[栗子内容管理系统]", "author": "", "license": "Apache-2.0", diff --git a/chestnut-ui/src/api/contentcore/rela.js b/chestnut-ui/src/api/contentcore/rela.js new file mode 100644 index 00000000..0bb8c3a6 --- /dev/null +++ b/chestnut-ui/src/api/contentcore/rela.js @@ -0,0 +1,25 @@ +import request from '@/utils/request' + +export function getRelaContentList(query) { + return request({ + url: '/cms/content/rela', + method: 'get', + params: query + }) +} + +export function addRelaContents(data) { + return request({ + url: '/cms/content/rela?contentId=' + data.contentId, + method: 'post', + data: data.relaContentIds + }) +} + +export function delRelaContents(data) { + return request({ + url: '/cms/content/rela?contentId=' + data.contentId, + method: 'delete', + data: data.relaContentIds + }) +} \ No newline at end of file diff --git a/chestnut-ui/src/assets/styles/btn.scss b/chestnut-ui/src/assets/styles/btn.scss index e6ba1a8e..06327de8 100644 --- a/chestnut-ui/src/assets/styles/btn.scss +++ b/chestnut-ui/src/assets/styles/btn.scss @@ -97,3 +97,10 @@ font-size: 14px; border-radius: 4px; } + +.btn-cell-wrap + .btn-cell-wrap { + margin-left: 10px; +} +.btn-cell-wrap:empty { + margin-left: 0; +} diff --git a/chestnut-ui/src/directive/permission/hasPermi.js b/chestnut-ui/src/directive/permission/hasPermi.js index a0e07708..18ab06e1 100644 --- a/chestnut-ui/src/directive/permission/hasPermi.js +++ b/chestnut-ui/src/directive/permission/hasPermi.js @@ -1,6 +1,9 @@ /** * v-hasPermi 操作权限处理 * Copyright (c) 2023 兮玥(190785909@qq.com) + * + * 1、非el-button标签的按钮权限需要给对应控件添加class="btn-permi" + * 2、表格操作列的多个按钮需要给按钮添加一个包裹住用来占位,否则会影响按钮位置 */ import store from '@/store' @@ -18,27 +21,15 @@ function fn (el, binding) { }) if (!hasPermissions) { - if (el.cacheParentElement && el.cacheParentElement.className.split(' ').indexOf('el-dropdown') > -1) { - el.cacheParentElement.parentNode.removeChild(el.cacheParentElement) - el.cacheParentElement.parentNode.style.display = 'none'; - } else if (el.className.indexOf('el-button') > -1) { - el.parentNode && el.parentNode.removeChild(el) - if (el.cacheParentElement != null) { - el.cacheParentElement.style.display = 'none'; - } - } else if (el.className.indexOf('el-dropdown-menu__item') > -1) { + if (el.classList.contains('el-button') || el.classList.contains("btn-permi")) { + el.cacheParentElement && el.cacheParentElement.removeChild(el) + } else if (el.classList.contains('el-dropdown-menu__item')) { el.cacheElement.style.display = 'none'; } } else { - if (el.cacheParentElement && el.cacheParentElement.className.split(' ').indexOf('el-dropdown') > -1) { - el.cacheParentElement.parentNode.appendChild(el.cacheElement.parentNode) - el.cacheParentElement.parentNode.style.display = ''; - } else if (el.className.indexOf('el-button') > -1) { - if (el.cacheParentElement) { - el.cacheParentElement.appendChild(el.cacheElement) - el.cacheParentElement.style.display = ''; - } - } else if (el.className.indexOf('el-dropdown-menu__item') > -1) { + if (el.classList.contains('el-button') || el.classList.contains("btn-permi")) { + el.cacheParentElement && el.cacheParentElement.appendChild(el.cacheElement) + } else if (el.classList.contains('el-dropdown-menu__item')) { if (el.cacheElement) { el.cacheElement.style.display = ''; } diff --git a/chestnut-ui/src/i18n/lang/en.js b/chestnut-ui/src/i18n/lang/en.js index e2987dce..9c2b42f9 100644 --- a/chestnut-ui/src/i18n/lang/en.js +++ b/chestnut-ui/src/i18n/lang/en.js @@ -1128,7 +1128,8 @@ export default { ViewCount: "Views", FavoriteCount: "Favorities", LikeCount: "Likes", - CommentCount: "Comments" + CommentCount: "Comments", + RelaContent: "Related contents" }, Image: { Title: "Title", diff --git a/chestnut-ui/src/i18n/lang/zh-CN.js b/chestnut-ui/src/i18n/lang/zh-CN.js index bbf238b4..b5624da0 100644 --- a/chestnut-ui/src/i18n/lang/zh-CN.js +++ b/chestnut-ui/src/i18n/lang/zh-CN.js @@ -1128,7 +1128,8 @@ export default { ViewCount: "浏览量", FavoriteCount: "收藏数", LikeCount: "点赞数", - CommentCount: "评论数" + CommentCount: "评论数", + RelaContent: "相关内容" }, Image: { Title: "标题", diff --git a/chestnut-ui/src/views/cms/ad/advertisementEditor.vue b/chestnut-ui/src/views/cms/ad/advertisementEditor.vue index e8292d62..8ff2348f 100644 --- a/chestnut-ui/src/views/cms/ad/advertisementEditor.vue +++ b/chestnut-ui/src/views/cms/ad/advertisementEditor.vue @@ -2,19 +2,25 @@
- {{ $t('CMS.Adv.GoBack') }} - {{ $t("Common.Save") }} + + + {{ $t('CMS.Adv.GoBack') }} + + + {{ $t("Common.Save") }} + +
- {{ $t("Common.Save") }} - {{ $t('CMS.Catalog.ApplyToChildren') }} + + {{ $t("Common.Save") }} + + + {{ $t('CMS.Catalog.ApplyToChildren') }} + - \ No newline at end of file diff --git a/chestnut-ui/src/views/cms/contentcore/catalogInfo.vue b/chestnut-ui/src/views/cms/contentcore/catalogInfo.vue index c8cc52b7..ea683781 100644 --- a/chestnut-ui/src/views/cms/contentcore/catalogInfo.vue +++ b/chestnut-ui/src/views/cms/contentcore/catalogInfo.vue @@ -20,18 +20,17 @@ @click="handlePreview">{{ $t('CMS.ContentCore.Preview') }} - + {{ $t('CMS.ContentCore.Publish') }} - + @@ -85,16 +85,15 @@ - - {{ $t("Common.Delete") }} - + + {{ $t("Common.Delete") }} + {{ $t('CMS.ContentCore.Preview') }} {{ $t('CMS.Content.Unlock') }} {{ $t('CMS.Content.Lock') }} + {{ $t('CMS.Content.RelaContent') }} {{ $t('Common.Close') }} {{ $t('CMS.Content.BackToList') }}
@@ -229,6 +230,7 @@ :open="openContentSelector" @ok="handleContentSelectorOk" @close="handleContentSelectorClose"> +
@@ -246,6 +248,7 @@ import CMSLogoView from '@/views/cms/components/LogoView'; import CMSResourceDialog from "@/views/cms/contentcore/resourceDialog"; import CMSCatalogSelector from "@/views/cms/contentcore/catalogSelector"; import CMSContentSelector from "@/views/cms/contentcore/contentSelector"; +import CMSContrentRelaDialog from '@/views/cms/contentcore/contentRelaDialog'; import CMSTemplateSelector from '@/views/cms/contentcore/templateSelector'; import CMSEXModelEditor from '@/views/cms/components/EXModelEditor'; import CMSTagEditor from '@/views/cms/components/TagEditor'; @@ -269,6 +272,7 @@ export default { "cms-logo-view": CMSLogoView, 'cms-catalog-selector': CMSCatalogSelector, 'cms-content-selector': CMSContentSelector, + 'cms-content-rela-dialog': CMSContrentRelaDialog, "cms-exmodel-editor": CMSEXModelEditor, "cms-tag-editor": CMSTagEditor, // "ckeditor": CKEditor5 @@ -324,6 +328,7 @@ export default { selectExTemplate: false, publishAfterSave: false, toPublishAfterSave: false, + openRelaContentDialog: false, }; }, created() { @@ -594,6 +599,28 @@ export default { handleContentSelectorOk(contents) { if (contents && contents.length > 0) { this.form.redirectUrl = contents[0].internalUrl; + if (!this.form.logo || this.form.logo.length == 0) { + this.form.logo = contents[0].logo; + this.form.logoSrc = contents[0].logoSrc; + } + if (!this.form.title || this.form.title.length == 0) { + this.form.title = contents[0].title; + } + if (!this.form.author || this.form.author.length == 0) { + this.form.author = contents[0].author; + } + if (!this.form.editor || this.form.editor.length == 0) { + this.form.editor = contents[0].editor; + } + if (!this.form.tags || this.form.tags.length == 0) { + this.form.tags = contents[0].tags; + } + if (!this.form.keywords || this.form.keywords.length == 0) { + this.form.keywords = contents[0].keywords; + } + if (!this.form.summary || this.form.summary.length == 0) { + this.form.summary = contents[0].summary; + } this.openContentSelector = false; } else { this.$modal.msgWarning(this.$t('Common.SelectFirst')); @@ -601,6 +628,12 @@ export default { }, handleContentSelectorClose() { this.openContentSelector = false; + }, + handleRelaContent() { + this.openRelaContentDialog = true; + }, + handleRelaContentClose() { + this.openRelaContentDialog = false; } } }; diff --git a/chestnut-ui/src/views/cms/contentcore/contentList.vue b/chestnut-ui/src/views/cms/contentcore/contentList.vue index d93018cb..6c93bf03 100644 --- a/chestnut-ui/src/views/cms/contentcore/contentList.vue +++ b/chestnut-ui/src/views/cms/contentcore/contentList.vue @@ -2,7 +2,7 @@
- + {{ $t("Common.Delete") }} @@ -45,6 +46,7 @@ icon="el-icon-timer" size="mini" :disabled="multiple" + v-hasPermi="[ $p('Catalog:EditContent:{0}', [ catalogId ]) ]" @click="handleToPublish">{{ $t("CMS.ContentCore.ToPublish") }} @@ -55,6 +57,7 @@ icon="el-icon-s-promotion" size="mini" :disabled="multiple" + v-hasPermi="[ $p('Catalog:EditContent:{0}', [ catalogId ]) ]" @click="handlePublish">{{ $t("CMS.ContentCore.Publish") }} @@ -65,6 +68,7 @@ icon="el-icon-download" size="mini" :disabled="multiple" + v-hasPermi="[ $p('Catalog:EditContent:{0}', [ catalogId ]) ]" @click="handleOffline">{{ $t("CMS.Content.Offline") }} @@ -89,7 +93,7 @@ - + - +