mirror of
https://gitee.com/liweiyi/ChestnutCMS.git
synced 2025-12-06 08:28:23 +08:00
版本更新:V1.5.8
This commit is contained in:
parent
c847340220
commit
a3261f18cb
12
Jenkinsfile
vendored
12
Jenkinsfile
vendored
@ -121,20 +121,17 @@ pipeline {
|
||||
dir('./ChestnutCMS') {
|
||||
withCredentials([usernamePassword(credentialsId: 'ALIYUN-DOCKER-REGISTRY-LWY', passwordVariable: 'DOCKERPWD', usernameVariable: 'DOCKERUSER')]) {
|
||||
sh '''
|
||||
cp -f bin/docker-deploy.sh ${APP_PATH}
|
||||
|
||||
cp -f bin/docker-deploy.sh ${APP_PATH}/docker-deploy.sh
|
||||
cp -f docker/docker-compose_${DEPLOY_ENV}.yml ${APP_PATH}/docker-compose.yml
|
||||
|
||||
cd ${APP_PATH}
|
||||
|
||||
cp -f ../bin/docker-deploy.sh docker-deploy.sh
|
||||
|
||||
sed -i "s/{{DOCKERUSER}}/${DOCKERUSER}/g" docker-deploy.sh
|
||||
sed -i "s/{{DOCKERPWD}}/${DOCKERPWD}/g" docker-deploy.sh
|
||||
sed -i "s/{{DOCKER_HUB_URL}}/${DOCKER_HUB_URL}/g" docker-deploy.sh
|
||||
sed -i "s/{{IMAGE_REPOSITORY}}/${DOCKER_HUB_WORKSPACE}\\/${APP_NAME}/g" docker-deploy.sh
|
||||
sed -i "s/{{IMAGE_TAG}}/${IMAGE_TAG}/g" docker-deploy.sh
|
||||
|
||||
cp -f docker/docker-compose_${DEPLOY_ENV}.yml docker-compose.yml
|
||||
|
||||
|
||||
sed -i "s/{{DOCKER_IMAGE}}/${DOCKER_HUB_URL}\\/${DOCKER_HUB_WORKSPACE}\\/${APP_NAME}:${IMAGE_TAG}/g" docker-compose.yml
|
||||
'''
|
||||
sshPublisher(publishers: [sshPublisherDesc(configName: 'GameCluster', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''
|
||||
@ -203,7 +200,6 @@ pipeline {
|
||||
usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: true)])
|
||||
sh 'rm -f ui.zip'
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>chestnut</artifactId>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@ -5,7 +5,7 @@ chestnut:
|
||||
# 代号
|
||||
alias: ChestnutCMS
|
||||
# 版本
|
||||
version: 1.5.7
|
||||
version: 1.5.8
|
||||
# 版权年份
|
||||
copyrightYear: 2022-2025
|
||||
system:
|
||||
@ -15,6 +15,8 @@ chestnut:
|
||||
uploadPath: 'E:/dev/workspace_chestnut/uploadPath'
|
||||
member:
|
||||
uploadPath: 'E:/dev/workspace_chestnut/_xy_member/'
|
||||
image:
|
||||
type: 'JDK'
|
||||
cms:
|
||||
publish:
|
||||
strategy: ThreadPool
|
||||
@ -24,7 +26,7 @@ chestnut:
|
||||
|
||||
# 开发环境配置
|
||||
server:
|
||||
# 服务器的HTTP端口,默认为8080
|
||||
# 服务器的HTTP端口,默认为9080
|
||||
port: 9080
|
||||
# 开启优雅停机
|
||||
shutdown: graceful
|
||||
|
||||
@ -5,7 +5,7 @@ chestnut:
|
||||
# 代号
|
||||
alias: ChestnutCMS
|
||||
# 版本
|
||||
version: 1.5.7
|
||||
version: 1.5.8
|
||||
# 版权年份
|
||||
copyrightYear: 2022-2025
|
||||
system:
|
||||
@ -15,6 +15,8 @@ chestnut:
|
||||
uploadPath: /home/app/uploadPath
|
||||
freemarker:
|
||||
templateLoaderPath: /home/app/statics
|
||||
image:
|
||||
type: 'JDK'
|
||||
cms:
|
||||
resourceRoot: /home/app/wwwroot_release
|
||||
publish:
|
||||
|
||||
@ -5,7 +5,7 @@ chestnut:
|
||||
# 代号
|
||||
alias: ChestnutCMS
|
||||
# 版本
|
||||
version: 1.5.7
|
||||
version: 1.5.8
|
||||
# 版权年份
|
||||
copyrightYear: 2022-2025
|
||||
system:
|
||||
@ -13,12 +13,17 @@ chestnut:
|
||||
demoMode: true
|
||||
# 文件路径 示例( Windows配置D:/chestnut/uploadPath,Linux配置 /home/app/uploadPath)
|
||||
uploadPath: /home/app/uploadPath
|
||||
# 验证码类型 math 数组计算 char 字符验证
|
||||
captchaType: math
|
||||
freemarker:
|
||||
templateLoaderPath: /home/app/statics
|
||||
image:
|
||||
type: 'JDK'
|
||||
cms:
|
||||
resourceRoot: /home/app/wwwroot_release
|
||||
publish:
|
||||
strategy: ThreadPool
|
||||
pool:
|
||||
threadNamePrefix: "CMS-PUBLISH-"
|
||||
queueCapacity: 10000
|
||||
|
||||
# 开发环境配置
|
||||
server:
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-advertisement</artifactId>
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
package com.chestnut.advertisement.listener;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.chestnut.advertisement.domain.CmsAdvertisement;
|
||||
import com.chestnut.advertisement.service.IAdvertisementService;
|
||||
import com.chestnut.common.async.AsyncTaskManager;
|
||||
@ -26,6 +27,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@ -41,10 +44,21 @@ public class AdvertisementListener {
|
||||
try {
|
||||
long total = this.advertisementService
|
||||
.count(new LambdaQueryWrapper<CmsAdvertisement>().eq(CmsAdvertisement::getSiteId, site.getSiteId()));
|
||||
long lastId = 0;
|
||||
for (long i = 0; i * pageSize < total; i++) {
|
||||
AsyncTaskManager.setTaskProgressInfo((int) (i * pageSize * 100 / total), "正在删除广告数据:" + (i * pageSize) + "/" + total);
|
||||
this.advertisementService.remove(new LambdaQueryWrapper<CmsAdvertisement>()
|
||||
.eq(CmsAdvertisement::getSiteId, site.getSiteId()).last("limit " + pageSize));
|
||||
Page<CmsAdvertisement> advertisements = this.advertisementService.lambdaQuery()
|
||||
.select(CmsAdvertisement::getAdvertisementId)
|
||||
.eq(CmsAdvertisement::getSiteId, site.getSiteId())
|
||||
.gt(CmsAdvertisement::getAdvertisementId, lastId)
|
||||
.orderByAsc(CmsAdvertisement::getAdvertisementId)
|
||||
.page(Page.of(1, pageSize, false));
|
||||
if (!advertisements.getRecords().isEmpty()) {
|
||||
List<Long> advertisementIds = advertisements.getRecords().stream()
|
||||
.map(CmsAdvertisement::getAdvertisementId).toList();
|
||||
this.advertisementService.removeBatchByIds(advertisementIds);
|
||||
lastId = advertisementIds.get(advertisementIds.size() - 1);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
AsyncTaskManager.addErrMessage("删除广告数据错误:" + e.getMessage());
|
||||
|
||||
@ -8,9 +8,9 @@ ADVERTISEMENT.TYPE.image=圖片
|
||||
FREEMARKER.TAG.cms_advertisement.NAME=廣告列表標籤
|
||||
FREEMARKER.TAG.cms_advertisement.DESC=獲取廣告數據列表,內嵌`<#list DataList as ad>${ad.name}</#list>`遍曆數據
|
||||
FREEMARKER.TAG.cms_advertisement.code=廣告位編碼
|
||||
FREEMARKER.TAG.cms_advertisement.type=廣告鏈接類型
|
||||
FREEMARKER.TAG.cms_advertisement.type.None=原始鏈接
|
||||
FREEMARKER.TAG.cms_advertisement.type.Stat=統計鏈接
|
||||
FREEMARKER.TAG.cms_advertisement.type=廣告連結類型
|
||||
FREEMARKER.TAG.cms_advertisement.type.None=原始連結
|
||||
FREEMARKER.TAG.cms_advertisement.type.Stat=統計連結
|
||||
|
||||
# 統計菜單
|
||||
STAT.MENU.CmsAdv=廣告數據統計
|
||||
@ -23,7 +23,7 @@ SCHEDULED_TASK.AdvertisementStatJob=廣告統計任務
|
||||
SCHEDULED_TASK.AdvertisementPublishJob=廣告定時發布下線任務
|
||||
|
||||
MONITORED.CACHE.AD_ID2NAME=廣告名稱
|
||||
MONITORED.CACHE.AD_ID2URL=廣告跳轉鏈接
|
||||
MONITORED.CACHE.AD_ID2URL=廣告跳轉連結
|
||||
|
||||
CMS.AD.ID=廣告ID
|
||||
CMS.AD.SPACE_ID=所屬廣告版位(頁面部件)ID
|
||||
@ -34,7 +34,7 @@ CMS.AD.KEYWORDS=關鍵詞
|
||||
CMS.AD.STATE=狀態
|
||||
CMS.AD.ONLINE_DATE=上線時間
|
||||
CMS.AD.OFFLINE_DATE=下線時間
|
||||
CMS.AD.REDIRECT_URL=原始跳轉鏈接
|
||||
CMS.AD.LINK=實際跳轉鏈接(可設置為中轉地址)
|
||||
CMS.AD.RESOURCE_PATH=廣告素材资源路徑
|
||||
CMS.AD.RESOURCE_SRC=廣告素材訪問鏈接
|
||||
CMS.AD.REDIRECT_URL=原始跳轉連結
|
||||
CMS.AD.LINK=實際跳轉連結(可設置為中轉地址)
|
||||
CMS.AD.RESOURCE_PATH=廣告素材資源路徑
|
||||
CMS.AD.RESOURCE_SRC=廣告素材訪問地址
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-article</artifactId>
|
||||
|
||||
@ -1,139 +1,139 @@
|
||||
/*
|
||||
* Copyright 2022-2025 兮玥(190785909@qq.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chestnut.article.controller.front;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.chestnut.article.domain.CmsArticleDetail;
|
||||
import com.chestnut.article.domain.vo.ArticleApiVO;
|
||||
import com.chestnut.article.service.IArticleService;
|
||||
import com.chestnut.common.domain.R;
|
||||
import com.chestnut.common.security.web.BaseRestController;
|
||||
import com.chestnut.common.utils.IdUtils;
|
||||
import com.chestnut.common.utils.StringUtils;
|
||||
import com.chestnut.contentcore.domain.CmsCatalog;
|
||||
import com.chestnut.contentcore.domain.CmsContent;
|
||||
import com.chestnut.contentcore.fixed.dict.ContentAttribute;
|
||||
import com.chestnut.contentcore.fixed.dict.ContentStatus;
|
||||
import com.chestnut.contentcore.service.ICatalogService;
|
||||
import com.chestnut.contentcore.service.IContentService;
|
||||
import com.chestnut.contentcore.template.tag.CmsCatalogTag;
|
||||
import com.chestnut.contentcore.template.tag.CmsContentTag;
|
||||
import com.chestnut.contentcore.util.CatalogUtils;
|
||||
import com.chestnut.contentcore.util.InternalUrlUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 内容数据API接口
|
||||
*
|
||||
* @author 兮玥
|
||||
* @email 190785909@qq.com
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/api/cms/article")
|
||||
public class ArticleApiController extends BaseRestController {
|
||||
|
||||
private final ICatalogService catalogService;
|
||||
|
||||
private final IContentService contentService;
|
||||
|
||||
private final IArticleService articleService;
|
||||
|
||||
@GetMapping("/list")
|
||||
public R<List<ArticleApiVO>> getContentList(
|
||||
@RequestParam("sid") Long siteId,
|
||||
@RequestParam(value = "cid", required = false, defaultValue = "0") Long catalogId,
|
||||
@RequestParam(value = "lv", required = false, defaultValue = "Root") String level,
|
||||
@RequestParam(value = "attrs", required = false) String hasAttributes,
|
||||
@RequestParam(value = "no_attrs", required = false) String noAttributes,
|
||||
@RequestParam(value = "st", required = false, defaultValue = "Recent") String sortType,
|
||||
@RequestParam(value = "ps", required = false, defaultValue = "16") Integer pageSize,
|
||||
@RequestParam(value = "pn", required = false, defaultValue = "1") Long pageNumber,
|
||||
@RequestParam(value = "pp") String publishPipeCode,
|
||||
@RequestParam(value = "preview", required = false, defaultValue = "false") Boolean preview,
|
||||
@RequestParam(value = "text", required = false, defaultValue = "false") Boolean text
|
||||
) {
|
||||
if (!CmsCatalogTag.CatalogTagLevel.isRoot(level) && !IdUtils.validate(catalogId)) {
|
||||
return R.fail("The parameter cid is required where lv is `Root`.");
|
||||
}
|
||||
LambdaQueryWrapper<CmsContent> q = new LambdaQueryWrapper<>();
|
||||
q.eq(CmsContent::getSiteId, siteId).eq(CmsContent::getStatus, ContentStatus.PUBLISHED);
|
||||
if (!CmsCatalogTag.CatalogTagLevel.isRoot(level)) {
|
||||
CmsCatalog catalog = this.catalogService.getCatalog(catalogId);
|
||||
if (Objects.isNull(catalog)) {
|
||||
return R.fail("Catalog not found: " + catalogId);
|
||||
}
|
||||
if (CmsCatalogTag.CatalogTagLevel.isCurrent(level)) {
|
||||
q.eq(CmsContent::getCatalogId, catalog.getCatalogId());
|
||||
} else if (CmsCatalogTag.CatalogTagLevel.isChild(level)) {
|
||||
q.likeRight(CmsContent::getCatalogAncestors, catalog.getAncestors() + CatalogUtils.ANCESTORS_SPLITER);
|
||||
} else if (CmsCatalogTag.CatalogTagLevel.isCurrentAndChild(level)) {
|
||||
q.likeRight(CmsContent::getCatalogAncestors, catalog.getAncestors());
|
||||
}
|
||||
}
|
||||
if (StringUtils.isNotEmpty(hasAttributes)) {
|
||||
int attrTotal = ContentAttribute.convertInt(hasAttributes.split(","));
|
||||
q.apply(attrTotal > 0, "attributes&{0}={1}", attrTotal, attrTotal);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(noAttributes)) {
|
||||
String[] contentAttrs = noAttributes.split(",");
|
||||
int attrTotal = ContentAttribute.convertInt(contentAttrs);
|
||||
for (String attr : contentAttrs) {
|
||||
int bit = ContentAttribute.bit(attr);
|
||||
q.apply(bit > 0, "attributes&{0}<>{1}", attrTotal, bit);
|
||||
}
|
||||
}
|
||||
if (CmsContentTag.SortTagAttr.isRecent(sortType)) {
|
||||
q.orderByDesc(CmsContent::getPublishDate);
|
||||
} else {
|
||||
q.orderByDesc(Arrays.asList(CmsContent::getTopFlag, CmsContent::getSortFlag));
|
||||
}
|
||||
|
||||
Page<CmsContent> pageResult = this.contentService.dao().page(new Page<>(pageNumber, pageSize, false), q);
|
||||
if (pageResult.getRecords().isEmpty()) {
|
||||
return R.ok(List.of());
|
||||
}
|
||||
List<Long> contentIds = pageResult.getRecords().stream().map(CmsContent::getContentId).toList();
|
||||
Map<Long, CmsArticleDetail> articleDetails = new HashMap<>();
|
||||
if (text) {
|
||||
articleDetails.putAll(this.articleService.dao().listByIds(contentIds)
|
||||
.stream().collect(Collectors.toMap(CmsArticleDetail::getContentId, c -> c)));
|
||||
}
|
||||
|
||||
List<ArticleApiVO> list = new ArrayList<>();
|
||||
pageResult.getRecords().forEach(c -> {
|
||||
ArticleApiVO vo = ArticleApiVO.newInstance(c, null);
|
||||
CmsCatalog catalog = this.catalogService.getCatalog(c.getCatalogId());
|
||||
vo.setCatalogName(catalog.getName());
|
||||
vo.setCatalogLink(catalogService.getCatalogLink(catalog, 1, publishPipeCode, preview));
|
||||
vo.setLink(this.contentService.getContentLink(c, 1, publishPipeCode, preview));
|
||||
vo.setLogoSrc(InternalUrlUtils.getActualUrl(c.getLogo(), publishPipeCode, preview));
|
||||
if (text && articleDetails.containsKey(c.getContentId())) {
|
||||
vo.setContentHtml(articleDetails.get(c.getContentId()).getContentHtml());
|
||||
}
|
||||
list.add(vo);
|
||||
});
|
||||
return R.ok(list);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2022-2025 兮玥(190785909@qq.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chestnut.article.controller.front;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.chestnut.article.domain.CmsArticleDetail;
|
||||
import com.chestnut.article.domain.vo.ArticleApiVO;
|
||||
import com.chestnut.article.service.IArticleService;
|
||||
import com.chestnut.common.domain.R;
|
||||
import com.chestnut.common.security.web.BaseRestController;
|
||||
import com.chestnut.common.utils.IdUtils;
|
||||
import com.chestnut.common.utils.StringUtils;
|
||||
import com.chestnut.contentcore.domain.CmsCatalog;
|
||||
import com.chestnut.contentcore.domain.CmsContent;
|
||||
import com.chestnut.contentcore.fixed.dict.ContentAttribute;
|
||||
import com.chestnut.contentcore.fixed.dict.ContentStatus;
|
||||
import com.chestnut.contentcore.service.ICatalogService;
|
||||
import com.chestnut.contentcore.service.IContentService;
|
||||
import com.chestnut.contentcore.template.tag.CmsCatalogTag;
|
||||
import com.chestnut.contentcore.template.tag.CmsContentTag;
|
||||
import com.chestnut.contentcore.util.CatalogUtils;
|
||||
import com.chestnut.contentcore.util.InternalUrlUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 内容数据API接口
|
||||
*
|
||||
* @author 兮玥
|
||||
* @email 190785909@qq.com
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/api/cms/article")
|
||||
public class ArticleApiController extends BaseRestController {
|
||||
|
||||
private final ICatalogService catalogService;
|
||||
|
||||
private final IContentService contentService;
|
||||
|
||||
private final IArticleService articleService;
|
||||
|
||||
@GetMapping("/list")
|
||||
public R<List<ArticleApiVO>> getContentList(
|
||||
@RequestParam("sid") Long siteId,
|
||||
@RequestParam(value = "cid", required = false, defaultValue = "0") Long catalogId,
|
||||
@RequestParam(value = "lv", required = false, defaultValue = "Root") String level,
|
||||
@RequestParam(value = "attrs", required = false) String hasAttributes,
|
||||
@RequestParam(value = "no_attrs", required = false) String noAttributes,
|
||||
@RequestParam(value = "st", required = false, defaultValue = "Recent") String sortType,
|
||||
@RequestParam(value = "ps", required = false, defaultValue = "16") Integer pageSize,
|
||||
@RequestParam(value = "pn", required = false, defaultValue = "1") Long pageNumber,
|
||||
@RequestParam(value = "pp") String publishPipeCode,
|
||||
@RequestParam(value = "preview", required = false, defaultValue = "false") Boolean preview,
|
||||
@RequestParam(value = "text", required = false, defaultValue = "false") Boolean text
|
||||
) {
|
||||
if (!CmsCatalogTag.CatalogTagLevel.isRoot(level) && !IdUtils.validate(catalogId)) {
|
||||
return R.fail("The parameter cid is required where lv is `Root`.");
|
||||
}
|
||||
LambdaQueryWrapper<CmsContent> q = new LambdaQueryWrapper<>();
|
||||
q.eq(CmsContent::getSiteId, siteId).eq(CmsContent::getStatus, ContentStatus.PUBLISHED);
|
||||
if (!CmsCatalogTag.CatalogTagLevel.isRoot(level)) {
|
||||
CmsCatalog catalog = this.catalogService.getCatalog(catalogId);
|
||||
if (Objects.isNull(catalog)) {
|
||||
return R.fail("Catalog not found: " + catalogId);
|
||||
}
|
||||
if (CmsCatalogTag.CatalogTagLevel.isCurrent(level)) {
|
||||
q.eq(CmsContent::getCatalogId, catalog.getCatalogId());
|
||||
} else if (CmsCatalogTag.CatalogTagLevel.isChild(level)) {
|
||||
q.likeRight(CmsContent::getCatalogAncestors, catalog.getAncestors() + CatalogUtils.ANCESTORS_SPLITER);
|
||||
} else if (CmsCatalogTag.CatalogTagLevel.isCurrentAndChild(level)) {
|
||||
q.likeRight(CmsContent::getCatalogAncestors, catalog.getAncestors());
|
||||
}
|
||||
}
|
||||
if (StringUtils.isNotEmpty(hasAttributes)) {
|
||||
int attrTotal = ContentAttribute.convertInt(hasAttributes.split(","));
|
||||
q.apply(attrTotal > 0, "attributes&{0}={1}", attrTotal, attrTotal);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(noAttributes)) {
|
||||
String[] contentAttrs = noAttributes.split(",");
|
||||
int attrTotal = ContentAttribute.convertInt(contentAttrs);
|
||||
for (String attr : contentAttrs) {
|
||||
int bit = ContentAttribute.bit(attr);
|
||||
q.apply(bit > 0, "attributes&{0}<>{1}", attrTotal, bit);
|
||||
}
|
||||
}
|
||||
if (CmsContentTag.SortTagAttr.isRecent(sortType)) {
|
||||
q.orderByDesc(CmsContent::getPublishDate);
|
||||
} else {
|
||||
q.orderByDesc(Arrays.asList(CmsContent::getTopFlag, CmsContent::getSortFlag));
|
||||
}
|
||||
|
||||
Page<CmsContent> pageResult = this.contentService.dao().page(new Page<>(pageNumber, pageSize, false), q);
|
||||
if (pageResult.getRecords().isEmpty()) {
|
||||
return R.ok(List.of());
|
||||
}
|
||||
List<Long> contentIds = pageResult.getRecords().stream().map(CmsContent::getContentId).toList();
|
||||
Map<Long, CmsArticleDetail> articleDetails = new HashMap<>();
|
||||
if (text) {
|
||||
articleDetails.putAll(this.articleService.dao().listByIds(contentIds)
|
||||
.stream().collect(Collectors.toMap(CmsArticleDetail::getContentId, c -> c)));
|
||||
}
|
||||
|
||||
List<ArticleApiVO> list = new ArrayList<>();
|
||||
pageResult.getRecords().forEach(c -> {
|
||||
ArticleApiVO vo = ArticleApiVO.newInstance(c, null);
|
||||
CmsCatalog catalog = this.catalogService.getCatalog(c.getCatalogId());
|
||||
vo.setCatalogName(catalog.getName());
|
||||
vo.setCatalogLink(catalogService.getCatalogLink(catalog, 1, publishPipeCode, preview));
|
||||
vo.setLink(this.contentService.getContentLink(c, 1, publishPipeCode, preview));
|
||||
vo.setLogoSrc(InternalUrlUtils.getActualUrl(c.getLogo(), publishPipeCode, preview));
|
||||
if (text && articleDetails.containsKey(c.getContentId())) {
|
||||
vo.setContentHtml(articleDetails.get(c.getContentId()).getContentHtml());
|
||||
}
|
||||
list.add(vo);
|
||||
});
|
||||
return R.ok(list);
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ FREEMARKER.FUNC.dealArticleBody.DESC=文章正文處理函數,主要用來處
|
||||
FREEMARKER.FUNC.dealArticleBody.Arg1.Name=文章正文內容
|
||||
FREEMARKER.FUNC.dealArticleBody.Arg2.Name=文章正文格式
|
||||
|
||||
# 固定字典項
|
||||
ArticleBodyFormat.RichText=富文本
|
||||
|
||||
CMS.ARTICLE.FORMAT=文章正文格式
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-block</artifactId>
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-comment</artifactId>
|
||||
|
||||
@ -7,19 +7,19 @@ FREEMARKER.TAG.cms_comment.type=來源類型
|
||||
CMS.COMMENT.ID=評論ID
|
||||
CMS.COMMENT.UID=評論用戶ID
|
||||
CMS.COMMENT.PARENT_ID=父級評論ID
|
||||
CMS.COMMENT.REPLY_UID=回復的用戶ID
|
||||
CMS.COMMENT.REPLY_COUNT=回復數
|
||||
CMS.COMMENT.REPLY_UID=回複的用戶ID
|
||||
CMS.COMMENT.REPLY_COUNT=回複數
|
||||
CMS.COMMENT.SOURCE_TYPE=來源分類
|
||||
CMS.COMMENT.SOURCE_ID=來源唯一標識
|
||||
CMS.COMMENT.SOURCE_TITLE=來源標題
|
||||
CMS.COMMENT.SOURCE_URL=來源URL
|
||||
CMS.COMMENT.CONTENT=評論內容
|
||||
CMS.COMMENT.LIKE_COUNT=點讚數
|
||||
CMS.COMMENT.LIKE_COUNT=點贊數
|
||||
CMS.COMMENT.AUDIT_STATUS=評論審核狀態
|
||||
CMS.COMMENT.COMMENT_TIME=評論提交時間
|
||||
CMS.COMMENT.DEL_FLAG=刪除標識
|
||||
CMS.COMMENT.IP=用戶ID
|
||||
CMS.COMMENT.IP=用戶IP
|
||||
CMS.COMMENT.REGION=用戶歸屬地
|
||||
CMS.COMMENT.CLIENT_TYPE=客戶端類型
|
||||
CMS.COMMENT.USER_AGENT=UserAgent
|
||||
CMS.COMMENT.REPLY_LIST=回復列表
|
||||
CMS.COMMENT.REPLY_LIST=回複列表
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-contentcore</artifactId>
|
||||
|
||||
@ -84,8 +84,8 @@ public class CatalogMonitoredCache implements IMonitoredCache<CmsCatalog> {
|
||||
return redisCache.getCacheObject(cacheKeyByAlias(siteId, alias), CmsCatalog.class, supplier);
|
||||
}
|
||||
|
||||
public void clear(CmsCatalog catalog) {
|
||||
this.redisCache.deleteObject(cacheKeyById(catalog.getCatalogId()));
|
||||
this.redisCache.deleteObject(cacheKeyByAlias(catalog.getSiteId(), catalog.getAlias()));
|
||||
public void clear(Long siteId, Long catalogId, String catalogAlias) {
|
||||
this.redisCache.deleteObject(cacheKeyById(catalogId));
|
||||
this.redisCache.deleteObject(cacheKeyByAlias(siteId, catalogAlias));
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ import com.chestnut.common.log.annotation.Log;
|
||||
import com.chestnut.common.log.enums.BusinessType;
|
||||
import com.chestnut.common.security.anno.Priv;
|
||||
import com.chestnut.common.security.domain.LoginUser;
|
||||
import com.chestnut.common.security.domain.Operator;
|
||||
import com.chestnut.common.security.web.BaseRestController;
|
||||
import com.chestnut.common.utils.*;
|
||||
import com.chestnut.contentcore.core.ICatalogType;
|
||||
@ -270,7 +271,7 @@ public class CatalogController extends BaseRestController {
|
||||
throw ContentCoreErrorCode.CATALOG_CANNOT_PUBLISH.exception();
|
||||
}
|
||||
AsyncTask task = this.publishService.publishCatalog(catalog, dto.getPublishChild(), dto.getPublishDetail(),
|
||||
dto.getPublishStatus(), StpAdminUtil.getLoginUser());
|
||||
dto.getPublishStatus(), Operator.of(StpAdminUtil.getLoginUser()));
|
||||
return R.ok(task.getTaskId());
|
||||
}
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@ import com.chestnut.common.log.annotation.Log;
|
||||
import com.chestnut.common.log.enums.BusinessType;
|
||||
import com.chestnut.common.security.anno.Priv;
|
||||
import com.chestnut.common.security.domain.LoginUser;
|
||||
import com.chestnut.common.security.domain.Operator;
|
||||
import com.chestnut.common.security.web.BaseRestController;
|
||||
import com.chestnut.common.security.web.PageRequest;
|
||||
import com.chestnut.common.utils.IdUtils;
|
||||
@ -171,12 +172,11 @@ public class ContentController extends BaseRestController {
|
||||
@PostMapping
|
||||
public R<?> addContent(@RequestParam("contentType") String contentType, HttpServletRequest request)
|
||||
throws IOException {
|
||||
LoginUser loginUser = StpAdminUtil.getLoginUser();
|
||||
IContentType ct = ContentCoreUtils.getContentType(contentType);
|
||||
|
||||
IContent<?> content = ct.readFrom(request.getInputStream());
|
||||
content.setOperator(StpAdminUtil.getLoginUser());
|
||||
PermissionUtils.checkPermission(CatalogPrivItem.AddContent.getPermissionKey(content.getCatalogId()),
|
||||
content.getOperator());
|
||||
PermissionUtils.checkPermission(CatalogPrivItem.AddContent.getPermissionKey(content.getCatalogId()), loginUser);
|
||||
content.setOperator(Operator.of(loginUser));
|
||||
|
||||
AsyncTask task = this.contentService.addContent(content);
|
||||
return R.ok(Map.of("taskId", task.getTaskId()));
|
||||
@ -187,12 +187,13 @@ public class ContentController extends BaseRestController {
|
||||
@PutMapping
|
||||
public R<?> saveContent(@RequestParam("contentType") String contentType, HttpServletRequest request)
|
||||
throws IOException {
|
||||
LoginUser loginUser = StpAdminUtil.getLoginUser();
|
||||
IContentType ct = ContentCoreUtils.getContentType(contentType);
|
||||
|
||||
IContent<?> content = ct.readFrom(request.getInputStream());
|
||||
content.setOperator(StpAdminUtil.getLoginUser());
|
||||
content.setOperator(Operator.of(loginUser));
|
||||
PermissionUtils.checkPermission(CatalogPrivItem.EditContent.getPermissionKey(content.getCatalogId()),
|
||||
content.getOperator());
|
||||
StpAdminUtil.getLoginUser());
|
||||
|
||||
AsyncTask task = this.contentService.saveContent(content);
|
||||
return R.ok(Map.of("taskId", task.getTaskId()));
|
||||
|
||||
@ -89,13 +89,13 @@ public class CoreController extends BaseRestController {
|
||||
IInternalDataType internalDataType = ContentCoreUtils.getInternalDataType(dataType);
|
||||
Assert.notNull(internalDataType, () -> ContentCoreErrorCode.UNSUPPORTED_INTERNAL_DATA_TYPE.exception(dataType));
|
||||
|
||||
IInternalDataType.RequestData data = new IInternalDataType.RequestData(dataId, pageIndex, publishPipe,
|
||||
true, ServletUtils.getParamMap(ServletUtils.getRequest()));
|
||||
try {
|
||||
IInternalDataType.RequestData data = new IInternalDataType.RequestData(dataId, pageIndex, publishPipe,
|
||||
true, ServletUtils.getParamMap(ServletUtils.getRequest()));
|
||||
String pageData = internalDataType.getPageData(data);
|
||||
response.getWriter().write(pageData);
|
||||
internalDataType.processPageData(data, response.getWriter());
|
||||
} catch (Exception e) {
|
||||
response.getWriter().write(e.getMessage());
|
||||
// Ignore
|
||||
e.printStackTrace(response.getWriter());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -32,6 +32,7 @@ import com.chestnut.common.utils.ServletUtils;
|
||||
import com.chestnut.common.utils.StringUtils;
|
||||
import com.chestnut.contentcore.core.IResourceType;
|
||||
import com.chestnut.contentcore.core.impl.InternalDataType_Resource;
|
||||
import com.chestnut.contentcore.core.impl.ResourceType_Image;
|
||||
import com.chestnut.contentcore.domain.CmsResource;
|
||||
import com.chestnut.contentcore.domain.CmsSite;
|
||||
import com.chestnut.contentcore.domain.dto.ResourceUploadDTO;
|
||||
@ -118,7 +119,11 @@ public class ResourceController extends BaseRestController {
|
||||
if (r.getPath().startsWith("http://") || r.getPath().startsWith("https://")) {
|
||||
r.setSrc(r.getPath());
|
||||
} else {
|
||||
resourceService.dealDefaultThumbnail(site, r.getInternalUrl(), r::setSrc);
|
||||
if (ResourceType_Image.isImage(r.getResourceType())) {
|
||||
resourceService.dealDefaultThumbnail(site, r.getInternalUrl(), r::setSrc);
|
||||
} else {
|
||||
r.setSrc(InternalUrlUtils.getActualPreviewUrl(r.getInternalUrl()));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -192,7 +197,7 @@ public class ResourceController extends BaseRestController {
|
||||
return R.ok(resource);
|
||||
}
|
||||
|
||||
@GetMapping("/downlad/{resourceId}")
|
||||
@GetMapping("/download/{resourceId}")
|
||||
public void downloadResourceFile(@PathVariable @LongId Long resourceId, HttpServletResponse response) {
|
||||
CmsResource resource = this.resourceService.getById(resourceId);
|
||||
Assert.notNull(resource, () -> CommonErrorCode.DATA_NOT_FOUND_BY_ID.exception("resourceId", resourceId));
|
||||
|
||||
@ -26,6 +26,7 @@ import com.chestnut.common.log.annotation.Log;
|
||||
import com.chestnut.common.log.enums.BusinessType;
|
||||
import com.chestnut.common.security.anno.Priv;
|
||||
import com.chestnut.common.security.domain.LoginUser;
|
||||
import com.chestnut.common.security.domain.Operator;
|
||||
import com.chestnut.common.security.web.BaseRestController;
|
||||
import com.chestnut.common.security.web.PageRequest;
|
||||
import com.chestnut.common.utils.Assert;
|
||||
@ -257,7 +258,7 @@ public class SiteController extends BaseRestController {
|
||||
Assert.notNull(site, () -> CommonErrorCode.DATA_NOT_FOUND_BY_ID.exception("siteId", dto.getSiteId()));
|
||||
|
||||
if (!dto.isPublishIndex()) {
|
||||
AsyncTask task = publishService.publishAll(site, dto.getContentStatus(), StpAdminUtil.getLoginUser());
|
||||
AsyncTask task = publishService.publishAll(site, dto.getContentStatus(), Operator.of(StpAdminUtil.getLoginUser()));
|
||||
return R.ok(task.getTaskId());
|
||||
}
|
||||
publishService.publishSiteIndex(site);
|
||||
|
||||
@ -29,6 +29,7 @@ import com.chestnut.common.security.web.PageRequest;
|
||||
import com.chestnut.common.staticize.StaticizeService;
|
||||
import com.chestnut.common.utils.*;
|
||||
import com.chestnut.common.utils.file.FileExUtils;
|
||||
import com.chestnut.common.validation.RegexConsts;
|
||||
import com.chestnut.contentcore.domain.CmsSite;
|
||||
import com.chestnut.contentcore.domain.CmsTemplate;
|
||||
import com.chestnut.contentcore.domain.dto.TemplateAddDTO;
|
||||
@ -182,7 +183,7 @@ public class TemplateController extends BaseRestController {
|
||||
fileName = FileExUtils.normalizePath(fileName);
|
||||
String[] split = fileName.substring(0, fileName.indexOf(suffix)).split("/");
|
||||
for (String item : split) {
|
||||
if (StringUtils.isEmpty(item) || !Pattern.matches("^[a-zA-Z0-9_]+$", item)) {
|
||||
if (StringUtils.isEmpty(item) || !Pattern.matches(RegexConsts.REGEX_CODE, item)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,8 +16,9 @@
|
||||
package com.chestnut.contentcore.core;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.chestnut.common.exception.CommonErrorCode;
|
||||
import com.chestnut.common.security.domain.LoginUser;
|
||||
import com.chestnut.common.security.domain.Operator;
|
||||
import com.chestnut.common.utils.*;
|
||||
import com.chestnut.contentcore.domain.CmsCatalog;
|
||||
import com.chestnut.contentcore.domain.CmsContent;
|
||||
@ -30,7 +31,6 @@ import com.chestnut.contentcore.listener.event.AfterContentSaveEvent;
|
||||
import com.chestnut.contentcore.listener.event.BeforeContentSaveEvent;
|
||||
import com.chestnut.contentcore.listener.event.OnContentCopyEvent;
|
||||
import com.chestnut.contentcore.listener.event.OnContentMoveEvent;
|
||||
import com.chestnut.contentcore.perms.CatalogPermissionType;
|
||||
import com.chestnut.contentcore.properties.PublishedContentEditProperty;
|
||||
import com.chestnut.contentcore.service.ICatalogService;
|
||||
import com.chestnut.contentcore.service.IContentService;
|
||||
@ -40,7 +40,6 @@ import com.chestnut.contentcore.util.ContentCoreUtils;
|
||||
import com.chestnut.contentcore.util.ContentLogUtils;
|
||||
import com.chestnut.contentcore.util.InternalUrlUtils;
|
||||
import com.chestnut.system.fixed.dict.YesOrNo;
|
||||
import com.chestnut.system.permission.PermissionUtils;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
@ -73,7 +72,7 @@ public abstract class AbstractContent<T> implements IContent<T> {
|
||||
@Setter
|
||||
private Map<String, Object> params;
|
||||
|
||||
private LoginUser operator;
|
||||
private Operator operator;
|
||||
|
||||
@Override
|
||||
public CmsSite getSite() {
|
||||
@ -122,12 +121,12 @@ public abstract class AbstractContent<T> implements IContent<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginUser getOperator() {
|
||||
public Operator getOperator() {
|
||||
return this.operator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOperator(LoginUser operator) {
|
||||
public void setOperator(Operator operator) {
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
@ -274,9 +273,6 @@ public abstract class AbstractContent<T> implements IContent<T> {
|
||||
this.getContentEntity().getTitle())) {
|
||||
throw ContentCoreErrorCode.TITLE_REPLEAT.exception();
|
||||
}
|
||||
// 校验权限
|
||||
PermissionUtils.checkPermission(CatalogPermissionType.CatalogPrivItem.AddContent.getPermissionKey(toCatalog.getCatalogId()), this.getOperator());
|
||||
|
||||
CmsContent newContent = new CmsContent();
|
||||
BeanUtils.copyProperties(this.getContentEntity(), newContent, "contentId", "template", "staticPath", "topFlag",
|
||||
"topDate", "isLock", "lockUser");
|
||||
@ -316,8 +312,6 @@ public abstract class AbstractContent<T> implements IContent<T> {
|
||||
this.getContentEntity().getTitle())) {
|
||||
throw ContentCoreErrorCode.TITLE_REPLEAT.exception();
|
||||
}
|
||||
// 校验权限
|
||||
PermissionUtils.checkPermission(CatalogPermissionType.CatalogPrivItem.AddContent.getPermissionKey(toCatalog.getCatalogId()), this.getOperator());
|
||||
|
||||
CmsCatalog fromCatalog = this.getCatalogService().getCatalog(content.getCatalogId());
|
||||
// 重置内容信息
|
||||
@ -377,12 +371,12 @@ public abstract class AbstractContent<T> implements IContent<T> {
|
||||
}
|
||||
LambdaQueryWrapper<CmsContent> q = new LambdaQueryWrapper<CmsContent>()
|
||||
.eq(CmsContent::getCatalogId, next.getCatalogId()).gt(CmsContent::getSortFlag, next.getSortFlag())
|
||||
.orderByAsc(CmsContent::getSortFlag).last("limit 1");
|
||||
CmsContent prev = this.getContentService().dao().getOne(q);
|
||||
if (prev == null) {
|
||||
.orderByAsc(CmsContent::getSortFlag);
|
||||
Page<CmsContent> prev = this.getContentService().dao().page(Page.of(1, 1, false), q);
|
||||
if (prev.getRecords().isEmpty()) {
|
||||
this.content.setSortFlag(SortUtils.getDefaultSortValue());
|
||||
} else {
|
||||
this.content.setSortFlag((next.getSortFlag() + prev.getSortFlag()) / 2);
|
||||
this.content.setSortFlag((next.getSortFlag() + prev.getRecords().get(0).getSortFlag()) / 2);
|
||||
}
|
||||
this.getContentEntity().updateBy(this.getOperatorUName());
|
||||
this.getContentService().dao().updateById(content);
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.chestnut.contentcore.core;
|
||||
|
||||
import com.chestnut.common.security.domain.LoginUser;
|
||||
import com.chestnut.common.security.domain.Operator;
|
||||
import com.chestnut.contentcore.domain.CmsCatalog;
|
||||
import com.chestnut.contentcore.domain.CmsContent;
|
||||
import com.chestnut.contentcore.domain.CmsSite;
|
||||
@ -95,7 +95,7 @@ public interface IContent<T> {
|
||||
/**
|
||||
* 获取操作人信息
|
||||
*/
|
||||
LoginUser getOperator();
|
||||
Operator getOperator();
|
||||
|
||||
/**
|
||||
* 获取操作人用户名
|
||||
@ -111,7 +111,7 @@ public interface IContent<T> {
|
||||
/**
|
||||
* 设置操作人信息
|
||||
*/
|
||||
void setOperator(LoginUser operator);
|
||||
void setOperator(Operator operator);
|
||||
|
||||
/**
|
||||
* 复制内容到指定栏目
|
||||
|
||||
@ -22,6 +22,7 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -93,6 +94,8 @@ public interface IInternalDataType {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
default void processPageData(RequestData requestData, Writer writer) throws TemplateException, IOException {}
|
||||
|
||||
/**
|
||||
* 访问链接
|
||||
*
|
||||
|
||||
@ -26,6 +26,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@ -56,6 +57,14 @@ public class InternalDataType_Catalog implements IInternalDataType {
|
||||
return this.publishService.getCatalogPageData(catalog, requestData, listFlag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processPageData(RequestData requestData, Writer writer) throws TemplateException, IOException {
|
||||
CmsCatalog catalog = catalogService.getCatalog(requestData.getDataId());
|
||||
boolean listFlag = YesOrNo.isYes(requestData.getParams().get("list"));
|
||||
this.publishService.processCatalogPage(catalog, requestData, listFlag, writer);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLink(InternalURL internalUrl, int pageIndex, String publishPipeCode, boolean isPreview) {
|
||||
CmsCatalog catalog = catalogService.getCatalog(internalUrl.getId());
|
||||
|
||||
@ -27,6 +27,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@ -58,6 +59,14 @@ public class InternalDataType_Content implements IInternalDataType {
|
||||
return this.publishService.getContentPageData(content, requestData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processPageData(RequestData requestData, Writer writer) throws TemplateException, IOException {
|
||||
CmsContent content = contentService.dao().getById(requestData.getDataId());
|
||||
Assert.notNull(content, () -> CommonErrorCode.DATA_NOT_FOUND_BY_ID.exception("contentId", requestData.getDataId()));
|
||||
|
||||
this.publishService.processContentPage(content, requestData, writer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLink(InternalURL internalUrl, int pageIndex, String publishPipeCode, boolean isPreview) {
|
||||
CmsContent content = contentService.dao().getById(internalUrl.getId());
|
||||
|
||||
@ -26,6 +26,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* 内部数据类型:页面组件
|
||||
@ -53,6 +54,14 @@ public class InternalDataType_PageWidget implements IInternalDataType {
|
||||
CmsPageWidget pageWidget = pageWidgetService.getById(data.getDataId());
|
||||
Assert.notNull(pageWidget, () -> CommonErrorCode.DATA_NOT_FOUND_BY_ID.exception("pageWidgetId", data.getDataId()));
|
||||
|
||||
return this.publishService.getPageWidgetPageData(pageWidget, data.getPublishPipeCode(), data.isPreview());
|
||||
return this.publishService.getPageWidgetPageData(pageWidget, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processPageData(RequestData data, Writer writer) throws TemplateException, IOException {
|
||||
CmsPageWidget pageWidget = pageWidgetService.getById(data.getDataId());
|
||||
Assert.notNull(pageWidget, () -> CommonErrorCode.DATA_NOT_FOUND_BY_ID.exception("pageWidgetId", data.getDataId()));
|
||||
|
||||
this.publishService.processPageWidget(pageWidget, data, writer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* 内部数据类型:站点
|
||||
@ -54,6 +55,12 @@ public class InternalDataType_Site implements IInternalDataType {
|
||||
return this.publishService.getSitePageData(site, requestData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processPageData(RequestData requestData, Writer writer) throws TemplateException, IOException {
|
||||
CmsSite site = siteService.getSite(requestData.getDataId());
|
||||
this.publishService.processSitePage(site, requestData, writer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLink(InternalURL internalUrl, int pageIndex, String publishPipeCode, boolean isPreview) {
|
||||
CmsSite site = siteService.getSite(internalUrl.getId());
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.chestnut.contentcore.core.impl;
|
||||
|
||||
import com.chestnut.common.utils.StringUtils;
|
||||
import com.chestnut.contentcore.core.IPublishPipeProp;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -59,7 +60,10 @@ public class PublishPipeProp_RelativePrefix implements IPublishPipeProp {
|
||||
|
||||
public static String getValue(String publishPipeCode, Map<String, Map<String, Object>> publishPipeProps) {
|
||||
if (Objects.nonNull(publishPipeProps)) {
|
||||
return MapUtils.getString(publishPipeProps.get(publishPipeCode), KEY);
|
||||
String v = MapUtils.getString(publishPipeProps.get(publishPipeCode), KEY);
|
||||
if (StringUtils.isNotBlank(v)) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return DEFAULT_VALUE;
|
||||
}
|
||||
|
||||
@ -65,7 +65,8 @@ public class CmsContentDAO extends BackupServiceImpl<CmsContentMapper, CmsConten
|
||||
}
|
||||
LambdaQueryWrapper<CmsContent> q = new LambdaQueryWrapper<CmsContent>()
|
||||
.select(StringUtils.isNotEmpty(columns), columns)
|
||||
.eq(CmsContent::getSiteId, siteId);
|
||||
.eq(CmsContent::getSiteId, siteId)
|
||||
.orderByAsc(CmsContent::getContentId);
|
||||
return this.page(page, q);
|
||||
}
|
||||
|
||||
@ -83,7 +84,8 @@ public class CmsContentDAO extends BackupServiceImpl<CmsContentMapper, CmsConten
|
||||
}
|
||||
return this.getBackupMapper().selectPage(page, new LambdaQueryWrapper<BCmsContent>()
|
||||
.select(StringUtils.isNotEmpty(columns), columns)
|
||||
.eq(BCmsContent::getSiteId, siteId));
|
||||
.eq(BCmsContent::getSiteId, siteId)
|
||||
.orderByAsc(BCmsContent::getBackupId));
|
||||
}
|
||||
|
||||
public void removeBackupBatchByIds(List<Long> backupIds) {
|
||||
|
||||
@ -19,8 +19,8 @@ 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 com.chestnut.common.validation.RegexConsts;
|
||||
import com.chestnut.system.fixed.dict.EnableOrDisable;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
@ -64,7 +64,7 @@ public class CmsPublishPipe extends BaseEntity {
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
@Pattern(regexp = "[A-Za-z0-9_]+")
|
||||
@Pattern(regexp = RegexConsts.REGEX_CODE)
|
||||
private String code;
|
||||
|
||||
/**
|
||||
|
||||
@ -20,6 +20,7 @@ import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.chestnut.common.annotation.XComment;
|
||||
import com.chestnut.common.db.domain.BaseEntity;
|
||||
import com.chestnut.common.validation.RegexConsts;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Getter;
|
||||
@ -55,7 +56,7 @@ public class CmsSiteProperty extends BaseEntity {
|
||||
private String propName;
|
||||
|
||||
@XComment("属性编码")
|
||||
@Pattern(regexp = "[A-Za-z0-9_]+", message = "{VALIDATOR.CMS.SITE_PROPERTY.REGEXP_ERR}")
|
||||
@Pattern(regexp = RegexConsts.REGEX_CODE)
|
||||
private String propCode;
|
||||
|
||||
@XComment("属性值")
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
package com.chestnut.contentcore.domain.dto;
|
||||
|
||||
import com.chestnut.common.security.domain.BaseDTO;
|
||||
|
||||
import com.chestnut.common.validation.RegexConsts;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Getter;
|
||||
@ -46,14 +46,14 @@ public class CatalogAddDTO extends BaseDTO {
|
||||
* 栏目别名
|
||||
*/
|
||||
@NotBlank
|
||||
@Pattern(regexp = "^[A-Za-z0-9_]+$", message = "栏目别名只能使用大小写字母、数字、下划线组合")
|
||||
@Pattern(regexp = RegexConsts.REGEX_CODE)
|
||||
private String alias;
|
||||
|
||||
/**
|
||||
* 栏目目录
|
||||
*/
|
||||
@NotBlank
|
||||
@Pattern(regexp = "^[A-Za-z0-9_\\/]+$", message = "栏目路径只能使用大小写字母、数字、下划线组合")
|
||||
@Pattern(regexp = RegexConsts.REGEX_PATH)
|
||||
private String path;
|
||||
|
||||
/**
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
package com.chestnut.contentcore.domain.dto;
|
||||
|
||||
import com.chestnut.common.security.domain.BaseDTO;
|
||||
import com.chestnut.common.validation.RegexConsts;
|
||||
import com.chestnut.contentcore.domain.pojo.PublishPipeProps;
|
||||
import com.chestnut.system.fixed.dict.YesOrNo;
|
||||
import com.chestnut.system.validator.Dict;
|
||||
@ -54,14 +55,14 @@ public class CatalogUpdateDTO extends BaseDTO {
|
||||
* 栏目别名
|
||||
*/
|
||||
@NotBlank
|
||||
@Pattern(regexp = "^[A-Za-z0-9_]+$", message = "栏目别名只能使用大小写字母、数字、下划线组合")
|
||||
@Pattern(regexp = RegexConsts.REGEX_CODE, message = "栏目别名只能使用大小写字母、数字、下划线组合")
|
||||
private String alias;
|
||||
|
||||
/**
|
||||
* 栏目目录
|
||||
*/
|
||||
@NotBlank
|
||||
@Pattern(regexp = "^[A-Za-z0-9_\\/]+$", message = "栏目路径只能使用大小写字母、数字、下划线组合")
|
||||
@Pattern(regexp = RegexConsts.REGEX_PATH, message = "栏目路径只能使用大小写字母、数字、下划线组合")
|
||||
private String path;
|
||||
|
||||
/*
|
||||
|
||||
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2022-2025 兮玥(190785909@qq.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chestnut.contentcore.enums;
|
||||
|
||||
import com.chestnut.common.i18n.I18nUtils;
|
||||
|
||||
@ -60,8 +60,6 @@ public class ContentCoreListener {
|
||||
|
||||
private final IPublishService publishService;
|
||||
|
||||
private final AsyncTaskManager asyncTaskManager;
|
||||
|
||||
@EventListener
|
||||
public void beforeSiteDelete(BeforeSiteDeleteEvent event) {
|
||||
CmsSite site = event.getSite();
|
||||
@ -74,27 +72,37 @@ public class ContentCoreListener {
|
||||
// 删除内容数据
|
||||
try {
|
||||
long total = this.contentService.dao().countBySiteId(site.getSiteId());
|
||||
long lastId = 0;
|
||||
for (long i = 0; i * pageSize < total; i++) {
|
||||
AsyncTaskManager.setTaskProgressInfo((int) (i * pageSize * 100 / total), "正在删除内容数据:" + (i * pageSize) + "/" + total);
|
||||
List<Long> contentIds = this.contentService.dao()
|
||||
.pageBySiteId(
|
||||
new Page<>(0, pageSize, false),
|
||||
site.getSiteId(),
|
||||
List.of(CmsContent::getContentId)
|
||||
).getRecords().stream().map(CmsContent::getContentId).toList();
|
||||
this.contentService.dao().removeBatchByIds(contentIds);
|
||||
Page<CmsContent> page = this.contentService.dao().lambdaQuery()
|
||||
.select(CmsContent::getContentId)
|
||||
.eq(CmsContent::getSiteId, site.getSiteId())
|
||||
.gt(CmsContent::getContentId, lastId)
|
||||
.orderByAsc(CmsContent::getContentId)
|
||||
.page(Page.of(0, pageSize, false));
|
||||
if (!page.getRecords().isEmpty()) {
|
||||
List<Long> contentIds = page.getRecords().stream().map(CmsContent::getContentId).toList();
|
||||
this.contentService.dao().removeBatchByIds(contentIds);
|
||||
lastId = contentIds.get(contentIds.size() - 1);
|
||||
}
|
||||
}
|
||||
// 删除备份内容数据
|
||||
total = this.contentService.dao().countBackupBySiteId(site.getSiteId());
|
||||
lastId = 0;
|
||||
for (long i = 0; i * pageSize < total; i++) {
|
||||
AsyncTaskManager.setTaskProgressInfo((int) (i * pageSize * 100 / total), "正在删除内容备份数据:" + (i * pageSize) + "/" + total);
|
||||
List<Long> backupIds = this.contentService.dao()
|
||||
.pageBackupBySiteId(
|
||||
new Page<>(0, pageSize, false),
|
||||
site.getSiteId(),
|
||||
List.of(BCmsContent::getContentId)
|
||||
).getRecords().stream().map(BCmsContent::getBackupId).toList();
|
||||
this.contentService.dao().removeBackupBatchByIds(backupIds);
|
||||
Page<BCmsContent> page = this.contentService.dao().getBackupMapper()
|
||||
.selectPage(Page.of(0, pageSize, false), new LambdaQueryWrapper<BCmsContent>()
|
||||
.select(BCmsContent::getBackupId)
|
||||
.eq(BCmsContent::getSiteId, site.getSiteId())
|
||||
.gt(BCmsContent::getBackupId, lastId)
|
||||
.orderByAsc(BCmsContent::getBackupId));
|
||||
if (!page.getRecords().isEmpty()) {
|
||||
List<Long> backupIds = page.getRecords().stream().map(BCmsContent::getBackupId).toList();
|
||||
this.contentService.dao().removeBackupBatchByIds(backupIds);
|
||||
lastId = backupIds.get(backupIds.size() - 1);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
AsyncTaskManager.addErrMessage("删除内容错误:" + e.getMessage());
|
||||
@ -104,10 +112,20 @@ public class ContentCoreListener {
|
||||
try {
|
||||
long total = this.resourceService
|
||||
.count(new LambdaQueryWrapper<CmsResource>().eq(CmsResource::getSiteId, site.getSiteId()));
|
||||
long lastId = 0;
|
||||
for (long i = 0; i * pageSize < total; i++) {
|
||||
AsyncTaskManager.setTaskProgressInfo((int) (i * pageSize * 100 / total), "正在删除资源数据:" + (i * pageSize) + "/" + total);
|
||||
this.resourceService.remove(new LambdaQueryWrapper<CmsResource>()
|
||||
.eq(CmsResource::getSiteId, site.getSiteId()).last("limit " + pageSize));
|
||||
Page<CmsResource> resources = this.resourceService.lambdaQuery()
|
||||
.select(CmsResource::getResourceId)
|
||||
.eq(CmsResource::getSiteId, site.getSiteId())
|
||||
.gt(CmsResource::getResourceId, lastId)
|
||||
.orderByAsc(CmsResource::getResourceId)
|
||||
.page(Page.of(0, pageSize, false));
|
||||
if (!resources.getRecords().isEmpty()) {
|
||||
List<Long> resourceIds = resources.getRecords().stream().map(CmsResource::getResourceId).toList();
|
||||
this.resourceService.removeBatchByIds(resourceIds);
|
||||
lastId = resourceIds.get(resourceIds.size() - 1);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
AsyncTaskManager.addErrMessage("删除资源数据错误:" + e.getMessage());
|
||||
@ -117,10 +135,20 @@ public class ContentCoreListener {
|
||||
try {
|
||||
long total = this.catalogService
|
||||
.count(new LambdaQueryWrapper<CmsCatalog>().eq(CmsCatalog::getSiteId, site.getSiteId()));
|
||||
long lastId = 0;
|
||||
for (long i = 0; i * pageSize < total; i++) {
|
||||
AsyncTaskManager.setTaskProgressInfo((int) (i * pageSize * 100 / total), "正在删除栏目数据:" + (i * pageSize) + "/" + total);
|
||||
this.catalogService.remove(new LambdaQueryWrapper<CmsCatalog>()
|
||||
.eq(CmsCatalog::getSiteId, site.getSiteId()).last("limit " + pageSize));
|
||||
Page<CmsCatalog> catalogs = this.catalogService.lambdaQuery()
|
||||
.select(CmsCatalog::getCatalogId)
|
||||
.eq(CmsCatalog::getSiteId, site.getSiteId())
|
||||
.gt(CmsCatalog::getCatalogId, lastId)
|
||||
.orderByAsc(CmsCatalog::getCatalogId)
|
||||
.page(Page.of(0, pageSize, false));
|
||||
if (!catalogs.getRecords().isEmpty()) {
|
||||
List<Long> catalogIds = catalogs.getRecords().stream().map(CmsCatalog::getCatalogId).toList();
|
||||
this.catalogService.removeBatchByIds(catalogIds);
|
||||
lastId = catalogIds.get(catalogIds.size() - 1);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
AsyncTaskManager.addErrMessage("删除栏目数据错误:" + e.getMessage());
|
||||
@ -130,10 +158,20 @@ public class ContentCoreListener {
|
||||
try {
|
||||
long total = this.sitePropertyService
|
||||
.count(new LambdaQueryWrapper<CmsSiteProperty>().eq(CmsSiteProperty::getSiteId, site.getSiteId()));
|
||||
long lastId = 0;
|
||||
for (long i = 0; i * pageSize < total; i++) {
|
||||
AsyncTaskManager.setTaskProgressInfo((int) (i * pageSize * 100 / total), "正在删除站点扩展属性数据:" + (i * pageSize) + "/" + total);
|
||||
this.sitePropertyService.remove(new LambdaQueryWrapper<CmsSiteProperty>()
|
||||
.eq(CmsSiteProperty::getSiteId, site.getSiteId()).last("limit " + pageSize));
|
||||
Page<CmsSiteProperty> siteProperties = this.sitePropertyService.lambdaQuery()
|
||||
.select(CmsSiteProperty::getPropertyId)
|
||||
.eq(CmsSiteProperty::getSiteId, site.getSiteId())
|
||||
.gt(CmsSiteProperty::getPropertyId, lastId)
|
||||
.orderByAsc(CmsSiteProperty::getPropertyId)
|
||||
.page(Page.of(0, pageSize, false));
|
||||
if (!siteProperties.getRecords().isEmpty()) {
|
||||
List<Long> ids = siteProperties.getRecords().stream().map(CmsSiteProperty::getPropertyId).toList();
|
||||
this.sitePropertyService.removeBatchByIds(ids);
|
||||
lastId = ids.get(ids.size() - 1);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
AsyncTaskManager.addErrMessage("删除站点扩展属性错误:" + e.getMessage());
|
||||
@ -143,10 +181,20 @@ public class ContentCoreListener {
|
||||
try {
|
||||
long total = this.templateService
|
||||
.count(new LambdaQueryWrapper<CmsTemplate>().eq(CmsTemplate::getSiteId, site.getSiteId()));
|
||||
long lastId = 0;
|
||||
for (long i = 0; i * pageSize < total; i++) {
|
||||
AsyncTaskManager.setTaskProgressInfo((int) (i * pageSize * 100 / total), "正在删除模板数据:" + (i * pageSize) + "/" + total);
|
||||
this.templateService.remove(new LambdaQueryWrapper<CmsTemplate>()
|
||||
.eq(CmsTemplate::getSiteId, site.getSiteId()).last("limit " + pageSize));
|
||||
Page<CmsTemplate> templates = this.templateService.lambdaQuery()
|
||||
.select(CmsTemplate::getTemplateId)
|
||||
.eq(CmsTemplate::getSiteId, site.getSiteId())
|
||||
.gt(CmsTemplate::getTemplateId, lastId)
|
||||
.orderByAsc(CmsTemplate::getTemplateId)
|
||||
.page(Page.of(0, pageSize, false));
|
||||
if (!templates.getRecords().isEmpty()) {
|
||||
List<Long> ids = templates.getRecords().stream().map(CmsTemplate::getTemplateId).toList();
|
||||
this.templateService.removeBatchByIds(ids);
|
||||
lastId = ids.get(ids.size() - 1);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
AsyncTaskManager.addErrMessage("删除模板数据错误:" + e.getMessage());
|
||||
@ -156,10 +204,21 @@ public class ContentCoreListener {
|
||||
try {
|
||||
long total = this.contentRelaService
|
||||
.count(new LambdaQueryWrapper<CmsContentRela>().eq(CmsContentRela::getSiteId, site.getSiteId()));
|
||||
long lastId = 0;
|
||||
for (long i = 0; i * pageSize < total; i++) {
|
||||
AsyncTaskManager.setTaskProgressInfo((int) (i * pageSize * 100 / total), "正在内容关联表数据:" + (i * pageSize) + "/" + total);
|
||||
this.contentRelaService.remove(new LambdaQueryWrapper<CmsContentRela>()
|
||||
.eq(CmsContentRela::getSiteId, site.getSiteId()).last("limit " + pageSize));
|
||||
AsyncTaskManager.setTaskProgressInfo((int) (i * pageSize * 100 / total),
|
||||
"正在内容关联表数据:" + (i * pageSize) + "/" + total);
|
||||
Page<CmsContentRela> templates = this.contentRelaService.lambdaQuery()
|
||||
.select(CmsContentRela::getRelaContentId)
|
||||
.eq(CmsContentRela::getSiteId, site.getSiteId())
|
||||
.gt(CmsContentRela::getRelaContentId, lastId)
|
||||
.orderByAsc(CmsContentRela::getRelaContentId)
|
||||
.page(Page.of(0, pageSize, false));
|
||||
if (!templates.getRecords().isEmpty()) {
|
||||
List<Long> ids = templates.getRecords().stream().map(CmsContentRela::getRelaContentId).toList();
|
||||
this.contentRelaService.removeBatchByIds(ids);
|
||||
lastId = ids.get(ids.size() - 1);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
AsyncTaskManager.addErrMessage("删除内容关联表数据错误:" + e.getMessage());
|
||||
|
||||
@ -17,6 +17,7 @@ package com.chestnut.contentcore.service;
|
||||
|
||||
import com.chestnut.common.async.AsyncTask;
|
||||
import com.chestnut.common.security.domain.LoginUser;
|
||||
import com.chestnut.common.security.domain.Operator;
|
||||
import com.chestnut.contentcore.core.IContent;
|
||||
import com.chestnut.contentcore.core.IInternalDataType;
|
||||
import com.chestnut.contentcore.core.IPageWidget;
|
||||
@ -27,6 +28,7 @@ import com.chestnut.contentcore.domain.CmsSite;
|
||||
import freemarker.template.TemplateException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.List;
|
||||
|
||||
public interface IPublishService {
|
||||
@ -50,7 +52,7 @@ public interface IPublishService {
|
||||
* @param contentStatus 内容状态
|
||||
* @return 结果
|
||||
*/
|
||||
AsyncTask publishAll(CmsSite site, final String contentStatus, final LoginUser operator);
|
||||
AsyncTask publishAll(CmsSite site, final String contentStatus, final Operator operator);
|
||||
|
||||
/**
|
||||
* 站点首页页面内容
|
||||
@ -64,6 +66,8 @@ public interface IPublishService {
|
||||
String getSitePageData(CmsSite site, IInternalDataType.RequestData requestData)
|
||||
throws IOException, TemplateException;
|
||||
|
||||
void processSitePage(CmsSite site, IInternalDataType.RequestData requestData, Writer writer) throws TemplateException, IOException;
|
||||
|
||||
/**
|
||||
* 获取栏目模板页面内容
|
||||
*
|
||||
@ -77,6 +81,9 @@ public interface IPublishService {
|
||||
String getCatalogPageData(CmsCatalog catalog, IInternalDataType.RequestData requestData, boolean listFlag)
|
||||
throws IOException, TemplateException;
|
||||
|
||||
void processCatalogPage(CmsCatalog catalog, IInternalDataType.RequestData requestData, boolean listFlag, Writer writer)
|
||||
throws IOException, TemplateException;
|
||||
|
||||
/**
|
||||
* 发布栏目,异步任务
|
||||
*
|
||||
@ -87,7 +94,7 @@ public interface IPublishService {
|
||||
* @return 结果
|
||||
*/
|
||||
AsyncTask publishCatalog(CmsCatalog catalog, boolean publishChild, boolean publishDetail,
|
||||
String publishStatus, final LoginUser operator);
|
||||
String publishStatus, final Operator operator);
|
||||
|
||||
/**
|
||||
* 获取内容模板页面结果
|
||||
@ -108,6 +115,9 @@ public interface IPublishService {
|
||||
*/
|
||||
void asyncStaticizeContent(IContent<?> content);
|
||||
|
||||
String processContentPage(CmsContent content, IInternalDataType.RequestData requestData, Writer writer)
|
||||
throws IOException, TemplateException;
|
||||
|
||||
/**
|
||||
* 发布内容
|
||||
*
|
||||
@ -116,7 +126,7 @@ public interface IPublishService {
|
||||
*/
|
||||
AsyncTask publishContents(List<CmsContent> contents, LoginUser operator);
|
||||
|
||||
void publishContent(CmsContent content, LoginUser operator);
|
||||
void publishContent(CmsContent content, Operator operator);
|
||||
|
||||
/**
|
||||
* 获取内容扩展模板解析内容
|
||||
@ -135,13 +145,15 @@ public interface IPublishService {
|
||||
* 获取页面部件模板解析内容
|
||||
*
|
||||
* @param pageWidget 页面部件
|
||||
* @param publishPipeCode 发布通道编码
|
||||
* @param isPreview 是否预览
|
||||
* @param data 请求数据
|
||||
* @return 结果
|
||||
* @throws IOException e1
|
||||
* @throws TemplateException e2
|
||||
*/
|
||||
String getPageWidgetPageData(CmsPageWidget pageWidget, String publishPipeCode, boolean isPreview) throws IOException, TemplateException;
|
||||
String getPageWidgetPageData(CmsPageWidget pageWidget, IInternalDataType.RequestData data) throws IOException, TemplateException;
|
||||
|
||||
void processPageWidget(CmsPageWidget pageWidget, IInternalDataType.RequestData data, Writer writer)
|
||||
throws IOException, TemplateException;
|
||||
|
||||
/**
|
||||
* 页面部件静态化
|
||||
|
||||
@ -277,6 +277,7 @@ public class CatalogServiceImpl extends ServiceImpl<CmsCatalogMapper, CmsCatalog
|
||||
checkRedirectUrl(dto.getCatalogType(), dto.getRedirectUrl());
|
||||
|
||||
String oldPath = catalog.getPath();
|
||||
String oldAlias = catalog.getAlias();
|
||||
BeanUtils.copyProperties(dto, catalog);
|
||||
// 发布通道数据处理
|
||||
Map<String, Map<String, Object>> publishPipeProps = dto.getPublishPipeDatas().stream()
|
||||
@ -285,7 +286,7 @@ public class CatalogServiceImpl extends ServiceImpl<CmsCatalogMapper, CmsCatalog
|
||||
catalog.updateBy(dto.getOperator().getUsername());
|
||||
this.updateById(catalog);
|
||||
|
||||
this.clearCache(catalog);
|
||||
this.clearCache(catalog.getSiteId(), catalog.getCatalogId(), oldAlias);
|
||||
this.applicationContext.publishEvent(new AfterCatalogSaveEvent(this, catalog, oldPath, dto.getParams()));
|
||||
return catalog;
|
||||
}
|
||||
@ -404,7 +405,11 @@ public class CatalogServiceImpl extends ServiceImpl<CmsCatalogMapper, CmsCatalog
|
||||
|
||||
@Override
|
||||
public void clearCache(CmsCatalog catalog) {
|
||||
this.catalogCache.clear(catalog);
|
||||
this.catalogCache.clear(catalog.getSiteId(), catalog.getCatalogId(), catalog.getAlias());
|
||||
}
|
||||
|
||||
private void clearCache(Long siteId, Long catalogId, String alias) {
|
||||
this.catalogCache.clear(siteId, catalogId, alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -21,6 +21,7 @@ import com.chestnut.common.async.AsyncTask;
|
||||
import com.chestnut.common.async.AsyncTaskManager;
|
||||
import com.chestnut.common.exception.CommonErrorCode;
|
||||
import com.chestnut.common.security.domain.LoginUser;
|
||||
import com.chestnut.common.security.domain.Operator;
|
||||
import com.chestnut.common.utils.Assert;
|
||||
import com.chestnut.common.utils.SpringUtils;
|
||||
import com.chestnut.common.utils.StringUtils;
|
||||
@ -40,6 +41,7 @@ import com.chestnut.contentcore.exception.ContentCoreErrorCode;
|
||||
import com.chestnut.contentcore.fixed.dict.ContentOpType;
|
||||
import com.chestnut.contentcore.fixed.dict.ContentStatus;
|
||||
import com.chestnut.contentcore.listener.event.*;
|
||||
import com.chestnut.contentcore.perms.CatalogPermissionType;
|
||||
import com.chestnut.contentcore.perms.CatalogPermissionType.CatalogPrivItem;
|
||||
import com.chestnut.contentcore.properties.RepeatTitleCheckProperty;
|
||||
import com.chestnut.contentcore.publish.IContentPathRule;
|
||||
@ -104,20 +106,16 @@ public class ContentServiceImpl implements IContentService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteContent(CmsContent cmsContent, LoginUser operator, Map<String, Object> params) {
|
||||
public void deleteContent(CmsContent cmsContent, LoginUser loginUser, Map<String, Object> params) {
|
||||
boolean canDelete = ContentStatus.isDraft(cmsContent.getStatus()) || ContentStatus.isOffline(cmsContent.getStatus());
|
||||
Assert.isTrue(canDelete, ContentCoreErrorCode.DEL_CONTENT_ERR::exception);
|
||||
|
||||
IContentType contentType = ContentCoreUtils.getContentType(cmsContent.getContentType());
|
||||
IContent<?> content = contentType.loadContent(cmsContent);
|
||||
content.setOperator(operator);
|
||||
content.setOperator(Operator.of(loginUser));
|
||||
content.setParams(params);
|
||||
transactionTemplate.executeWithoutResult(transactionStatus -> deleteContent0(content));
|
||||
SpringUtils.publishEvent(new AfterContentDeleteEvent(this, content));
|
||||
}
|
||||
|
||||
private void deleteContent0(IContent<?> content) {
|
||||
content.delete();
|
||||
// 删除映射内容
|
||||
List<CmsContent> mappingList = this.dao().lambdaQuery()
|
||||
.eq(CmsContent::getCopyType, ContentCopyType.Mapping)
|
||||
@ -126,15 +124,21 @@ public class ContentServiceImpl implements IContentService {
|
||||
for (CmsContent mappingContent : mappingList) {
|
||||
log.debug("CC.Content[{}].delete: mapping content delete", content.getContentEntity().getContentId());
|
||||
try {
|
||||
deleteContent(mappingContent, content.getOperator(), Map.of(
|
||||
IContent.PARAM_IS_DELETE_BY_CATALOG, content.getParams().get(IContent.PARAM_IS_DELETE_BY_CATALOG)
|
||||
));
|
||||
IContentType mappingContentType = ContentCoreUtils.getContentType(cmsContent.getContentType());
|
||||
IContent<?> mappingIContent = mappingContentType.loadContent(cmsContent);
|
||||
mappingIContent.setOperator(Operator.of(loginUser));
|
||||
mappingIContent.setParams(params);
|
||||
transactionTemplate.executeWithoutResult(transactionStatus -> deleteContent0(mappingIContent));
|
||||
SpringUtils.publishEvent(new AfterContentDeleteEvent(this, mappingIContent));
|
||||
} catch (Exception e) {
|
||||
AsyncTaskManager.setTaskTenPercentProgressInfo(ContentTips.DELETING_MAPPING_CONTENT.locale(
|
||||
mappingContent.getTitle(), mappingContent.getContentId()));
|
||||
}
|
||||
}
|
||||
// 删除相关内容
|
||||
}
|
||||
|
||||
private void deleteContent0(IContent<?> content) {
|
||||
content.delete();
|
||||
contentRelaService.onContentDelete(content.getContentEntity().getContentId());
|
||||
// TODO 删除内容历史版本?
|
||||
}
|
||||
@ -170,13 +174,13 @@ public class ContentServiceImpl implements IContentService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteContentsByCatalog(CmsCatalog catalog, boolean includeChild, LoginUser operator) {
|
||||
public void deleteContentsByCatalog(CmsCatalog catalog, boolean includeChild, LoginUser loginUser) {
|
||||
long pageSize = 100;
|
||||
long total = this.dao().lambdaQuery()
|
||||
.eq(!includeChild, CmsContent::getCatalogId, catalog.getCatalogId())
|
||||
.likeRight(includeChild, CmsContent::getCatalogAncestors, catalog.getAncestors())
|
||||
.count();
|
||||
|
||||
Operator operator = Operator.of(loginUser);
|
||||
for (int i = 0; i * pageSize < total; i++) {
|
||||
AsyncTaskManager.setTaskProgressInfo((int) (i * pageSize / total),
|
||||
"正在栏目删除内容:" + (i * pageSize) + " / " + total);
|
||||
@ -307,6 +311,8 @@ public class ContentServiceImpl implements IContentService {
|
||||
CmsContent cmsContent = dao().getById(contentId);
|
||||
if (Objects.nonNull(cmsContent)) {
|
||||
for (CmsCatalog catalog : catalogs) {
|
||||
// 校验权限
|
||||
PermissionUtils.checkPermission(CatalogPermissionType.CatalogPrivItem.AddContent.getPermissionKey(catalog.getCatalogId()), dto.getOperator());
|
||||
CmsContent copyContent = copy0(cmsContent, catalog, dto.getCopyType(), dto.getOperator());
|
||||
SpringUtils.publishEvent(new AfterContentCopyEvent(this, cmsContent, copyContent));
|
||||
}
|
||||
@ -321,12 +327,12 @@ public class ContentServiceImpl implements IContentService {
|
||||
|
||||
}
|
||||
|
||||
private CmsContent copy0(CmsContent cmsContent, CmsCatalog toCatalog, Integer copyType, LoginUser operator) {
|
||||
private CmsContent copy0(CmsContent cmsContent, CmsCatalog toCatalog, Integer copyType, LoginUser loginUser) {
|
||||
AsyncTaskManager.setTaskTenPercentProgressInfo(ContentTips.COPYING_CONTENT.locale(AsyncTaskManager.getLocale(),
|
||||
cmsContent.getTitle(), toCatalog.getName()));
|
||||
IContentType ct = ContentCoreUtils.getContentType(cmsContent.getContentType());
|
||||
IContent<?> content = ct.loadContent(cmsContent);
|
||||
content.setOperator(operator);
|
||||
content.setOperator(Operator.of(loginUser));
|
||||
return transactionTemplate.execute(transactionStatus -> content.copyTo(toCatalog, copyType));
|
||||
}
|
||||
|
||||
@ -357,7 +363,9 @@ public class ContentServiceImpl implements IContentService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveContent(CmsContent cmsContent, CmsCatalog toCatalog, LoginUser operator) {
|
||||
public void moveContent(CmsContent cmsContent, CmsCatalog toCatalog, LoginUser loginUser) {
|
||||
// 校验权限
|
||||
PermissionUtils.checkPermission(CatalogPermissionType.CatalogPrivItem.AddContent.getPermissionKey(toCatalog.getCatalogId()), loginUser);
|
||||
if (cmsContent.getCatalogId().equals(toCatalog.getCatalogId())) {
|
||||
log.warn("Cannot move content to source catalog!");
|
||||
return;
|
||||
@ -366,7 +374,7 @@ public class ContentServiceImpl implements IContentService {
|
||||
cmsContent.getTitle(), toCatalog.getName()));
|
||||
IContentType ct = ContentCoreUtils.getContentType(cmsContent.getContentType());
|
||||
IContent<?> content = ct.loadContent(cmsContent);
|
||||
content.setOperator(operator);
|
||||
content.setOperator(Operator.of(loginUser));
|
||||
transactionTemplate.executeWithoutResult(transactionStatus -> content.moveTo(toCatalog));
|
||||
}
|
||||
|
||||
@ -376,7 +384,7 @@ public class ContentServiceImpl implements IContentService {
|
||||
for (CmsContent c : contents) {
|
||||
IContentType ct = ContentCoreUtils.getContentType(c.getContentType());
|
||||
IContent<?> content = ct.loadContent(c);
|
||||
content.setOperator(dto.getOperator());
|
||||
content.setOperator(Operator.of(dto.getOperator()));
|
||||
transactionTemplate.executeWithoutResult(transactionStatus -> content.setTop(dto.getTopEndTime()));
|
||||
SpringUtils.publishEvent(new AfterContentTopSetEvent(this, content));
|
||||
}
|
||||
@ -391,7 +399,7 @@ public class ContentServiceImpl implements IContentService {
|
||||
for (CmsContent c : contents) {
|
||||
IContentType ct = ContentCoreUtils.getContentType(c.getContentType());
|
||||
IContent<?> content = ct.loadContent(c);
|
||||
content.setOperator(operator);
|
||||
content.setOperator(Operator.of(operator));
|
||||
transactionTemplate.executeWithoutResult(transactionStatus -> content.cancelTop());
|
||||
SpringUtils.publishEvent(new AfterContentTopCancelEvent(this, content));
|
||||
}
|
||||
@ -420,11 +428,11 @@ public class ContentServiceImpl implements IContentService {
|
||||
offline0(cmsContent, operator, LocaleContextHolder.getLocale());
|
||||
}
|
||||
|
||||
private void offline0(CmsContent cmsContent, LoginUser operator, Locale locale) {
|
||||
private void offline0(CmsContent cmsContent, LoginUser loginUser, Locale locale) {
|
||||
AsyncTaskManager.setTaskTenPercentProgressInfo(ContentTips.OFFLINE_CONTENT.locale(locale, cmsContent.getTitle()));
|
||||
IContentType ct = ContentCoreUtils.getContentType(cmsContent.getContentType());
|
||||
IContent<?> content = ct.loadContent(cmsContent);
|
||||
content.setOperator(operator);
|
||||
content.setOperator(Operator.of(loginUser));
|
||||
transactionTemplate.executeWithoutResult(transactionStatus -> content.offline());
|
||||
// 映射关联内容同步下线
|
||||
if (!cmsContent.isLinkContent() && !ContentCopyType.isMapping(cmsContent.getCopyType())) {
|
||||
@ -435,7 +443,7 @@ public class ContentServiceImpl implements IContentService {
|
||||
for (CmsContent c : mappingList) {
|
||||
log.debug("CC.Content[{}].offline: mapping content offline", cmsContent.getContentId());
|
||||
AsyncTaskManager.setTaskTenPercentProgressInfo(ContentTips.OFFLINE_MAPPING_CONTENT.locale(locale, c.getTitle()));
|
||||
offline0(c, operator, locale);
|
||||
offline0(c, loginUser, locale);
|
||||
}
|
||||
}
|
||||
SpringUtils.publishEvent(new AfterContentOfflineEvent(this, content));
|
||||
@ -447,7 +455,7 @@ public class ContentServiceImpl implements IContentService {
|
||||
CmsContent c = this.dao().getById(dto.getContentId());
|
||||
IContentType ct = ContentCoreUtils.getContentType(c.getContentType());
|
||||
IContent<?> content = ct.loadContent(c);
|
||||
content.setOperator(dto.getOperator());
|
||||
content.setOperator(Operator.of(dto.getOperator()));
|
||||
content.sort(dto.getTargetContentId());
|
||||
}
|
||||
|
||||
@ -460,10 +468,10 @@ public class ContentServiceImpl implements IContentService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toPublish(CmsContent cmsContent, LoginUser operator) {
|
||||
public void toPublish(CmsContent cmsContent, LoginUser loginUser) {
|
||||
IContentType ct = ContentCoreUtils.getContentType(cmsContent.getContentType());
|
||||
IContent<?> content = ct.loadContent(cmsContent);
|
||||
content.setOperator(operator);
|
||||
content.setOperator(Operator.of(loginUser));
|
||||
transactionTemplate.executeWithoutResult(transactionStatus -> content.toPublish());
|
||||
SpringUtils.publishEvent(new AfterContentToPublishEvent(this, content));
|
||||
}
|
||||
|
||||
@ -15,12 +15,12 @@
|
||||
*/
|
||||
package com.chestnut.contentcore.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.chestnut.common.async.AsyncTaskManager;
|
||||
import com.chestnut.common.exception.CommonErrorCode;
|
||||
import com.chestnut.common.security.domain.LoginUser;
|
||||
import com.chestnut.common.utils.Assert;
|
||||
import com.chestnut.common.utils.IdUtils;
|
||||
import com.chestnut.contentcore.cache.PageWidgetMonitoredCache;
|
||||
import com.chestnut.contentcore.core.IPageWidget;
|
||||
import com.chestnut.contentcore.core.IPageWidgetType;
|
||||
@ -76,11 +76,10 @@ public class PageWidgetServiceImpl extends ServiceImpl<CmsPageWidgetMapper, CmsP
|
||||
|
||||
@Override
|
||||
public boolean checkCodeUnique(Long siteId, String code, Long pageWidgetId) {
|
||||
LambdaQueryWrapper<CmsPageWidget> q = new LambdaQueryWrapper<CmsPageWidget>().eq(CmsPageWidget::getCode, code)
|
||||
return this.lambdaQuery().eq(CmsPageWidget::getCode, code)
|
||||
.eq(CmsPageWidget::getSiteId, siteId)
|
||||
.ne(pageWidgetId != null && pageWidgetId > 0, CmsPageWidget::getPageWidgetId, pageWidgetId)
|
||||
.last("limit 1");
|
||||
return this.count(q) == 0;
|
||||
.ne(IdUtils.validate(pageWidgetId), CmsPageWidget::getPageWidgetId, pageWidgetId)
|
||||
.count() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -20,6 +20,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.chestnut.common.async.AsyncTask;
|
||||
import com.chestnut.common.async.AsyncTaskManager;
|
||||
import com.chestnut.common.security.domain.LoginUser;
|
||||
import com.chestnut.common.security.domain.Operator;
|
||||
import com.chestnut.common.staticize.StaticizeService;
|
||||
import com.chestnut.common.staticize.core.TemplateContext;
|
||||
import com.chestnut.common.utils.Assert;
|
||||
@ -61,6 +62,7 @@ import org.springframework.transaction.support.TransactionTemplate;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@ -92,6 +94,14 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
|
||||
@Override
|
||||
public String getSitePageData(CmsSite site, IInternalDataType.RequestData requestData)
|
||||
throws IOException, TemplateException {
|
||||
try (StringWriter writer = new StringWriter()) {
|
||||
processSitePage(site, requestData, writer);
|
||||
return writer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processSitePage(CmsSite site, IInternalDataType.RequestData requestData, Writer writer) throws TemplateException, IOException {
|
||||
String indexTemplate = site.getIndexTemplate(requestData.getPublishPipeCode());
|
||||
File templateFile = this.templateService.findTemplateFile(site, indexTemplate, requestData.getPublishPipeCode());
|
||||
if (Objects.isNull(templateFile)) {
|
||||
@ -108,9 +118,8 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
|
||||
templateType.initTemplateData(site.getSiteId(), context);
|
||||
|
||||
long s = System.currentTimeMillis();
|
||||
try (StringWriter writer = new StringWriter()) {
|
||||
try {
|
||||
this.staticizeService.process(context, writer);
|
||||
return writer.toString();
|
||||
} finally {
|
||||
logger.debug("[{}]Parse index template: {}\t, cost: {}ms", requestData.getPublishPipeCode(), site.getName(), System.currentTimeMillis() - s);
|
||||
}
|
||||
@ -126,7 +135,7 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncTask publishAll(CmsSite site, final String contentStatus, final LoginUser operator) {
|
||||
public AsyncTask publishAll(CmsSite site, final String contentStatus, final Operator operator) {
|
||||
AsyncTask asyncTask = new AsyncTask() {
|
||||
|
||||
@Override
|
||||
@ -162,7 +171,7 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
|
||||
content.setContentEntity(xContent);
|
||||
content.setOperator(operator);
|
||||
Boolean published = transactionTemplate.execute(callback -> content.publish());
|
||||
if (published) {
|
||||
if (Boolean.TRUE.equals(published)) {
|
||||
applicationContext.publishEvent(new AfterContentPublishEvent(contentType, content));
|
||||
}
|
||||
this.checkInterrupt();
|
||||
@ -200,6 +209,15 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
|
||||
@Override
|
||||
public String getCatalogPageData(CmsCatalog catalog, IInternalDataType.RequestData requestData, boolean listFlag)
|
||||
throws IOException, TemplateException {
|
||||
try (StringWriter writer = new StringWriter()) {
|
||||
this.processCatalogPage(catalog, requestData, listFlag, writer);
|
||||
return writer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processCatalogPage(CmsCatalog catalog, IInternalDataType.RequestData requestData, boolean listFlag, Writer writer)
|
||||
throws IOException, TemplateException {
|
||||
if (CatalogType_Link.ID.equals(catalog.getCatalogType())) {
|
||||
throw new RuntimeException("链接类型栏目无独立页面:" + catalog.getName());
|
||||
}
|
||||
@ -240,9 +258,8 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
|
||||
templateContext.setFirstFileName(catalogLink);
|
||||
templateContext.setOtherFileName(TemplateUtils.appendPageIndexParam(catalogLink, TemplateContext.PlaceHolder_PageNo));
|
||||
}
|
||||
try (StringWriter writer = new StringWriter()) {
|
||||
try {
|
||||
this.staticizeService.process(templateContext, writer);
|
||||
return writer.toString();
|
||||
} finally {
|
||||
logger.debug("[{}]栏目页模板解析:{},耗时:{}ms", requestData.getPublishPipeCode(), catalog.getName(),
|
||||
(System.currentTimeMillis() - s));
|
||||
@ -251,7 +268,7 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
|
||||
|
||||
@Override
|
||||
public AsyncTask publishCatalog(CmsCatalog catalog, boolean publishChild, boolean publishDetail,
|
||||
final String publishStatus, final LoginUser operator) {
|
||||
final String publishStatus, final Operator operator) {
|
||||
List<CmsPublishPipe> publishPipes = publishPipeService.getPublishPipes(catalog.getSiteId());
|
||||
Assert.isTrue(!publishPipes.isEmpty(), ContentCoreErrorCode.NO_PUBLISHPIPE::exception);
|
||||
|
||||
@ -296,7 +313,7 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
|
||||
content.setContentEntity(xContent);
|
||||
content.setOperator(operator);
|
||||
Boolean published = transactionTemplate.execute(callback -> content.publish());
|
||||
if (published) {
|
||||
if (Boolean.TRUE.equals(published)) {
|
||||
applicationContext.publishEvent(new AfterContentPublishEvent(contentType, content));
|
||||
}
|
||||
this.checkInterrupt();
|
||||
@ -386,23 +403,64 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
|
||||
templateContext.setFirstFileName(contentLink);
|
||||
templateContext.setOtherFileName(TemplateUtils.appendPageIndexParam(contentLink, TemplateContext.PlaceHolder_PageNo));
|
||||
// staticize
|
||||
this.staticizeService.process(templateContext, writer);
|
||||
this.processContentPage(content, requestData, writer);
|
||||
logger.debug("[{}][{}]内容模板解析:{},耗时:{}", requestData.getPublishPipeCode(), contentType.getId(), content.getTitle(),
|
||||
System.currentTimeMillis() - s);
|
||||
return writer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String processContentPage(CmsContent content, IInternalDataType.RequestData requestData, Writer writer)
|
||||
throws IOException, TemplateException {
|
||||
CmsSite site = this.siteService.getById(content.getSiteId());
|
||||
CmsCatalog catalog = this.catalogService.getCatalog(content.getCatalogId());
|
||||
if (content.isLinkContent()) {
|
||||
throw new RuntimeException("标题内容:" + content.getTitle() + ",跳转链接:" + content.getRedirectUrl());
|
||||
}
|
||||
// 查找模板
|
||||
final String detailTemplate = getDetailTemplate(site, catalog, content, requestData.getPublishPipeCode());
|
||||
File templateFile = this.templateService.findTemplateFile(site, detailTemplate, requestData.getPublishPipeCode());
|
||||
Assert.notNull(templateFile,
|
||||
() -> ContentCoreErrorCode.TEMPLATE_EMPTY.exception(requestData.getPublishPipeCode(), detailTemplate));
|
||||
|
||||
IContentType contentType = ContentCoreUtils.getContentType(content.getContentType());
|
||||
long s = System.currentTimeMillis();
|
||||
// 生成静态页面
|
||||
try {
|
||||
// 模板ID = 通道:站点目录:模板文件名
|
||||
String templateKey = SiteUtils.getTemplateKey(site, requestData.getPublishPipeCode(), detailTemplate);
|
||||
TemplateContext templateContext = new TemplateContext(templateKey, requestData.isPreview(), requestData.getPublishPipeCode());
|
||||
templateContext.setPageIndex(requestData.getPageIndex());
|
||||
templateContext.getVariables().put(TemplateUtils.TemplateVariable_Request, Objects.requireNonNullElse(requestData.getParams(), Map.of()));
|
||||
// init template datamode
|
||||
TemplateUtils.initGlobalVariables(site, templateContext);
|
||||
// init templateType data to datamode
|
||||
ITemplateType templateType = this.templateService.getTemplateType(ContentTemplateType.TypeId);
|
||||
templateType.initTemplateData(content.getContentId(), templateContext);
|
||||
// 分页链接
|
||||
String contentLink = this.contentService.getContentLink(content, 1, requestData.getPublishPipeCode(), requestData.isPreview());
|
||||
templateContext.setFirstFileName(contentLink);
|
||||
templateContext.setOtherFileName(TemplateUtils.appendPageIndexParam(contentLink, TemplateContext.PlaceHolder_PageNo));
|
||||
// staticize
|
||||
this.staticizeService.process(templateContext, writer);
|
||||
return writer.toString();
|
||||
} finally {
|
||||
logger.debug("[{}][{}]内容模板解析:{},耗时:{}", requestData.getPublishPipeCode(), contentType.getId(), content.getTitle(),
|
||||
System.currentTimeMillis() - s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 内容发布
|
||||
*/
|
||||
@Override
|
||||
public AsyncTask publishContents(List<CmsContent> contents, LoginUser operator) {
|
||||
public AsyncTask publishContents(List<CmsContent> contents, LoginUser loginUser) {
|
||||
Locale locale = LocaleContextHolder.getLocale();
|
||||
AsyncTask task = new AsyncTask() {
|
||||
@Override
|
||||
public void run0() {
|
||||
publishContents0(contents, operator, locale);
|
||||
publishContents0(contents, Operator.of(loginUser), locale);
|
||||
}
|
||||
};
|
||||
task.setType("PublishContents");
|
||||
@ -411,11 +469,11 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishContent(CmsContent content, LoginUser operator) {
|
||||
public void publishContent(CmsContent content, Operator operator) {
|
||||
publishContents0(List.of(content), operator, null);
|
||||
}
|
||||
|
||||
private void publishContents0(List<CmsContent> contents, LoginUser operator, Locale locale) {
|
||||
private void publishContents0(List<CmsContent> contents, Operator operator, Locale locale) {
|
||||
if (contents.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@ -427,7 +485,7 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
|
||||
IContent<?> content = contentType.loadContent(cmsContent);
|
||||
content.setOperator(operator);
|
||||
Boolean published = transactionTemplate.execute(callback -> content.publish());
|
||||
if (published) {
|
||||
if (Boolean.TRUE.equals(published)) {
|
||||
applicationContext.publishEvent(new AfterContentPublishEvent(contentType, content));
|
||||
}
|
||||
catalogIds.add(cmsContent.getCatalogId());
|
||||
@ -517,20 +575,29 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPageWidgetPageData(CmsPageWidget pageWidget, String publishPipeCode, boolean isPreview)
|
||||
public String getPageWidgetPageData(CmsPageWidget pageWidget, IInternalDataType.RequestData data)
|
||||
throws IOException, TemplateException {
|
||||
try (StringWriter writer = new StringWriter()) {
|
||||
processPageWidget(pageWidget, data, writer);
|
||||
return writer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processPageWidget(CmsPageWidget pageWidget, IInternalDataType.RequestData data, Writer writer)
|
||||
throws IOException, TemplateException {
|
||||
CmsSite site = this.siteService.getById(pageWidget.getSiteId());
|
||||
String template = MapUtils.getString(pageWidget.getTemplates(), publishPipeCode, "");
|
||||
String template = MapUtils.getString(pageWidget.getTemplates(), data.getPublishPipeCode(), "");
|
||||
File templateFile = this.templateService.findTemplateFile(site, template,
|
||||
publishPipeCode);
|
||||
data.getPublishPipeCode());
|
||||
Assert.notNull(templateFile, () -> ContentCoreErrorCode.TEMPLATE_EMPTY.exception(template));
|
||||
|
||||
// 生成静态页面
|
||||
try (StringWriter writer = new StringWriter()) {
|
||||
long s = System.currentTimeMillis();
|
||||
long s = System.currentTimeMillis();
|
||||
try {
|
||||
// 模板ID = 通道:站点目录:模板文件名
|
||||
String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, template);
|
||||
TemplateContext templateContext = new TemplateContext(templateKey, isPreview, publishPipeCode);
|
||||
String templateKey = SiteUtils.getTemplateKey(site, data.getPublishPipeCode(), template);
|
||||
TemplateContext templateContext = new TemplateContext(templateKey, data.isPreview(), data.getPublishPipeCode());
|
||||
// init template global variables
|
||||
TemplateUtils.initGlobalVariables(site, templateContext);
|
||||
templateContext.getVariables().put(TemplateUtils.TemplateVariable_PageWidget, pageWidget);
|
||||
@ -539,9 +606,9 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
|
||||
templateType.initTemplateData(site.getSiteId(), templateContext);
|
||||
// staticize
|
||||
this.staticizeService.process(templateContext, writer);
|
||||
logger.debug("[{}]页面部件【{}#{}】模板解析耗时:{}ms", publishPipeCode, pageWidget.getName(),
|
||||
} finally {
|
||||
logger.debug("[{}]页面部件【{}#{}】模板解析耗时:{}ms", data.getPublishPipeCode(), pageWidget.getName(),
|
||||
pageWidget.getCode(), System.currentTimeMillis() - s);
|
||||
return writer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -15,8 +15,7 @@
|
||||
*/
|
||||
package com.chestnut.contentcore.template.exception;
|
||||
|
||||
import com.chestnut.common.utils.StringUtils;
|
||||
|
||||
import com.chestnut.common.i18n.I18nUtils;
|
||||
import freemarker.core.Environment;
|
||||
import freemarker.template.TemplateException;
|
||||
|
||||
@ -24,7 +23,7 @@ public class CatalogNotFoundException extends TemplateException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public CatalogNotFoundException(String tag, long catalogId, String alias, Environment env) {
|
||||
super(StringUtils.messageFormat("<@{0}>[id: {1}, alias: {2}]", tag, catalogId, alias), env);
|
||||
public CatalogNotFoundException(long catalogId, String alias, Environment env) {
|
||||
super(I18nUtils.parse("FREEMARKER.ERR.CatalogNotFound", env.getLocale(), catalogId, alias), env);
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ public class CmsCatalogTag extends AbstractListTag {
|
||||
}
|
||||
String level = MapUtils.getString(attrs, ATTR_LEVEL);
|
||||
if (!CatalogTagLevel.isRoot(level) && Objects.isNull(catalog)) {
|
||||
throw new CatalogNotFoundException(getTagName(), catalogId, alias, env);
|
||||
throw new CatalogNotFoundException(catalogId, alias, env);
|
||||
}
|
||||
String condition = MapUtils.getString(attrs, TagAttr.AttrName_Condition);
|
||||
|
||||
|
||||
@ -25,10 +25,16 @@ import com.chestnut.common.staticize.tag.TagAttr;
|
||||
import com.chestnut.common.staticize.tag.TagAttrOption;
|
||||
import com.chestnut.common.utils.Assert;
|
||||
import com.chestnut.common.utils.StringUtils;
|
||||
import com.chestnut.contentcore.domain.CmsCatalog;
|
||||
import com.chestnut.contentcore.domain.CmsContent;
|
||||
import com.chestnut.contentcore.domain.vo.TagContentVO;
|
||||
import com.chestnut.contentcore.fixed.dict.ContentAttribute;
|
||||
import com.chestnut.contentcore.fixed.dict.ContentStatus;
|
||||
import com.chestnut.contentcore.service.ICatalogService;
|
||||
import com.chestnut.contentcore.service.IContentService;
|
||||
import com.chestnut.contentcore.template.exception.CatalogNotFoundException;
|
||||
import com.chestnut.contentcore.util.CatalogUtils;
|
||||
import com.chestnut.contentcore.util.TemplateUtils;
|
||||
import freemarker.core.Environment;
|
||||
import freemarker.template.TemplateException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -37,6 +43,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@ -47,35 +54,82 @@ public class CmsContentClosestTag extends AbstractListTag {
|
||||
public final static String DESC = "{FREEMARKER.TAG." + TAG_NAME + ".DESC}";
|
||||
public final static String ATTR_USAGE_CONTENT_ID = "{FREEMARKER.TAG." + TAG_NAME + ".contentId}";
|
||||
public final static String ATTR_USAGE_TYPE = "{FREEMARKER.TAG." + TAG_NAME + ".type}";
|
||||
public final static String ATTR_USAGE_SORT = "{FREEMARKER.TAG." + TAG_NAME + ".sort}";
|
||||
public final static String ATTR_OPTION_TYPE_PREV = "{FREEMARKER.TAG." + TAG_NAME + ".type.Prev}";
|
||||
public final static String ATTR_OPTION_TYPE_NEXT = "{FREEMARKER.TAG." + TAG_NAME + ".type.Next}";
|
||||
|
||||
final static String ATTR_CONTENT_ID = "contentid";
|
||||
|
||||
final static String ATTR_SORT = "sort";
|
||||
|
||||
final static String ATTR_TYPE = "type";
|
||||
public final static String ATTR_CATALOG_ID = "catalogid";
|
||||
public final static String ATTR_CATALOG_ALIAS = "catalogalias";
|
||||
public final static String ATTR_LEVEL = "level";
|
||||
public final static String ATTR_SORT = "sort";
|
||||
public final static String ATTR_HAS_ATTRIBUTE = "hasattribute";
|
||||
public final static String ATTR_NO_ATTRIBUTE = "noattribute";
|
||||
public final static String ATTR_STATUS = "status";
|
||||
public final static String ATTR_TOP_FLAG = "topflag";
|
||||
|
||||
private final ICatalogService catalogService;
|
||||
|
||||
private final IContentService contentService;
|
||||
|
||||
@Override
|
||||
public TagPageData prepareData(Environment env, Map<String, String> attrs, boolean page, int size, int pageIndex) throws TemplateException {
|
||||
boolean isNext = TypeTagAttr.isNext(attrs.get(ATTR_TYPE));
|
||||
String sort = attrs.get(ATTR_SORT);
|
||||
Long contentId = MapUtils.getLong(attrs, ATTR_CONTENT_ID);
|
||||
|
||||
CmsContent content = this.contentService.dao().getById(contentId);
|
||||
Assert.notNull(content, () -> new TemplateException(StringUtils.messageFormat("Tag attr[contentid={0}] data not found.", contentId), env));
|
||||
|
||||
LambdaQueryWrapper<CmsContent> q = new LambdaQueryWrapper<CmsContent>()
|
||||
.eq(CmsContent::getCatalogId, content.getCatalogId())
|
||||
.eq(CmsContent::getStatus, ContentStatus.PUBLISHED);
|
||||
if (CmsContentTag.SortTagAttr.isRecent(sort)) {
|
||||
CmsCatalog catalog = null;
|
||||
long catalogId = MapUtils.getLongValue(attrs, ATTR_CATALOG_ID);
|
||||
if (catalogId > 0) {
|
||||
catalog = this.catalogService.getCatalog(catalogId);
|
||||
}
|
||||
long siteId = TemplateUtils.evalSiteId(env);
|
||||
String alias = MapUtils.getString(attrs, ATTR_CATALOG_ALIAS);
|
||||
if (Objects.isNull(catalog) && StringUtils.isNotEmpty(alias)) {
|
||||
catalog = this.catalogService.getCatalogByAlias(siteId, alias);
|
||||
}
|
||||
String level = MapUtils.getString(attrs, ATTR_LEVEL);
|
||||
if (!CmsContentTag.LevelTagAttr.isRoot(level) && Objects.isNull(catalog)) {
|
||||
throw new CatalogNotFoundException(catalogId, alias, env);
|
||||
}
|
||||
String condition = MapUtils.getString(attrs, TagAttr.AttrName_Condition);
|
||||
String status = MapUtils.getString(attrs, ATTR_STATUS, ContentStatus.PUBLISHED);
|
||||
|
||||
LambdaQueryWrapper<CmsContent> q = new LambdaQueryWrapper<>();
|
||||
q.eq(CmsContent::getSiteId, siteId).eq(!"-1".equals(status), CmsContent::getStatus, status);
|
||||
if (Objects.nonNull(catalog)) {
|
||||
if (CmsContentTag.LevelTagAttr.isCurrent(level)) {
|
||||
q.eq(CmsContent::getCatalogId, catalog.getCatalogId());
|
||||
} else if (CmsContentTag.LevelTagAttr.isChild(level)) {
|
||||
q.likeRight(CmsContent::getCatalogAncestors, catalog.getAncestors() + CatalogUtils.ANCESTORS_SPLITER);
|
||||
} else if (CmsContentTag.LevelTagAttr.isCurrentAndChild(level)) {
|
||||
q.likeRight(CmsContent::getCatalogAncestors, catalog.getAncestors());
|
||||
}
|
||||
}
|
||||
String hasAttribute = MapUtils.getString(attrs, ATTR_HAS_ATTRIBUTE);
|
||||
if (StringUtils.isNotEmpty(hasAttribute)) {
|
||||
int attrTotal = ContentAttribute.convertInt(hasAttribute.split(","));
|
||||
q.apply(attrTotal > 0, "attributes&{0}={1}", attrTotal, attrTotal);
|
||||
}
|
||||
String noAttribute = MapUtils.getString(attrs, ATTR_NO_ATTRIBUTE);
|
||||
if (StringUtils.isNotEmpty(noAttribute)) {
|
||||
String[] contentAttrs = noAttribute.split(",");
|
||||
int attrTotal = ContentAttribute.convertInt(contentAttrs);
|
||||
for (String attr : contentAttrs) {
|
||||
int bit = ContentAttribute.bit(attr);
|
||||
q.apply(bit > 0, "attributes&{0}<>{1}", attrTotal, bit);
|
||||
}
|
||||
}
|
||||
q.apply(StringUtils.isNotEmpty(condition), condition);
|
||||
String sortType = MapUtils.getString(attrs, ATTR_SORT);
|
||||
q.orderByDesc(MapUtils.getBooleanValue(attrs, ATTR_TOP_FLAG, true), CmsContent::getTopFlag);
|
||||
if (CmsContentTag.SortTagAttr.isRecent(sortType)) {
|
||||
q.gt(isNext, CmsContent::getPublishDate, content.getPublishDate());
|
||||
q.lt(!isNext, CmsContent::getPublishDate, content.getPublishDate());
|
||||
q.orderBy(true, isNext, CmsContent::getPublishDate);
|
||||
} else if(CmsContentTag.SortTagAttr.isViews(sort)) {
|
||||
} else if(CmsContentTag.SortTagAttr.isViews(sortType)) {
|
||||
q.gt(isNext, CmsContent::getViewCount, content.getViewCount());
|
||||
q.lt(!isNext, CmsContent::getViewCount, content.getViewCount());
|
||||
q.orderBy(true, isNext, CmsContent::getViewCount);
|
||||
@ -120,11 +174,18 @@ public class CmsContentClosestTag extends AbstractListTag {
|
||||
|
||||
@Override
|
||||
public List<TagAttr> getTagAttrs() {
|
||||
return List.of(
|
||||
new TagAttr(ATTR_CONTENT_ID, true, TagAttrDataType.INTEGER, ATTR_USAGE_CONTENT_ID),
|
||||
new TagAttr(ATTR_TYPE, true, TagAttrDataType.STRING, ATTR_USAGE_TYPE, TypeTagAttr.toTagAttrOptions(), TypeTagAttr.Prev.name()),
|
||||
new TagAttr(ATTR_SORT, false, TagAttrDataType.STRING, ATTR_USAGE_SORT, CmsContentTag.SortTagAttr.toTagAttrOptions(), CmsContentTag.SortTagAttr.Default.name())
|
||||
);
|
||||
List<TagAttr> tagAttrs = super.getTagAttrs();
|
||||
tagAttrs.add(new TagAttr(ATTR_CONTENT_ID, true, TagAttrDataType.INTEGER, ATTR_USAGE_CONTENT_ID));
|
||||
tagAttrs.add(new TagAttr(ATTR_TYPE, true, TagAttrDataType.STRING, ATTR_USAGE_TYPE, TypeTagAttr.toTagAttrOptions(), TypeTagAttr.Prev.name()));
|
||||
tagAttrs.add(new TagAttr(ATTR_CATALOG_ID, false, TagAttrDataType.INTEGER, CmsContentTag.ATTR_USAGE_CATALOG_ID));
|
||||
tagAttrs.add(new TagAttr(ATTR_CATALOG_ALIAS, false, TagAttrDataType.STRING, CmsContentTag.ATTR_USAGE_CATALOG_ALIAS));
|
||||
tagAttrs.add(new TagAttr(ATTR_LEVEL, false, TagAttrDataType.STRING, CmsContentTag.ATTR_USAGE_LEVEL, CmsContentTag.LevelTagAttr.toTagAttrOptions(), CmsContentTag.LevelTagAttr.Current.name()));
|
||||
tagAttrs.add(new TagAttr(ATTR_SORT, false, TagAttrDataType.STRING, CmsContentTag.ATTR_USAGE_SORT, CmsContentTag.SortTagAttr.toTagAttrOptions(), CmsContentTag.SortTagAttr.Default.name()));
|
||||
tagAttrs.add(new TagAttr(ATTR_HAS_ATTRIBUTE, false, TagAttrDataType.STRING, CmsContentTag.ATTR_USAGE_HAS_ATTRIBUTE));
|
||||
tagAttrs.add(new TagAttr(ATTR_NO_ATTRIBUTE, false, TagAttrDataType.STRING, CmsContentTag.ATTR_USAGE_NO_ATTRIBUTE));
|
||||
tagAttrs.add(new TagAttr(ATTR_STATUS, false, TagAttrDataType.STRING, CmsContentTag.ATTR_USAGE_STATUS));
|
||||
tagAttrs.add(new TagAttr(ATTR_TOP_FLAG, false, TagAttrDataType.BOOLEAN, CmsContentTag.ATTR_USAGE_TOP_FLAG, Boolean.TRUE.toString()));
|
||||
return tagAttrs;
|
||||
}
|
||||
|
||||
enum TypeTagAttr {
|
||||
|
||||
@ -109,7 +109,7 @@ public class CmsContentTag extends AbstractListTag {
|
||||
}
|
||||
String level = MapUtils.getString(attrs, ATTR_LEVEL);
|
||||
if (!LevelTagAttr.isRoot(level) && Objects.isNull(catalog)) {
|
||||
throw new CatalogNotFoundException(getTagName(), catalogId, alias, env);
|
||||
throw new CatalogNotFoundException(catalogId, alias, env);
|
||||
}
|
||||
String condition = MapUtils.getString(attrs, TagAttr.AttrName_Condition);
|
||||
String status = MapUtils.getString(attrs, ATTR_STATUS, ContentStatus.PUBLISHED);
|
||||
|
||||
@ -23,7 +23,10 @@ import com.chestnut.common.staticize.tag.AbstractTag;
|
||||
import com.chestnut.common.staticize.tag.TagAttr;
|
||||
import com.chestnut.common.utils.Assert;
|
||||
import com.chestnut.common.utils.StringUtils;
|
||||
import com.chestnut.contentcore.core.impl.PublishPipeProp_PrefixMode;
|
||||
import com.chestnut.contentcore.core.impl.PublishPipeProp_RelativePrefix;
|
||||
import com.chestnut.contentcore.domain.CmsSite;
|
||||
import com.chestnut.contentcore.enums.SitePrefixMode;
|
||||
import com.chestnut.contentcore.properties.EnableSSIProperty;
|
||||
import com.chestnut.contentcore.service.ISiteService;
|
||||
import com.chestnut.contentcore.service.ITemplateService;
|
||||
@ -160,7 +163,7 @@ public class CmsIncludeTag extends AbstractTag {
|
||||
}
|
||||
}
|
||||
if (ssi) {
|
||||
String prefix = SiteUtils.getPublishPipePrefix(site, context.getPublishPipeCode(), context.isPreview());
|
||||
String prefix = getIncludePathPrefix(context.getPublishPipeCode(), site);
|
||||
env.getOut().write(StringUtils.messageFormat(SSI_INCLUDE_TAG, prefix + staticFilePath));
|
||||
} else {
|
||||
env.getOut().write(staticContent);
|
||||
@ -169,6 +172,18 @@ public class CmsIncludeTag extends AbstractTag {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getIncludePathPrefix(String publishPipeCode, CmsSite site) {
|
||||
String prefix = null;
|
||||
String prefixMode = PublishPipeProp_PrefixMode.getValue(publishPipeCode, site.getPublishPipeProps());
|
||||
if (SitePrefixMode.isRelative(prefixMode)) {
|
||||
prefix = PublishPipeProp_RelativePrefix.getValue(publishPipeCode, site.getPublishPipeProps());
|
||||
}
|
||||
if (StringUtils.isEmpty(prefix)) {
|
||||
prefix = "/";
|
||||
}
|
||||
return prefix;
|
||||
}
|
||||
|
||||
private Map<String, String> mergeRequestVariable(Environment env, Map<String, String> params) throws TemplateModelException {
|
||||
TemplateModel variable = env.getVariable(TemplateUtils.TemplateVariable_Request);
|
||||
if (Objects.nonNull(variable)) {
|
||||
|
||||
@ -124,19 +124,19 @@ public class CmsPageWidgetTag extends AbstractTag {
|
||||
String siteRoot = SiteUtils.getSiteRoot(site, context.getPublishPipeCode());
|
||||
String staticFileName = PageWidgetUtils.getStaticFileName(pw, site.getStaticSuffix(context.getPublishPipeCode()));
|
||||
String staticFilePath = pw.getPath() + staticFileName;
|
||||
if (ssi) {
|
||||
// 读取页面部件静态化内容
|
||||
String staticContent = templateService.getTemplateStaticContentCache(templateKey);
|
||||
if (Objects.isNull(staticContent) || !new File(siteRoot + staticFilePath).exists()) {
|
||||
staticContent = this.processTemplate(env, pw, templateKey);
|
||||
|
||||
String staticContent = templateService.getTemplateStaticContentCache(templateKey);
|
||||
if (Objects.isNull(staticContent) || !new File(siteRoot + staticFilePath).exists()) {
|
||||
staticContent = this.processTemplate(env, pw, templateKey);
|
||||
this.templateService.setTemplateStaticContentCache(templateKey, staticContent);
|
||||
if (ssi) {
|
||||
FileUtils.writeStringToFile(new File(siteRoot + staticFilePath), staticContent, StandardCharsets.UTF_8);
|
||||
this.templateService.setTemplateStaticContentCache(templateKey, staticContent);
|
||||
}
|
||||
String prefix = SiteUtils.getPublishPipePrefix(site, context.getPublishPipeCode(), context.isPreview());
|
||||
}
|
||||
if (ssi) {
|
||||
String prefix = CmsIncludeTag.getIncludePathPrefix(context.getPublishPipeCode(), site);
|
||||
env.getOut().write(StringUtils.messageFormat(CmsIncludeTag.SSI_INCLUDE_TAG, prefix + staticFilePath));
|
||||
} else {
|
||||
// 非ssi模式无法使用缓存
|
||||
String staticContent = this.processTemplate(env, pw, templateKey);
|
||||
env.getOut().write(staticContent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ public class CatalogUtils {
|
||||
publishPipeCode, pageIndex);
|
||||
return BackendContext.getValue() + catalogPath;
|
||||
}
|
||||
String prefix = SiteUtils.getPublishPipePrefix(site, publishPipeCode, isPreview);
|
||||
String prefix = SiteUtils.getPublishPipePrefix(site, publishPipeCode, false);
|
||||
if (catalog.isStaticize()) {
|
||||
return prefix + catalog.getPath();
|
||||
} else {
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
package com.chestnut.contentcore.util;
|
||||
|
||||
import com.chestnut.common.async.AsyncTaskManager;
|
||||
import com.chestnut.common.security.domain.LoginUser;
|
||||
import com.chestnut.common.security.domain.Operator;
|
||||
import com.chestnut.common.utils.IdUtils;
|
||||
import com.chestnut.common.utils.SpringUtils;
|
||||
import com.chestnut.contentcore.domain.CmsContent;
|
||||
@ -39,7 +39,7 @@ public class ContentLogUtils {
|
||||
|
||||
private static final AsyncTaskManager asyncTaskManager = SpringUtils.getBean(AsyncTaskManager.class);
|
||||
|
||||
public static void addLog(String opType, CmsContent content, LoginUser operator) {
|
||||
public static void addLog(String opType, CmsContent content, Operator operator) {
|
||||
addLog(opType, content, null, operator.getUserType(), operator.getUsername());
|
||||
}
|
||||
|
||||
|
||||
@ -21,6 +21,7 @@ import com.chestnut.contentcore.config.CMSConfig;
|
||||
import com.chestnut.contentcore.core.IInternalDataType;
|
||||
import com.chestnut.contentcore.core.impl.InternalDataType_Site;
|
||||
import com.chestnut.contentcore.core.impl.PublishPipeProp_PrefixMode;
|
||||
import com.chestnut.contentcore.core.impl.PublishPipeProp_RelativePrefix;
|
||||
import com.chestnut.contentcore.domain.CmsSite;
|
||||
import com.chestnut.contentcore.enums.SitePrefixMode;
|
||||
import com.chestnut.system.fixed.config.BackendContext;
|
||||
@ -48,7 +49,7 @@ public class SiteUtils {
|
||||
}
|
||||
String pathMode = PublishPipeProp_PrefixMode.getValue(publishPipeCode, site.getPublishPipeProps());
|
||||
if (SitePrefixMode.isRelative(pathMode)) {
|
||||
return "/";
|
||||
return PublishPipeProp_RelativePrefix.getValue(publishPipeCode, site.getPublishPipeProps());
|
||||
}
|
||||
return site.getUrl(publishPipeCode);
|
||||
}
|
||||
@ -81,7 +82,7 @@ public class SiteUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取站点资源文件访问链接前缀
|
||||
* 获取站点资源文件访问链接前缀,非预览模式为设置资源域名则使用指定发布通道域名
|
||||
*
|
||||
* @param site 站点
|
||||
* @param publishPipeCode 发布通道编码
|
||||
|
||||
@ -149,7 +149,6 @@ FREEMARKER.TAG.cms_content_closest.contentId=內容ID
|
||||
FREEMARKER.TAG.cms_content_closest.type=类型
|
||||
FREEMARKER.TAG.cms_content_closest.type.Prev=上一篇
|
||||
FREEMARKER.TAG.cms_content_closest.type.Next=下一篇
|
||||
FREEMARKER.TAG.cms_content_closest.sort=排序值
|
||||
FREEMARKER.TAG.cms_content_rela.NAME=相关内容标签
|
||||
FREEMARKER.TAG.cms_content_rela.DESC=相关内容标签,内嵌`<#list DataList as content>${content.name}</#list>`遍历数据
|
||||
FREEMARKER.TAG.cms_content_rela.contentId=内容ID
|
||||
@ -195,6 +194,8 @@ FREEMARKER.FUNC.fileExtractor.DESC=提取html文本中的文件资源链接
|
||||
FREEMARKER.FUNC.fileExtractor.Arg1.Name=Html文本内容
|
||||
FREEMARKER.FUNC.fileExtractor.Arg2.Name=文件类型/后缀
|
||||
|
||||
FREEMARKER.ERR.CatalogNotFound=栏目数据不存在:[栏目ID: {0}], [栏目别名: {1}]
|
||||
|
||||
# 校验规则
|
||||
VALIDATOR.CMS.SITE.PUBLISH_PIPE_PROPS_EMPTY=发布通道配置不能为空
|
||||
VALIDATOR.CMS.SITE_PROPERTY.REGEXP_ERR=属性编码只能使用大小写字母、数字和下划线
|
||||
|
||||
@ -149,7 +149,6 @@ FREEMARKER.TAG.cms_content_closest.contentId=Target content id
|
||||
FREEMARKER.TAG.cms_content_closest.type=Type
|
||||
FREEMARKER.TAG.cms_content_closest.type.Prev=Prev
|
||||
FREEMARKER.TAG.cms_content_closest.type.Next=Next
|
||||
FREEMARKER.TAG.cms_content_closest.sort=Sort Value
|
||||
FREEMARKER.TAG.cms_content_rela.NAME=Related content tag
|
||||
FREEMARKER.TAG.cms_content_rela.DESC=Fetch related contents by contentId, use `<#list>` in tag like `<#list DataList as content>${content.title}</#list>` to walk through the list of contents.
|
||||
FREEMARKER.TAG.cms_content_rela.contentId=Target content id
|
||||
@ -195,6 +194,8 @@ FREEMARKER.FUNC.fileExtractor.DESC=Get file link list from html text.
|
||||
FREEMARKER.FUNC.fileExtractor.Arg1.Name=Html text
|
||||
FREEMARKER.FUNC.fileExtractor.Arg2.Name=File type or suffix
|
||||
|
||||
FREEMARKER.ERR.CatalogNotFound=Missing catalog: [id: {0}], [alias: {1}]
|
||||
|
||||
# 校验规则
|
||||
VALIDATOR.CMS.SITE.PUBLISH_PIPE_PROPS_EMPTY=The site publish pipe props cannot be empty.
|
||||
VALIDATOR.CMS.SITE_PROPERTY.REGEXP_ERR=The code can only use uppercase/lowercase letters, numbers and underscores.
|
||||
|
||||
@ -1,338 +1,339 @@
|
||||
# 資源類型
|
||||
CMS.CONTENTCORE.RESOURCE_TYPE.image=圖片
|
||||
CMS.CONTENTCORE.RESOURCE_TYPE.audio=音頻
|
||||
CMS.CONTENTCORE.RESOURCE_TYPE.video=視頻
|
||||
CMS.CONTENTCORE.RESOURCE_TYPE.file=檔案
|
||||
|
||||
# 欄目類型
|
||||
CMS.CONTENTCORE.CATALOG_TYPE.common=普通欄目
|
||||
CMS.CONTENTCORE.CATALOG_TYPE.link=連結欄目
|
||||
|
||||
# 字典數據
|
||||
DICT.CMSPageWidgetStatus=內容狀態
|
||||
DICT.CMSPageWidgetStatus.0=初稿
|
||||
DICT.CMSPageWidgetStatus.30=已發布
|
||||
DICT.CMSPageWidgetStatus.40=已下線
|
||||
DICT.CMSPageWidgetStatus.60=重新編輯
|
||||
DICT.CMSContentStatus=內容狀態
|
||||
DICT.CMSContentStatus.0=初稿
|
||||
DICT.CMSContentStatus.20=待發布
|
||||
DICT.CMSContentStatus.30=已發布
|
||||
DICT.CMSContentStatus.40=已下線
|
||||
DICT.CMSContentStatus.60=重新編輯
|
||||
DICT.CMSContentAttribute=內容屬性
|
||||
DICT.CMSContentAttribute.image=圖片
|
||||
DICT.CMSContentAttribute.video=視頻
|
||||
DICT.CMSContentAttribute.attach=附件
|
||||
DICT.CMSContentAttribute.hot=熱點
|
||||
DICT.CMSContentAttribute.recommend=推薦
|
||||
DICT.CMSStaticSuffix=靜態檔案類型
|
||||
DICT.CMSStaticSuffix.shtml=shtml
|
||||
DICT.CMSStaticSuffix.html=html
|
||||
DICT.CMSStaticSuffix.xml=xml
|
||||
DICT.CMSStaticSuffix.json=json
|
||||
DICT.CMSContentOpType=內容操作類型
|
||||
DICT.CMSContentOpType.ADD=新增
|
||||
DICT.CMSContentOpType.UPDATE=修改
|
||||
DICT.CMSContentOpType.DELETE=刪除
|
||||
DICT.CMSContentOpType.LOCK=鎖定
|
||||
DICT.CMSContentOpType.UNLOCK=解鎖
|
||||
DICT.CMSContentOpType.TO_PUBLISH=待發佈
|
||||
DICT.CMSContentOpType.PUBLISH=發佈
|
||||
DICT.CMSContentOpType.OFFLINE=下線
|
||||
DICT.CMSContentOpType.SORT=排序
|
||||
DICT.CMSContentOpType.TOP=置頂
|
||||
DICT.CMSContentOpType.CANCEL_TOP=取消置頂
|
||||
|
||||
# 固定配置參數
|
||||
CONFIG.CMSBackendContext=後台訪問地址
|
||||
CONFIG.CMSModuleEnable=是否開啟CMS功能
|
||||
CONFIG.CMSTemplateSuffix=模板尾碼名
|
||||
CONFIG.AllowUploadFileType=CMS檔案上傳類型限制
|
||||
CONFIG.SiteApiUrl=站點API地址
|
||||
CONFIG.ResourceUploadAcceptSize=素材庫資源上傳大小限制
|
||||
|
||||
# 錯誤資訊
|
||||
ERRCODE.CMS.CONTENTCORE.NO_SITE=無站點數據,請先去站點管理菜單創建站點
|
||||
ERRCODE.CMS.CONTENTCORE.UNSUPPORTED_PAGE_WIDGET_TYPE=未知頁面部件類型:{0}
|
||||
ERRCODE.CMS.CONTENTCORE.TEMPLATE_EMPTY=模板未配置或模板檔案不存在
|
||||
ERRCODE.CMS.CONTENTCORE.TEMPLATE_FILE_NOT_FOUND=模板檔案“{0}”不存在
|
||||
ERRCODE.CMS.CONTENTCORE.INVALID_TEMPLATE_NAME=模板檔案名只能使用大小寫字母和下劃線,且必須以`{0}`結尾
|
||||
ERRCODE.CMS.CONTENTCORE.UNSUPPORTED_CONTENT_TYPE=未知內容類型:{0}
|
||||
ERRCODE.CMS.CONTENTCORE.UNSUPPORTED_CATALOG_TYPE=未知欄目類型:{0}
|
||||
ERRCODE.CMS.CONTENTCORE.UNSUPPORTED_INTERNAL_DATA_TYPE=未知內部數據類型:{0}
|
||||
ERRCODE.CMS.CONTENTCORE.UNSUPPORTED_RESOURCE_TYPE=未知資源類型:{0}
|
||||
ERRCODE.CMS.CONTENTCORE.UNSUPPORTED_DYNAMIC_PAGE_TYPE=未知動態模板類型:{0}
|
||||
ERRCODE.CMS.CONTENTCORE.UNSUPPORTED_CONTENT_PATH_RULE=未知內容詳情頁路徑規則:{0}
|
||||
ERRCODE.CMS.CONTENTCORE.DEL_CHILD_FIRST=請先刪除子欄目
|
||||
ERRCODE.CMS.CONTENTCORE.CONFLICT_CATALOG=欄目名稱/別名/目錄重複
|
||||
ERRCODE.CMS.CONTENTCORE.CATALOG_MAX_TREE_LEVEL=欄目層級超出上限
|
||||
ERRCODE.CMS.CONTENTCORE.CATALOG_MOVE_TO_SELF_OR_CHILD=欄目不能轉移到自身或子欄目
|
||||
ERRCODE.CMS.CONTENTCORE.INVALID_PROPERTY=擴展屬性[{0}={1}]校驗失敗
|
||||
ERRCODE.CMS.CONTENTCORE.EXISTS_SITE_PATH=站點目錄衝突
|
||||
ERRCODE.CMS.CONTENTCORE.CONTENT_LOCKED=內容已被"{0}"鎖定
|
||||
ERRCODE.CMS.CONTENTCORE.TITLE_REPLEAT=標題重複
|
||||
ERRCODE.CMS.CONTENTCORE.CANNOT_EDIT_PUBLISHED_CONTENT=已發布內容不允許編輯,請先下線內容!
|
||||
ERRCODE.CMS.CONTENTCORE.NO_PUBLISHPIPE=無可用發布通道
|
||||
ERRCODE.CMS.CONTENTCORE.CATALOG_CANNOT_PUBLISH=欄目發布失敗:欄目不可見/不可靜態化/標題欄目。
|
||||
ERRCODE.CMS.CONTENTCORE.SITE_FILE_OP_ERR=不能操作非當前站點檔案
|
||||
ERRCODE.CMS.CONTENTCORE.TEMPLATE_PATH_EXISTS=模板檔案已存在或路徑被佔用
|
||||
ERRCODE.CMS.CONTENTCORE.NOT_ALLOW_FILE_TYPE=禁止上傳的檔案類型:{0}
|
||||
ERRCODE.CMS.CONTENTCORE.NOT_EDITABLE_FILE=指定檔案不支援線上編輯
|
||||
ERRCODE.CMS.CONTENTCORE.FILE_NOT_EXIST=檔案不存在
|
||||
ERRCODE.CMS.CONTENTCORE.FILE_ALREADY_EXISTS=檔案已存在
|
||||
ERRCODE.CMS.CONTENTCORE.CATALOG_SORT_VALUE_ZERO=欄目排序值不能為0
|
||||
ERRCODE.CMS.CONTENTCORE.SITE_EXPORT_TASK_EXISTS=站點導出任務正在進行中
|
||||
ERRCODE.CMS.CONTENTCORE.DEL_CONTENT_ERR=只能刪除初稿和已下線內容
|
||||
ERRCODE.CMS.CONTENTCORE.RESOURCE_ACCEPT_SIZE_LIMIT=上傳文件大小超過限制
|
||||
ERRCODE.CMS.CONTENTCORE.UNSUPPORTED_RESOURCE_STORAGE=資源存儲方式與當前站點配置不一致
|
||||
ERRCODE.CMS.CONTENTCORE.MERGE_CATALOG_IS_EMPTY=被合並欄目不存在
|
||||
ERRCODE.CMS.CONTENTCORE.MERGE_CATALOG_NOT_LEAF=被合並欄目不能包含子欄目
|
||||
ERRCODE.CMS.CONTENTCORE.DENY_LINK_TO_LINK_INTERNAL_DATA=不能链接到链接内容或栏目
|
||||
|
||||
# freemarker模板標籤
|
||||
FREEMARKER.TAG.cms_site.NAME=站點列表標籤
|
||||
FREEMARKER.TAG.cms_site.DESC=獲取站點數據列表,內嵌`<#list DataList as site>${catalog.site}</#list>`遍曆數據
|
||||
FREEMARKER.TAG.cms_site.id=站點ID
|
||||
FREEMARKER.TAG.cms_site.level=數據獲取範圍,值為`Root`時忽略屬性`id`
|
||||
FREEMARKER.TAG.cms_site.level.Root=所有站點
|
||||
FREEMARKER.TAG.cms_site.level.Current=同級站點
|
||||
FREEMARKER.TAG.cms_site.level.Child=子站點
|
||||
FREEMARKER.TAG.cms_catalog.NAME=欄目列表標籤
|
||||
FREEMARKER.TAG.cms_catalog.DESC=獲取欄目數據列表,內嵌`<#list DataList as catalog>${catalog.name}</#list>`遍曆數據
|
||||
FREEMARKER.TAG.cms_catalog.id=欄目ID
|
||||
FREEMARKER.TAG.cms_catalog.alias=欄目別名
|
||||
FREEMARKER.TAG.cms_catalog.level=數據獲取範圍,值為`Root`時忽略屬性`id`、`alias`
|
||||
FREEMARKER.TAG.cms_catalog.level.Root=所有欄目
|
||||
FREEMARKER.TAG.cms_catalog.level.Current=同級欄目
|
||||
FREEMARKER.TAG.cms_catalog.level.Child=子欄目
|
||||
FREEMARKER.TAG.cms_catalog.level.CurrentAndChild=當前欄目及子欄目
|
||||
FREEMARKER.TAG.cms_catalog.level.Self=當前欄目
|
||||
FREEMARKER.TAG.cms_content.NAME=內容列表標籤
|
||||
FREEMARKER.TAG.cms_content.DESC=獲取內容數據列表,內嵌`<#list DataList as content>${content.name}</#list>`遍曆數據
|
||||
FREEMARKER.TAG.cms_content.catalogId=欄目ID
|
||||
FREEMARKER.TAG.cms_content.catalogAlias=欄目別名
|
||||
FREEMARKER.TAG.cms_content.level=數據獲取範圍,值為`Root`時忽略屬性`catalogid`、`catalogalias`
|
||||
FREEMARKER.TAG.cms_content.level.Root=所有欄目
|
||||
FREEMARKER.TAG.cms_content.level.Current=當前欄目
|
||||
FREEMARKER.TAG.cms_content.level.Child=子欄目
|
||||
FREEMARKER.TAG.cms_content.level.CurrentAndChild=當前欄目及子欄目
|
||||
FREEMARKER.TAG.cms_content.sort=排序方式
|
||||
FREEMARKER.TAG.cms_content.sort.Recent=發佈時間降序
|
||||
FREEMARKER.TAG.cms_content.sort.Views=瀏覽量降序
|
||||
FREEMARKER.TAG.cms_content.sort.Default=排序字段降序(默認)
|
||||
FREEMARKER.TAG.cms_content.hasattribute=包含內容屬性,多個屬性英文逗號分隔
|
||||
FREEMARKER.TAG.cms_content.noattribute=不包含內容屬性,多個屬性英文逗號分隔
|
||||
FREEMARKER.TAG.cms_content.status=狀態,'-1'表示不限制狀態
|
||||
FREEMARKER.TAG.cms_content.status.defaultValue=30: 已發佈
|
||||
FREEMARKER.TAG.cms_content.topflag=是否允許指定
|
||||
FREEMARKER.TAG.cms_site_property.NAME=站點自定義屬性標籤
|
||||
FREEMARKER.TAG.cms_site_property.DESC=獲取站點自定義屬性數據列表,內嵌`<#list DataList as prop>${prop.propName}</#list>`遍曆數據
|
||||
FREEMARKER.TAG.cms_site_property.siteid=站點ID,默認從模板變量中獲取`${Site.siteId}`
|
||||
FREEMARKER.TAG.cms_site_property.code=屬性編碼
|
||||
FREEMARKER.TAG.cms_include.NAME=模板引用標籤
|
||||
FREEMARKER.TAG.cms_include.DESC=引用其他模板內容,支援ssi引用標籤
|
||||
FREEMARKER.TAG.cms_include.file=引用模板文件路徑(相對模板目錄template/)
|
||||
FREEMARKER.TAG.cms_include.ssi=是否啟用SSI
|
||||
FREEMARKER.TAG.cms_include.virtual=是否啟用Virtual模式
|
||||
FREEMARKER.TAG.cms_include.cache=是否啟用緩存
|
||||
FREEMARKER.TAG.cms_pagewidget.NAME=頁面部件引用標籤
|
||||
FREEMARKER.TAG.cms_pagewidget.DESC=引用頁面部件內容,支援ssi引用標籤
|
||||
FREEMARKER.TAG.cms_pagewidget.code=頁面部件編碼
|
||||
FREEMARKER.TAG.cms_pagewidget.ssi=是否啟用SSI
|
||||
FREEMARKER.TAG.cms_pagewidget_data.NAME=頁面部件數據標籤
|
||||
FREEMARKER.TAG.cms_pagewidget_data.DESC=頁面部件數據標籤,標籤體內可使用`${Data.name}`獲取數據
|
||||
FREEMARKER.TAG.cms_pagewidget_data.code=頁面部件編碼
|
||||
FREEMARKER.TAG.cms_content_closest.NAME=內容前後篇標籤
|
||||
FREEMARKER.TAG.cms_content_closest.DESC=內容前後篇標籤,僅支援指定內容當前欄目列表,標籤體內可使用`${Data.title}`獲取數據
|
||||
FREEMARKER.TAG.cms_content_closest.contentId=內容ID
|
||||
FREEMARKER.TAG.cms_content_closest.type=類型
|
||||
FREEMARKER.TAG.cms_content_closest.type.Prev=上一篇
|
||||
FREEMARKER.TAG.cms_content_closest.type.Next=下一篇
|
||||
FREEMARKER.TAG.cms_content_closest.sort=排序方式
|
||||
FREEMARKER.TAG.cms_content_rela.NAME=相關內容標籤
|
||||
FREEMARKER.TAG.cms_content_rela.DESC=相關內容標籤,內嵌`<#list DataList as content>${content.name}</#list>`遍曆數據
|
||||
FREEMARKER.TAG.cms_content_rela.contentId=內容ID
|
||||
|
||||
# freemarker模板函數
|
||||
FREEMARKER.FUNC.htmlInternalUrl.DESC=將html文本中的內部連結地址“iurl://”解析為正常http(s)訪問地址,例如:`${htmlInternalUrl(ArticleContent)}`
|
||||
FREEMARKER.FUNC.htmlInternalUrl.Arg1.Name=Html文本內容
|
||||
FREEMARKER.FUNC.imageSize.DESC=獲得圖片縮放圖函數,不在的縮略圖會自動建立,例如:`${imageSize(content.logo, 300, 300)}`
|
||||
FREEMARKER.FUNC.imageSize.Arg1.Name=圖片資源內部路徑(iurl://)
|
||||
FREEMARKER.FUNC.imageSize.Arg1.Desc=僅支持處理內部資源圖片(iurl://)
|
||||
FREEMARKER.FUNC.imageSize.Arg2.Name=寬度
|
||||
FREEMARKER.FUNC.imageSize.Arg3.Name=高度
|
||||
FREEMARKER.FUNC.internalUrl.DESC=將內部連結“iurl://”解析為正常http(s)訪問地址,例如:`${internalUrl(content.redirectUrl)}`
|
||||
FREEMARKER.FUNC.internalUrl.Arg1.Name=內部鏈接(iurl://)
|
||||
FREEMARKER.FUNC.siteUrl.DESC=獲取站點指定發布通道訪問連結,例如:`${siteUrl(Site.siteId, 'h5')}`
|
||||
FREEMARKER.FUNC.siteUrl.Arg1.Name=站點ID
|
||||
FREEMARKER.FUNC.siteUrl.Arg2.Name=發佈通道編碼
|
||||
FREEMARKER.FUNC.catalogUrl.DESC=獲取欄目指定發布通道訪問連結,例如:`${catalogUrl(Catalog.catalogId, 'h5')}`
|
||||
FREEMARKER.FUNC.catalogUrl.Arg1.Name=欄目ID
|
||||
FREEMARKER.FUNC.catalogUrl.Arg2.Name=發佈通道編碼
|
||||
FREEMARKER.FUNC.contentUrl.DESC=獲取內容指定發布通道訪問連結,例如:`${contentUrl(Content.contentId, 'h5')}`
|
||||
FREEMARKER.FUNC.contentUrl.Arg1.Name=內容ID
|
||||
FREEMARKER.FUNC.contentUrl.Arg2.Name=發佈通道編碼
|
||||
FREEMARKER.FUNC.dynamicPageLink.DESC=動態頁面連結獲取函數,例如:`${dynamicPageLink('Search')}`
|
||||
FREEMARKER.FUNC.dynamicPageLink.Arg1.Name=動態頁面類型
|
||||
FREEMARKER.FUNC.dynamicPageLink.Arg2.Name=忽略`sid/pp`參數
|
||||
FREEMARKER.FUNC.dict.DESC=獲取字典數據列表,例如:`${dict('YesOrNo', 'Y')}`
|
||||
FREEMARKER.FUNC.dict.Arg1.Name=字典類型
|
||||
FREEMARKER.FUNC.dict.Arg2.Name=字典數據值
|
||||
FREEMARKER.FUNC.dict.Arg3.Name=國際化標識
|
||||
FREEMARKER.FUNC.sysConfig.DESC=獲取系統參數配置值,例如:`${sysConfig('SiteApiUrl')}`
|
||||
FREEMARKER.FUNC.sysConfig.Arg1.Name=系統參數鍵名
|
||||
FREEMARKER.FUNC.listHtmlInternalUrl.DESC=獲取html文本中的iurl列表,例如:`${listHtmlInternalUrl(ArticleContent)}`
|
||||
FREEMARKER.FUNC.listHtmlInternalUrl.Arg1.Name=Html文本內容
|
||||
FREEMARKER.FUNC.contentPageLink.DESC=獲取內容分頁鏈接,例如:`${contentPageLink(content.link, 2)}`
|
||||
FREEMARKER.FUNC.contentPageLink.Arg1.Name=內容鏈接
|
||||
FREEMARKER.FUNC.contentPageLink.Arg2.Name=頁碼
|
||||
FREEMARKER.FUNC.videoPlayer.DESC=將html文本中的視頻資源連結替換為<video>視頻播放器
|
||||
FREEMARKER.FUNC.videoPlayer.Arg1.Name=Html文本內容
|
||||
FREEMARKER.FUNC.videoPlayer.Arg2.Name=視頻寬度
|
||||
FREEMARKER.FUNC.videoPlayer.Arg3.Name=視頻高度
|
||||
FREEMARKER.FUNC.fileExtractor.DESC=提取html文本中的文件資源鏈接
|
||||
FREEMARKER.FUNC.fileExtractor.Arg1.Name=Html文本內容
|
||||
FREEMARKER.FUNC.fileExtractor.Arg2.Name=文件類型/後綴
|
||||
|
||||
# 校驗規則
|
||||
VALIDATOR.CMS.SITE.PUBLISH_PIPE_PROPS_EMPTY=發布通道配置不能為空
|
||||
VALIDATOR.CMS.SITE_PROPERTY.REGEXP_ERR=屬性編碼只能使用大小寫字母、數字和下劃線
|
||||
VALIDATOR.CMS.FILE_NAME.REGEXP_ERR=文件名不能包含斜杠或反斜杠
|
||||
|
||||
# 定時任務
|
||||
SCHEDULED_TASK.RecycleExpireJobHandler=資源回收筒過期內容刪除任務
|
||||
SCHEDULED_TASK.SitePublishJobHandler=內容定時發布任務
|
||||
SCHEDULED_TASK.ContentTopCancelJobHandler=內容置頂取消任務
|
||||
SCHEDULED_TASK.UpdateDynamicDataJobHandler=保存內容動態數據任務
|
||||
SCHEDULED_TASK.ContentOfflineJobHandler=內容定時下線任務
|
||||
SCHEDULED_TASK.ResourceChunkClearJobHandler=資源上傳分片文件過期刪除任務
|
||||
|
||||
# 缓存监控
|
||||
MONITORED.CACHE.SITE=站點
|
||||
MONITORED.CACHE.CATALOG=欄目
|
||||
MONITORED.CACHE.PAGE_WIDGET=頁面部件
|
||||
MONITORED.CACHE.TEMPLATE=模板
|
||||
|
||||
# 动态模板
|
||||
DYNAMIC_PAGE_TYPE.ARG.sid=站點ID
|
||||
DYNAMIC_PAGE_TYPE.ARG.pp=發佈通道編碼
|
||||
DYNAMIC_PAGE_TYPE.ARG.preview=是否預覽模式
|
||||
|
||||
# 内容静态化子目录划分规则
|
||||
CONTENT_PATH_RULE.IdHash=按/內容ID分片/劃分
|
||||
CONTENT_PATH_RULE.Year=按/年/劃分
|
||||
CONTENT_PATH_RULE.Month=按/年/月/劃分
|
||||
CONTENT_PATH_RULE.Date=按/年/月/日/劃分
|
||||
CONTENT_PATH_RULE.DateStr=按/年-月-日/劃分
|
||||
|
||||
TIP.CMS.CORE.DELETING_MAPPING_CONTENT=正在刪除關聯映射內容:{0},[ID:{1}]
|
||||
TIP.CMS.CORE.OFFLINE_CONTENT=正在下線內容:{0}
|
||||
TIP.CMS.CORE.OFFLINE_SUCCESS=下線成功
|
||||
TIP.CMS.CORE.OFFLINE_MAPPING_CONTENT=正在下線關聯映射內容:{0},[ID:{1}]
|
||||
TIP.CMS.CORE.PUBLISHING_CONTENT=正在發佈內容:{0}
|
||||
TIP.CMS.CORE.PUBLISHING_CATALOG=正在發佈欄目:{0}
|
||||
TIP.CMS.CORE.PUBLISHING_SITE=正在發佈站點:{0}
|
||||
TIP.CMS.CORE.PUBLISH_SUCCESS=發佈成功
|
||||
TIP.CMS.CORE.COPYING_CONTENT=正在複製:{0} > {1}
|
||||
TIP.CMS.CORE.COPY_CONTENT_SUCCESS=復製成功
|
||||
TIP.CMS.CORE.MOVING_CONTENT=正在移動:{0} > {1}
|
||||
TIP.CMS.CORE.MOVE_CONTENT_SUCCESS=移動成功
|
||||
|
||||
CMS.SITE.ID=站點ID
|
||||
CMS.SITE.PARENT_ID=父級站點ID
|
||||
CMS.SITE.NAME=站點名稱
|
||||
CMS.SITE.DESC=站點描述
|
||||
CMS.SITE.LOGO=站點LOGO
|
||||
CMS.SITE.LOGO_SRC=LOGO訪問地址
|
||||
CMS.SITE.PATH=站點路徑
|
||||
CMS.SITE.RESOURCE_URL=站點資源域名
|
||||
CMS.SITE.DEPT_CODE=所屬機構編碼
|
||||
CMS.SITE.SEO_KEYWORDS=SEO關鍵詞
|
||||
CMS.SITE.SEO_DESC=SEO描述
|
||||
CMS.SITE.SEO_TITLE=SEO標題
|
||||
CMS.SITE.CONFIG_PROPS=擴展配置
|
||||
CMS.SITE.LINK=鏈接地址
|
||||
|
||||
CMS.SITE.PROP.ID=站點屬性ID
|
||||
CMS.SITE.PROP.SITE_ID=所屬站點ID
|
||||
CMS.SITE.PROP.NAME=屬性名稱
|
||||
CMS.SITE.PROP.CODE=屬性編碼
|
||||
CMS.SITE.PROP.VALUE=屬性值
|
||||
|
||||
CMS.CATALOG.ID=欄目ID
|
||||
CMS.CATALOG.SITE_ID=站點ID
|
||||
CMS.CATALOG.PARENT_ID=父級欄目ID
|
||||
CMS.CATALOG.ANCESTORS=祖級欄目IDs
|
||||
CMS.CATALOG.NAME=欄目名稱
|
||||
CMS.CATALOG.LOGO=欄目引導圖
|
||||
CMS.CATALOG.LOGO_SRC=欄目引導圖訪問路徑
|
||||
CMS.CATALOG.ALIAS=欄目別名
|
||||
CMS.CATALOG.DESC=欄目簡介
|
||||
CMS.CATALOG.DEPT_CODE=所屬部門編碼
|
||||
CMS.CATALOG.TYPE=欄目類型
|
||||
CMS.CATALOG.PATH=欄目目錄
|
||||
CMS.CATALOG.REDIRECT_URL=欄目跳轉地址
|
||||
CMS.CATALOG.TREE_LEVEL=欄目層級
|
||||
CMS.CATALOG.CHILD_COUNT=子欄目數量
|
||||
CMS.CATALOG.CONTENT_COUNT=內容數量
|
||||
CMS.CATALOG.SEO_KEYWORDS=SEO關鍵詞
|
||||
CMS.CATALOG.SEO_DESC=SEO描述
|
||||
CMS.CATALOG.SEO_TITLE=SEO標題
|
||||
CMS.CATALOG.CONFIG_PROPS=擴展配置
|
||||
CMS.CATALOG.LINK=欄目首頁鏈接
|
||||
CMS.CATALOG.LIST_LINK=欄目列表頁鏈接(無首頁模板時等同於首頁鏈接)
|
||||
|
||||
CMS.CONTENT.ID=內容ID
|
||||
CMS.CONTENT.SITE_ID=所屬站點ID
|
||||
CMS.CONTENT.CATALOG_ID=所屬欄目ID
|
||||
CMS.CONTENT.CATALOG_ANCESTORS=所屬欄目祖級IDs
|
||||
CMS.CONTENT.TOP_CATALOG=所屬頂級欄目ID
|
||||
CMS.CONTENT.DEPT_ID=所屬部門ID
|
||||
CMS.CONTENT.DEPT_CODE=所屬部門編碼
|
||||
CMS.CONTENT.TYPE=內容類型
|
||||
CMS.CONTENT.TITLE=標題
|
||||
CMS.CONTENT.SUB_TITLE=副標題
|
||||
CMS.CONTENT.SHORT_TITLE=短標題
|
||||
CMS.CONTENT.TITLE_STYLE=標題樣式
|
||||
CMS.CONTENT.LOGO=封面圖
|
||||
CMS.CONTENT.LOGO_SRC=封面圖訪問路徑
|
||||
CMS.CONTENT.IMAGES=封面圖列表
|
||||
CMS.CONTENT.SOURCE=來源
|
||||
CMS.CONTENT.SOURCE_URL=來源URL
|
||||
CMS.CONTENT.ORIGINAL=是否原創
|
||||
CMS.CONTENT.AUTHOR=作者
|
||||
CMS.CONTENT.EDITOR=編輯
|
||||
CMS.CONTENT.CONTRIBUTOR_ID=投稿用戶ID
|
||||
CMS.CONTENT.SUMMARY=摘要
|
||||
CMS.CONTENT.ATTRS=內容屬性標識列表
|
||||
CMS.CONTENT.STATUS=內容狀態
|
||||
CMS.CONTENT.LINK_FLAG=是否鏈接內容
|
||||
CMS.CONTENT.REDIRECT_URL=跳轉鏈接
|
||||
CMS.CONTENT.TOP_FLAG=置頂標識
|
||||
CMS.CONTENT.TOP_DATE=置頂結束時間
|
||||
CMS.CONTENT.KEYWORDS=關鍵詞
|
||||
CMS.CONTENT.TAGS=TAG詞
|
||||
CMS.CONTENT.PUBLISH_DATE=發佈時間
|
||||
CMS.CONTENT.SEO_TITLE=SEO標題
|
||||
CMS.CONTENT.SEO_KEYWORDS=SEO關鍵詞
|
||||
CMS.CONTENT.SEO_DESC=SEO描述
|
||||
CMS.CONTENT.LIKE=點讚數(非實時)
|
||||
CMS.CONTENT.COMMENT=評論數(非實時)
|
||||
CMS.CONTENT.FAVORITE=收藏數(非實時)
|
||||
CMS.CONTENT.VIEW=瀏覽量(非實時)
|
||||
CMS.CONTENT.PROP1=備用字段1
|
||||
CMS.CONTENT.PROP2=備用字段2
|
||||
CMS.CONTENT.PROP3=備用字段3
|
||||
CMS.CONTENT.PROP4=備用字段4
|
||||
CMS.CONTENT.LINK=內容鏈接
|
||||
|
||||
CMS.PAGE_WIDGET.ID=頁面部件ID
|
||||
CMS.PAGE_WIDGET.SITE_ID=所屬站點ID
|
||||
CMS.PAGE_WIDGET.CATALOG_ID=所屬欄目ID
|
||||
CMS.PAGE_WIDGET.CATALOG_ANCESTORS=所屬欄目祖級IDs
|
||||
CMS.PAGE_WIDGET.TYPE=類型
|
||||
CMS.PAGE_WIDGET.NAME=名稱
|
||||
CMS.PAGE_WIDGET.CODE=編碼
|
||||
CMS.PAGE_WIDGET.PUBLISH_PIPE=發佈通道
|
||||
CMS.PAGE_WIDGET.CONTENT_OBJ=擴展數據
|
||||
# 資源類型
|
||||
CMS.CONTENTCORE.RESOURCE_TYPE.image=圖片
|
||||
CMS.CONTENTCORE.RESOURCE_TYPE.audio=音頻
|
||||
CMS.CONTENTCORE.RESOURCE_TYPE.video=視頻
|
||||
CMS.CONTENTCORE.RESOURCE_TYPE.file=檔案
|
||||
|
||||
# 欄目類型
|
||||
CMS.CONTENTCORE.CATALOG_TYPE.common=普通欄目
|
||||
CMS.CONTENTCORE.CATALOG_TYPE.link=連結欄目
|
||||
|
||||
# 字典數據
|
||||
DICT.CMSPageWidgetStatus=內容狀態
|
||||
DICT.CMSPageWidgetStatus.0=初稿
|
||||
DICT.CMSPageWidgetStatus.30=已發布
|
||||
DICT.CMSPageWidgetStatus.40=已下線
|
||||
DICT.CMSPageWidgetStatus.60=重新編輯
|
||||
DICT.CMSContentStatus=內容狀態
|
||||
DICT.CMSContentStatus.0=初稿
|
||||
DICT.CMSContentStatus.20=待發布
|
||||
DICT.CMSContentStatus.30=已發布
|
||||
DICT.CMSContentStatus.40=已下線
|
||||
DICT.CMSContentStatus.60=重新編輯
|
||||
DICT.CMSContentAttribute=內容屬性
|
||||
DICT.CMSContentAttribute.image=圖片
|
||||
DICT.CMSContentAttribute.video=視頻
|
||||
DICT.CMSContentAttribute.attach=附件
|
||||
DICT.CMSContentAttribute.hot=熱點
|
||||
DICT.CMSContentAttribute.recommend=推薦
|
||||
DICT.CMSStaticSuffix=靜態檔案類型
|
||||
DICT.CMSStaticSuffix.shtml=shtml
|
||||
DICT.CMSStaticSuffix.html=html
|
||||
DICT.CMSStaticSuffix.xml=xml
|
||||
DICT.CMSStaticSuffix.json=json
|
||||
DICT.CMSContentOpType=內容操作類型
|
||||
DICT.CMSContentOpType.ADD=新建
|
||||
DICT.CMSContentOpType.UPDATE=修改
|
||||
DICT.CMSContentOpType.DELETE=刪除
|
||||
DICT.CMSContentOpType.LOCK=鎖定
|
||||
DICT.CMSContentOpType.UNLOCK=解鎖
|
||||
DICT.CMSContentOpType.TO_PUBLISH=待發布
|
||||
DICT.CMSContentOpType.PUBLISH=發布
|
||||
DICT.CMSContentOpType.OFFLINE=下線
|
||||
DICT.CMSContentOpType.SORT=排序
|
||||
DICT.CMSContentOpType.TOP=置頂
|
||||
DICT.CMSContentOpType.CANCEL_TOP=取消置頂
|
||||
|
||||
# 固定配置參數
|
||||
CONFIG.CMSBackendContext=後台訪問地址
|
||||
CONFIG.CMSModuleEnable=是否開啟CMS功能
|
||||
CONFIG.CMSTemplateSuffix=模板尾碼名
|
||||
CONFIG.AllowUploadFileType=CMS檔案上傳類型限制
|
||||
CONFIG.SiteApiUrl=站點API地址
|
||||
CONFIG.ResourceUploadAcceptSize=素材庫資源上傳大小限制
|
||||
|
||||
# 錯誤資訊
|
||||
ERRCODE.CMS.CONTENTCORE.NO_SITE=無站點數據,請先去站點管理菜單建立站點。
|
||||
ERRCODE.CMS.CONTENTCORE.UNSUPPORTED_PAGE_WIDGET_TYPE=未知頁面部件類型:{0}
|
||||
ERRCODE.CMS.CONTENTCORE.TEMPLATE_EMPTY=模板未配置或模板檔案不存在
|
||||
ERRCODE.CMS.CONTENTCORE.TEMPLATE_FILE_NOT_FOUND=模板檔案“{0}”不存在
|
||||
ERRCODE.CMS.CONTENTCORE.INVALID_TEMPLATE_NAME=模板檔案名只能使用大小寫字母和下劃線,且必須以`{0}`結尾
|
||||
ERRCODE.CMS.CONTENTCORE.UNSUPPORTED_CONTENT_TYPE=未知內容類型:{0}
|
||||
ERRCODE.CMS.CONTENTCORE.UNSUPPORTED_CATALOG_TYPE=未知欄目類型:{0}
|
||||
ERRCODE.CMS.CONTENTCORE.UNSUPPORTED_INTERNAL_DATA_TYPE=未知內部數據類型:{0}
|
||||
ERRCODE.CMS.CONTENTCORE.UNSUPPORTED_RESOURCE_TYPE=未知資源類型:{0}
|
||||
ERRCODE.CMS.CONTENTCORE.UNSUPPORTED_DYNAMIC_PAGE_TYPE=未知動態模板類型:{0}
|
||||
ERRCODE.CMS.CONTENTCORE.UNSUPPORTED_CONTENT_PATH_RULE=未知的內容詳情頁路徑規則:{0}
|
||||
ERRCODE.CMS.CONTENTCORE.DEL_CHILD_FIRST=請先刪除子欄目
|
||||
ERRCODE.CMS.CONTENTCORE.CONFLICT_CATALOG=欄目名稱/別名/目錄重複
|
||||
ERRCODE.CMS.CONTENTCORE.CATALOG_MAX_TREE_LEVEL=欄目層級超出上限
|
||||
ERRCODE.CMS.CONTENTCORE.CATALOG_MOVE_TO_SELF_OR_CHILD=欄目不能轉移到自身或子欄目
|
||||
ERRCODE.CMS.CONTENTCORE.INVALID_PROPERTY=擴展屬性[{0}={1}]校驗失敗
|
||||
ERRCODE.CMS.CONTENTCORE.EXISTS_SITE_PATH=站點目錄衝突
|
||||
ERRCODE.CMS.CONTENTCORE.CONTENT_LOCKED=內容已被"{0}"鎖定
|
||||
ERRCODE.CMS.CONTENTCORE.TITLE_REPLEAT=標題重複
|
||||
ERRCODE.CMS.CONTENTCORE.CANNOT_EDIT_PUBLISHED_CONTENT=已發布內容不允許編輯,請先下線內容!
|
||||
ERRCODE.CMS.CONTENTCORE.NO_PUBLISHPIPE=無可用發布通道
|
||||
ERRCODE.CMS.CONTENTCORE.CATALOG_CANNOT_PUBLISH=欄目發布失敗:欄目不可見/不可靜態化/標題欄目。
|
||||
ERRCODE.CMS.CONTENTCORE.SITE_FILE_OP_ERR=不能操作非當前站點檔案
|
||||
ERRCODE.CMS.CONTENTCORE.TEMPLATE_PATH_EXISTS=模板檔案已存在或路徑被佔用
|
||||
ERRCODE.CMS.CONTENTCORE.NOT_ALLOW_FILE_TYPE=禁止上傳的檔案類型:{0}
|
||||
ERRCODE.CMS.CONTENTCORE.NOT_EDITABLE_FILE=指定檔案不支援線上編輯
|
||||
ERRCODE.CMS.CONTENTCORE.FILE_NOT_EXIST=檔案不存在
|
||||
ERRCODE.CMS.CONTENTCORE.FILE_ALREADY_EXISTS=檔案已存在
|
||||
ERRCODE.CMS.CONTENTCORE.CATALOG_SORT_VALUE_ZERO=欄目排序值不能為0
|
||||
ERRCODE.CMS.CONTENTCORE.SITE_EXPORT_TASK_EXISTS=站點導出任務正在進行中
|
||||
ERRCODE.CMS.CONTENTCORE.DEL_CONTENT_ERR=只能刪除初稿和已下線內容
|
||||
ERRCODE.CMS.CONTENTCORE.RESOURCE_ACCEPT_SIZE_LIMIT=上傳檔案大小超過限制
|
||||
ERRCODE.CMS.CONTENTCORE.UNSUPPORTED_RESOURCE_STORAGE=資源存儲方式與當前站點配置不一致
|
||||
ERRCODE.CMS.CONTENTCORE.MERGE_CATALOG_IS_EMPTY=被合并欄目不存在
|
||||
ERRCODE.CMS.CONTENTCORE.MERGE_CATALOG_NOT_LEAF=被合并欄目不能包含子欄目
|
||||
ERRCODE.CMS.CONTENTCORE.DENY_LINK_TO_LINK_INTERNAL_DATA=不能連結到連結內容或欄目
|
||||
|
||||
# freemarker模板標籤
|
||||
FREEMARKER.TAG.cms_site.NAME=站點列表標籤
|
||||
FREEMARKER.TAG.cms_site.DESC=獲取站點數據列表,內嵌`<#list DataList as site>${catalog.site}</#list>`遍曆數據
|
||||
FREEMARKER.TAG.cms_site.id=站點ID
|
||||
FREEMARKER.TAG.cms_site.level=數據獲取範圍,值為`Root`時忽略屬性`id`
|
||||
FREEMARKER.TAG.cms_site.level.Root=所有站點
|
||||
FREEMARKER.TAG.cms_site.level.Current=同級站點
|
||||
FREEMARKER.TAG.cms_site.level.Child=子站點
|
||||
FREEMARKER.TAG.cms_catalog.NAME=欄目列表標籤
|
||||
FREEMARKER.TAG.cms_catalog.DESC=獲取欄目數據列表,內嵌`<#list DataList as catalog>${catalog.name}</#list>`遍曆數據
|
||||
FREEMARKER.TAG.cms_catalog.id=欄目ID
|
||||
FREEMARKER.TAG.cms_catalog.alias=欄目別名
|
||||
FREEMARKER.TAG.cms_catalog.level=數據獲取範圍,值為`Root`時忽略屬性`id`、`alias`
|
||||
FREEMARKER.TAG.cms_catalog.level.Root=所有欄目
|
||||
FREEMARKER.TAG.cms_catalog.level.Current=同級欄目
|
||||
FREEMARKER.TAG.cms_catalog.level.Child=子欄目
|
||||
FREEMARKER.TAG.cms_catalog.level.CurrentAndChild=當前欄目及子欄目
|
||||
FREEMARKER.TAG.cms_catalog.level.Self=當前欄目
|
||||
FREEMARKER.TAG.cms_content.NAME=內容列表標籤
|
||||
FREEMARKER.TAG.cms_content.DESC=獲取內容數據列表,內嵌`<#list DataList as content>${content.name}</#list>`遍曆數據
|
||||
FREEMARKER.TAG.cms_content.catalogId=欄目ID
|
||||
FREEMARKER.TAG.cms_content.catalogAlias=欄目別名
|
||||
FREEMARKER.TAG.cms_content.level=數據獲取範圍,值為`Root`時忽略屬性`catalogid`、`catalogalias`
|
||||
FREEMARKER.TAG.cms_content.level.Root=所有欄目
|
||||
FREEMARKER.TAG.cms_content.level.Current=當前欄目
|
||||
FREEMARKER.TAG.cms_content.level.Child=子欄目
|
||||
FREEMARKER.TAG.cms_content.level.CurrentAndChild=當前欄目及子欄目
|
||||
FREEMARKER.TAG.cms_content.sort=排序方式
|
||||
FREEMARKER.TAG.cms_content.sort.Recent=發布時間降序
|
||||
FREEMARKER.TAG.cms_content.sort.Views=瀏覽量降序
|
||||
FREEMARKER.TAG.cms_content.sort.Default=排序欄位降序(預設)
|
||||
FREEMARKER.TAG.cms_content.hasattribute=包含內容屬性,多個屬性英文逗號分隔
|
||||
FREEMARKER.TAG.cms_content.noattribute=不包含內容屬性,多個屬性英文逗號分隔
|
||||
FREEMARKER.TAG.cms_content.status=狀態,'-1'表示不限制狀態
|
||||
FREEMARKER.TAG.cms_content.status.defaultValue=30: 已發布
|
||||
FREEMARKER.TAG.cms_content.topflag=是否允許置頂
|
||||
FREEMARKER.TAG.cms_site_property.NAME=站點自定義屬性標籤
|
||||
FREEMARKER.TAG.cms_site_property.DESC=獲取站點自定義屬性數據列表,內嵌`<#list DataList as prop>${prop.propName}</#list>`遍曆數據
|
||||
FREEMARKER.TAG.cms_site_property.siteid=站點ID,預設從模板變數中獲取`${Site.siteId}`
|
||||
FREEMARKER.TAG.cms_site_property.code=屬性編碼
|
||||
FREEMARKER.TAG.cms_include.NAME=模板引用標籤
|
||||
FREEMARKER.TAG.cms_include.DESC=引用其他模板內容,支援ssi引用標籤
|
||||
FREEMARKER.TAG.cms_include.file=引用模板檔案路徑(相對模板目錄template/)
|
||||
FREEMARKER.TAG.cms_include.ssi=是否啟用SSI
|
||||
FREEMARKER.TAG.cms_include.virtual=是否啟用virtual模式,此模式下區塊無法繼承當前頁面上限文變數,需要通過參數傳入需要的變數
|
||||
FREEMARKER.TAG.cms_include.cache=是否啟用緩存
|
||||
FREEMARKER.TAG.cms_pagewidget.NAME=頁面部件引用標籤
|
||||
FREEMARKER.TAG.cms_pagewidget.DESC=引用頁面部件內容,支援ssi引用標籤
|
||||
FREEMARKER.TAG.cms_pagewidget.code=頁面部件編碼
|
||||
FREEMARKER.TAG.cms_pagewidget.ssi=是否啟用SSI
|
||||
FREEMARKER.TAG.cms_pagewidget_data.NAME=頁面部件數據標籤
|
||||
FREEMARKER.TAG.cms_pagewidget_data.DESC=頁面部件數據標籤,標籤體內可使用`${Data.name}`獲取數據
|
||||
FREEMARKER.TAG.cms_pagewidget_data.code=頁面部件編碼
|
||||
FREEMARKER.TAG.cms_content_closest.NAME=內容前後篇標籤
|
||||
FREEMARKER.TAG.cms_content_closest.DESC=內容前後篇標籤,僅支援指定內容當前欄目列表,標籤體內可使用`${Data.title}`獲取數據
|
||||
FREEMARKER.TAG.cms_content_closest.contentId=內容ID
|
||||
FREEMARKER.TAG.cms_content_closest.type=類型
|
||||
FREEMARKER.TAG.cms_content_closest.type.Prev=上一篇
|
||||
FREEMARKER.TAG.cms_content_closest.type.Next=下一篇
|
||||
FREEMARKER.TAG.cms_content_rela.NAME=相關內容標籤
|
||||
FREEMARKER.TAG.cms_content_rela.DESC=相關內容標籤,內嵌`<#list DataList as content>${content.name}</#list>`遍曆數據
|
||||
FREEMARKER.TAG.cms_content_rela.contentId=內容ID
|
||||
|
||||
# freemarker模板函數
|
||||
FREEMARKER.FUNC.htmlInternalUrl.DESC=將html文本中的內部連結地址“iurl://”解析為正常http(s)訪問地址,例如:`${htmlInternalUrl(ArticleContent)}`
|
||||
FREEMARKER.FUNC.htmlInternalUrl.Arg1.Name=Html文本內容
|
||||
FREEMARKER.FUNC.imageSize.DESC=獲得圖片縮放圖函數,不在的縮略圖會自動建立,例如:`${imageSize(content.logo, 300, 300)}`
|
||||
FREEMARKER.FUNC.imageSize.Arg1.Name=圖片資源內部路徑(iurl://)
|
||||
FREEMARKER.FUNC.imageSize.Arg1.Desc=僅支援處理內部資源圖片(iurl://)
|
||||
FREEMARKER.FUNC.imageSize.Arg2.Name=寬度
|
||||
FREEMARKER.FUNC.imageSize.Arg3.Name=高度
|
||||
FREEMARKER.FUNC.internalUrl.DESC=將內部連結“iurl://”解析為正常http(s)訪問地址,例如:`${internalUrl(content.redirectUrl)}`
|
||||
FREEMARKER.FUNC.internalUrl.Arg1.Name=內部連結(iurl://)
|
||||
FREEMARKER.FUNC.siteUrl.DESC=獲取站點指定發布通道訪問連結,例如:`${siteUrl(Site.siteId, 'h5')}`
|
||||
FREEMARKER.FUNC.siteUrl.Arg1.Name=站點ID
|
||||
FREEMARKER.FUNC.siteUrl.Arg2.Name=發布通道編碼
|
||||
FREEMARKER.FUNC.catalogUrl.DESC=獲取欄目指定發布通道訪問連結,例如:`${catalogUrl(Catalog.catalogId, 'h5')}`
|
||||
FREEMARKER.FUNC.catalogUrl.Arg1.Name=欄目ID
|
||||
FREEMARKER.FUNC.catalogUrl.Arg2.Name=發布通道編碼
|
||||
FREEMARKER.FUNC.contentUrl.DESC=獲取內容指定發布通道訪問連結,例如:`${contentUrl(Content.contentId, 'h5')}`
|
||||
FREEMARKER.FUNC.contentUrl.Arg1.Name=內容ID
|
||||
FREEMARKER.FUNC.contentUrl.Arg2.Name=發布通道編碼
|
||||
FREEMARKER.FUNC.dynamicPageLink.DESC=動態頁面連結獲取函數,例如:`${dynamicPageLink('Search')}`
|
||||
FREEMARKER.FUNC.dynamicPageLink.Arg1.Name=動態頁面類型
|
||||
FREEMARKER.FUNC.dynamicPageLink.Arg2.Name=忽略`sid/pp`參數
|
||||
FREEMARKER.FUNC.dict.DESC=獲取字典數據列表,例如:`${dict('YesOrNo', 'Y')}`
|
||||
FREEMARKER.FUNC.dict.Arg1.Name=字典類型
|
||||
FREEMARKER.FUNC.dict.Arg2.Name=字典數據值
|
||||
FREEMARKER.FUNC.dict.Arg3.Name=國際化標識
|
||||
FREEMARKER.FUNC.sysConfig.DESC=獲取系統參數配置值,例如:`${sysConfig('SiteApiUrl')}`
|
||||
FREEMARKER.FUNC.sysConfig.Arg1.Name=系統參數鍵名
|
||||
FREEMARKER.FUNC.listHtmlInternalUrl.DESC=獲取html文本中的iurl列表,例如:`${listHtmlInternalUrl(ArticleContent)}`
|
||||
FREEMARKER.FUNC.listHtmlInternalUrl.Arg1.Name=Html文本內容
|
||||
FREEMARKER.FUNC.contentPageLink.DESC=獲取內容分頁連結,例如:`${contentPageLink(content.link, 2)}`
|
||||
FREEMARKER.FUNC.contentPageLink.Arg1.Name=內容連結
|
||||
FREEMARKER.FUNC.contentPageLink.Arg2.Name=頁碼
|
||||
FREEMARKER.FUNC.videoPlayer.DESC=將html文本中的視頻資源連結替換為`<video>`視頻播放器
|
||||
FREEMARKER.FUNC.videoPlayer.Arg1.Name=Html文本內容
|
||||
FREEMARKER.FUNC.videoPlayer.Arg2.Name=視頻寬度
|
||||
FREEMARKER.FUNC.videoPlayer.Arg3.Name=視頻高度
|
||||
FREEMARKER.FUNC.fileExtractor.DESC=提取html文本中的檔案資源連結
|
||||
FREEMARKER.FUNC.fileExtractor.Arg1.Name=Html文本內容
|
||||
FREEMARKER.FUNC.fileExtractor.Arg2.Name=檔案類型/尾碼
|
||||
|
||||
FREEMARKER.ERR.CatalogNotFound=欄目數據不存在:[欄目ID: {0}], [欄目別名: {1}]
|
||||
|
||||
# 校驗規則
|
||||
VALIDATOR.CMS.SITE.PUBLISH_PIPE_PROPS_EMPTY=發布通道配置不能為空
|
||||
VALIDATOR.CMS.SITE_PROPERTY.REGEXP_ERR=屬性編碼只能使用大小寫字母、數字和下劃線
|
||||
VALIDATOR.CMS.FILE_NAME.REGEXP_ERR=檔案名不能包含斜杠或反斜杠
|
||||
|
||||
# 定時任務
|
||||
SCHEDULED_TASK.RecycleExpireJobHandler=資源回收筒過期內容刪除任務
|
||||
SCHEDULED_TASK.SitePublishJobHandler=內容定時發布任務
|
||||
SCHEDULED_TASK.ContentTopCancelJobHandler=內容置頂取消任務
|
||||
SCHEDULED_TASK.UpdateDynamicDataJobHandler=保存內容動態數據任務
|
||||
SCHEDULED_TASK.ContentOfflineJobHandler=內容定時下線任務
|
||||
SCHEDULED_TASK.ResourceChunkClearJobHandler=資源上傳分片檔案過期刪除任務
|
||||
|
||||
# 緩存監控
|
||||
MONITORED.CACHE.SITE=站點
|
||||
MONITORED.CACHE.CATALOG=欄目
|
||||
MONITORED.CACHE.PAGE_WIDGET=頁面部件
|
||||
MONITORED.CACHE.TEMPLATE=模板
|
||||
|
||||
# 動態模板
|
||||
DYNAMIC_PAGE_TYPE.ARG.sid=站點ID
|
||||
DYNAMIC_PAGE_TYPE.ARG.pp=發布通道編碼
|
||||
DYNAMIC_PAGE_TYPE.ARG.preview=是否預覽模式
|
||||
|
||||
# 內容靜態化子目錄劃分規則
|
||||
CONTENT_PATH_RULE.IdHash=按/內容ID分片/劃分
|
||||
CONTENT_PATH_RULE.Year=按/年/劃分
|
||||
CONTENT_PATH_RULE.Month=按/年/月/劃分
|
||||
CONTENT_PATH_RULE.Date=按/年/月/日/劃分
|
||||
CONTENT_PATH_RULE.DateStr=按/年-月-日/劃分
|
||||
|
||||
TIP.CMS.CORE.DELETING_MAPPING_CONTENT=正在刪除關聯映射內容:{0},[ID:{1}]
|
||||
TIP.CMS.CORE.OFFLINE_CONTENT=正在下線內容:{0}
|
||||
TIP.CMS.CORE.OFFLINE_SUCCESS=下線成功
|
||||
TIP.CMS.CORE.OFFLINE_MAPPING_CONTENT=正在下線關聯映射內容:{0},[ID:{1}]
|
||||
TIP.CMS.CORE.PUBLISHING_CONTENT=正在發布內容:{0}
|
||||
TIP.CMS.CORE.PUBLISHING_CATALOG=正在發布欄目:{0}
|
||||
TIP.CMS.CORE.PUBLISHING_SITE=正在發布站點:{0}
|
||||
TIP.CMS.CORE.PUBLISH_SUCCESS=發布成功
|
||||
TIP.CMS.CORE.COPYING_CONTENT=正在複製:{0} > {1}
|
||||
TIP.CMS.CORE.COPY_CONTENT_SUCCESS=複製成功
|
||||
TIP.CMS.CORE.MOVING_CONTENT=正在移動:{0} > {1}
|
||||
TIP.CMS.CORE.MOVE_CONTENT_SUCCESS=移動成功
|
||||
|
||||
CMS.SITE.ID=站點ID
|
||||
CMS.SITE.PARENT_ID=父級站點ID
|
||||
CMS.SITE.NAME=站點名稱
|
||||
CMS.SITE.DESC=站點描述
|
||||
CMS.SITE.LOGO=站點LOGO
|
||||
CMS.SITE.LOGO_SRC=LOGO訪問地址
|
||||
CMS.SITE.PATH=站點路徑
|
||||
CMS.SITE.RESOURCE_URL=站點資源功能變數名稱
|
||||
CMS.SITE.DEPT_CODE=所屬機構編碼
|
||||
CMS.SITE.SEO_KEYWORDS=SEO關鍵詞
|
||||
CMS.SITE.SEO_DESC=SEO描述
|
||||
CMS.SITE.SEO_TITLE=SEO標題
|
||||
CMS.SITE.CONFIG_PROPS=擴展配置
|
||||
CMS.SITE.LINK=連結地址
|
||||
|
||||
CMS.SITE.PROP.ID=站點屬性ID
|
||||
CMS.SITE.PROP.SITE_ID=所屬站點ID
|
||||
CMS.SITE.PROP.NAME=屬性名稱
|
||||
CMS.SITE.PROP.CODE=屬性編碼
|
||||
CMS.SITE.PROP.VALUE=屬性值
|
||||
|
||||
CMS.CATALOG.ID=欄目ID
|
||||
CMS.CATALOG.SITE_ID=站點ID
|
||||
CMS.CATALOG.PARENT_ID=父級欄目ID
|
||||
CMS.CATALOG.ANCESTORS=祖級欄目IDs
|
||||
CMS.CATALOG.NAME=欄目名稱
|
||||
CMS.CATALOG.LOGO=欄目引導圖
|
||||
CMS.CATALOG.LOGO_SRC=欄目引導圖訪問路徑
|
||||
CMS.CATALOG.ALIAS=欄目別名
|
||||
CMS.CATALOG.DESC=欄目簡介
|
||||
CMS.CATALOG.DEPT_CODE=所屬部門編碼
|
||||
CMS.CATALOG.TYPE=欄目類型
|
||||
CMS.CATALOG.PATH=欄目目錄
|
||||
CMS.CATALOG.REDIRECT_URL=標題欄目跳轉地址
|
||||
CMS.CATALOG.TREE_LEVEL=欄目層級
|
||||
CMS.CATALOG.CHILD_COUNT=子欄目數
|
||||
CMS.CATALOG.CONTENT_COUNT=內容數量
|
||||
CMS.CATALOG.SEO_KEYWORDS=SEO關鍵詞
|
||||
CMS.CATALOG.SEO_DESC=SEO描述
|
||||
CMS.CATALOG.SEO_TITLE=SEO標題
|
||||
CMS.CATALOG.CONFIG_PROPS=擴展配置
|
||||
CMS.CATALOG.LINK=欄目首頁連結
|
||||
CMS.CATALOG.LIST_LINK=欄目列表頁連結(無首頁模板時與首頁連結一致)
|
||||
|
||||
CMS.CONTENT.ID=內容ID
|
||||
CMS.CONTENT.SITE_ID=所屬站點ID
|
||||
CMS.CONTENT.CATALOG_ID=所屬欄目ID
|
||||
CMS.CONTENT.CATALOG_ANCESTORS=所屬欄目祖級IDs
|
||||
CMS.CONTENT.TOP_CATALOG=所屬頂級欄目ID
|
||||
CMS.CONTENT.DEPT_ID=所屬部門ID
|
||||
CMS.CONTENT.DEPT_CODE=所屬部門編碼
|
||||
CMS.CONTENT.TYPE=內容類型
|
||||
CMS.CONTENT.TITLE=標題
|
||||
CMS.CONTENT.SUB_TITLE=副標題
|
||||
CMS.CONTENT.SHORT_TITLE=短標題
|
||||
CMS.CONTENT.TITLE_STYLE=標題樣式
|
||||
CMS.CONTENT.LOGO=封面圖
|
||||
CMS.CONTENT.LOGO_SRC=封面圖訪問路徑
|
||||
CMS.CONTENT.IMAGES=封面圖列表
|
||||
CMS.CONTENT.SOURCE=來源
|
||||
CMS.CONTENT.SOURCE_URL=來源URL
|
||||
CMS.CONTENT.ORIGINAL=是否原創
|
||||
CMS.CONTENT.AUTHOR=作者
|
||||
CMS.CONTENT.EDITOR=編輯
|
||||
CMS.CONTENT.CONTRIBUTOR_ID=投稿用戶ID
|
||||
CMS.CONTENT.SUMMARY=摘要
|
||||
CMS.CONTENT.ATTRS=內容屬性標識列表
|
||||
CMS.CONTENT.STATUS=內容狀態
|
||||
CMS.CONTENT.LINK_FLAG=是否連結內容
|
||||
CMS.CONTENT.REDIRECT_URL=跳轉連結
|
||||
CMS.CONTENT.TOP_FLAG=置頂標識
|
||||
CMS.CONTENT.TOP_DATE=置頂結束時間
|
||||
CMS.CONTENT.KEYWORDS=關鍵詞
|
||||
CMS.CONTENT.TAGS=TAGs
|
||||
CMS.CONTENT.PUBLISH_DATE=發布時間
|
||||
CMS.CONTENT.SEO_TITLE=SEO標題
|
||||
CMS.CONTENT.SEO_KEYWORDS=SEO關鍵詞
|
||||
CMS.CONTENT.SEO_DESC=SEO描述
|
||||
CMS.CONTENT.LIKE=點贊數(非即時)
|
||||
CMS.CONTENT.COMMENT=評論數(非即時)
|
||||
CMS.CONTENT.FAVORITE=收藏數(非即時)
|
||||
CMS.CONTENT.VIEW=文章瀏覽數(非即時)
|
||||
CMS.CONTENT.PROP1=備用欄位1
|
||||
CMS.CONTENT.PROP2=備用欄位2
|
||||
CMS.CONTENT.PROP3=備用欄位3
|
||||
CMS.CONTENT.PROP4=備用欄位4
|
||||
CMS.CONTENT.LINK=內容連結
|
||||
|
||||
CMS.PAGE_WIDGET.ID=頁面部件ID
|
||||
CMS.PAGE_WIDGET.SITE_ID=所屬站點ID
|
||||
CMS.PAGE_WIDGET.CATALOG_ID=所屬欄目ID
|
||||
CMS.PAGE_WIDGET.CATALOG_ANCESTORS=所屬欄目祖級IDs
|
||||
CMS.PAGE_WIDGET.TYPE=類型
|
||||
CMS.PAGE_WIDGET.NAME=名稱
|
||||
CMS.PAGE_WIDGET.CODE=編碼
|
||||
CMS.PAGE_WIDGET.PUBLISH_PIPE=發布通道
|
||||
CMS.PAGE_WIDGET.CONTENT_OBJ=擴展數據
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-customform</artifactId>
|
||||
|
||||
@ -177,7 +177,7 @@ public class CustomFormCoreDataHandler implements ICoreDataHandler {
|
||||
for (CmsCustomFormData data : list) {
|
||||
String oldKey = data.getModelId() + "-" + data.getDataId();
|
||||
try {
|
||||
data.setDataId(IdUtils.getSnowflakeId());
|
||||
data.setDataId(IdUtils.getSnowflakeId()+"");
|
||||
data.setModelId(customFormIdMapping.get(data.getModelId()));
|
||||
// 处理图片和富文本内部链接
|
||||
MetaModel model = modelService.getMetaModel(data.getModelId());
|
||||
|
||||
@ -31,8 +31,8 @@ import com.chestnut.contentcore.domain.pojo.PublishPipeTemplate;
|
||||
import com.chestnut.contentcore.service.IPublishPipeService;
|
||||
import com.chestnut.contentcore.service.ISiteService;
|
||||
import com.chestnut.customform.domain.CmsCustomForm;
|
||||
import com.chestnut.customform.domain.dto.CustomFormAddDTO;
|
||||
import com.chestnut.customform.domain.dto.CustomFormEditDTO;
|
||||
import com.chestnut.customform.domain.dto.CreateCustomFormRequest;
|
||||
import com.chestnut.customform.domain.dto.UpdateCustomFormRequest;
|
||||
import com.chestnut.customform.domain.vo.CustomFormVO;
|
||||
import com.chestnut.customform.permission.CustomFormPriv;
|
||||
import com.chestnut.customform.rule.ICustomFormLimitRule;
|
||||
@ -109,27 +109,25 @@ public class CustomFormController extends BaseRestController {
|
||||
@Log(title = "新增自定义表单", businessType = BusinessType.INSERT)
|
||||
@Priv(type = AdminUserType.TYPE, value = CustomFormPriv.Add)
|
||||
@PostMapping
|
||||
public R<?> add(@RequestBody @Validated CustomFormAddDTO dto) {
|
||||
public R<?> add(@RequestBody @Validated CreateCustomFormRequest req) {
|
||||
CmsSite site = this.siteService.getCurrentSite(ServletUtils.getRequest());
|
||||
dto.setOperator(StpAdminUtil.getLoginUser());
|
||||
dto.setSiteId(site.getSiteId());
|
||||
this.customFormService.addCustomForm(dto);
|
||||
req.setSiteId(site.getSiteId());
|
||||
this.customFormService.addCustomForm(req);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Log(title = "编辑自定义表单", businessType = BusinessType.UPDATE)
|
||||
@Priv(type = AdminUserType.TYPE, value = {CustomFormPriv.Add, CustomFormPriv.Edit})
|
||||
@PutMapping
|
||||
public R<?> edit(@RequestBody @Validated CustomFormEditDTO dto) {
|
||||
dto.setOperator(StpAdminUtil.getLoginUser());
|
||||
this.customFormService.editCustomForm(dto);
|
||||
public R<?> edit(@RequestBody @Validated UpdateCustomFormRequest req) {
|
||||
this.customFormService.editCustomForm(req);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Log(title = "删除自定义表单", businessType = BusinessType.DELETE)
|
||||
@Priv(type = AdminUserType.TYPE, value = CustomFormPriv.Delete)
|
||||
@PostMapping("/delete")
|
||||
public R<?> remove(@RequestBody @Validated @NotEmpty List<Long> formIds) {
|
||||
public R<?> remove(@RequestBody @NotEmpty List<Long> formIds) {
|
||||
this.customFormService.deleteCustomForm(formIds);
|
||||
return R.ok();
|
||||
}
|
||||
@ -137,7 +135,7 @@ public class CustomFormController extends BaseRestController {
|
||||
@Log(title = "发布自定义表单", businessType = BusinessType.UPDATE)
|
||||
@Priv(type = AdminUserType.TYPE, value = { CustomFormPriv.Add, CustomFormPriv.Edit })
|
||||
@PutMapping("/publish")
|
||||
public R<?> publish(@RequestBody @Validated @NotEmpty List<Long> formIds) {
|
||||
public R<?> publish(@RequestBody @NotEmpty List<Long> formIds) {
|
||||
this.customFormService.publishCustomForms(formIds, StpAdminUtil.getLoginUser().getUsername());
|
||||
return R.ok();
|
||||
}
|
||||
@ -145,7 +143,7 @@ public class CustomFormController extends BaseRestController {
|
||||
@Log(title = " 下线自定义表单", businessType = BusinessType.UPDATE)
|
||||
@Priv(type = AdminUserType.TYPE, value = { CustomFormPriv.Add, CustomFormPriv.Edit })
|
||||
@PutMapping("/offline")
|
||||
public R<?> offline(@RequestBody @Validated @NotEmpty List<Long> formIds) throws IOException {
|
||||
public R<?> offline(@RequestBody @NotEmpty List<Long> formIds) throws IOException {
|
||||
this.customFormService.offlineCustomForms(formIds, StpAdminUtil.getLoginUser().getUsername());
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ public class CmsCustomFormData extends BaseModelData implements Serializable {
|
||||
public static final String TABLE_NAME = "cms_cfd_default";
|
||||
|
||||
@TableId(value = "data_id", type = IdType.INPUT)
|
||||
private Long dataId;
|
||||
private String dataId;
|
||||
|
||||
/**
|
||||
* 关联表单ID(元数据模型ID)
|
||||
@ -74,7 +74,7 @@ public class CmsCustomFormData extends BaseModelData implements Serializable {
|
||||
@Override
|
||||
public void setFieldValue(String fieldName, Object fieldValue) {
|
||||
switch(fieldName) {
|
||||
case "data_id" -> this.setDataId(ConvertUtils.toLong(fieldValue));
|
||||
case "data_id" -> this.setDataId(ConvertUtils.toStr(fieldValue));
|
||||
case "model_id" -> this.setModelId(ConvertUtils.toLong(fieldValue));
|
||||
case "site_id" -> this.setSiteId(ConvertUtils.toLong(fieldValue));
|
||||
case "client_ip" -> this.setClientIp(ConvertUtils.toStr(fieldValue));
|
||||
|
||||
@ -19,9 +19,9 @@ import com.chestnut.common.security.domain.BaseDTO;
|
||||
import com.chestnut.system.fixed.dict.YesOrNo;
|
||||
import com.chestnut.system.validator.Dict;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
/**
|
||||
* 自定义表单添加DTO
|
||||
@ -31,7 +31,7 @@ import lombok.Setter;
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class CustomFormAddDTO extends BaseDTO {
|
||||
public class CreateCustomFormRequest extends BaseDTO {
|
||||
|
||||
/**
|
||||
* 站点ID
|
||||
@ -42,29 +42,34 @@ public class CustomFormAddDTO extends BaseDTO {
|
||||
* 名称
|
||||
*/
|
||||
@NotBlank
|
||||
@Length(max = 100)
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
@NotBlank
|
||||
@Length(max = 50)
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 模型数据表
|
||||
*/
|
||||
@NotBlank
|
||||
@Length(max = 100)
|
||||
private String tableName;
|
||||
|
||||
/**
|
||||
* 是否需要验证码
|
||||
*/
|
||||
@NotBlank
|
||||
@Dict(YesOrNo.TYPE)
|
||||
private String needCaptcha;
|
||||
|
||||
/**
|
||||
* 是否需要会员登录
|
||||
*/
|
||||
@NotBlank
|
||||
@Dict(YesOrNo.TYPE)
|
||||
private String needLogin;
|
||||
|
||||
@ -72,10 +77,12 @@ public class CustomFormAddDTO extends BaseDTO {
|
||||
* 提交用户唯一性限制(无限制、IP、浏览器指纹)
|
||||
*/
|
||||
@NotBlank
|
||||
@Length(max = 20)
|
||||
private String ruleLimit;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@Length(max = 500)
|
||||
private String remark;
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2022-2025 兮玥(190785909@qq.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chestnut.customform.domain.dto;
|
||||
|
||||
import com.chestnut.contentcore.domain.pojo.PublishPipeTemplate;
|
||||
import com.chestnut.system.validator.LongId;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 自定义表单编辑DTO
|
||||
*
|
||||
* @author 兮玥
|
||||
* @email 190785909@qq.com
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class UpdateCustomFormRequest extends CreateCustomFormRequest {
|
||||
|
||||
@LongId
|
||||
private Long formId;
|
||||
|
||||
/**
|
||||
* 模板配置
|
||||
*/
|
||||
private List<PublishPipeTemplate> templates;
|
||||
}
|
||||
@ -17,11 +17,9 @@ package com.chestnut.customform.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.chestnut.customform.domain.CmsCustomForm;
|
||||
import com.chestnut.customform.domain.dto.CustomFormAddDTO;
|
||||
import com.chestnut.customform.domain.dto.CustomFormEditDTO;
|
||||
import com.chestnut.customform.domain.dto.CreateCustomFormRequest;
|
||||
import com.chestnut.customform.domain.dto.UpdateCustomFormRequest;
|
||||
import com.chestnut.customform.rule.ICustomFormLimitRule;
|
||||
import com.chestnut.xmodel.domain.XModel;
|
||||
import com.chestnut.xmodel.dto.XModelDTO;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
@ -36,7 +34,7 @@ public interface ICustomFormService extends IService<CmsCustomForm> {
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
void addCustomForm(CustomFormAddDTO dto);
|
||||
void addCustomForm(CreateCustomFormRequest dto);
|
||||
|
||||
/**
|
||||
* 编辑自定义表单
|
||||
@ -44,7 +42,7 @@ public interface ICustomFormService extends IService<CmsCustomForm> {
|
||||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
void editCustomForm(CustomFormEditDTO dto);
|
||||
void editCustomForm(UpdateCustomFormRequest dto);
|
||||
|
||||
/**
|
||||
* 删除自定义表单
|
||||
|
||||
@ -36,8 +36,8 @@ import com.chestnut.contentcore.util.TemplateUtils;
|
||||
import com.chestnut.customform.CmsCustomFormMetaModelType;
|
||||
import com.chestnut.customform.CustomFormConsts;
|
||||
import com.chestnut.customform.domain.CmsCustomForm;
|
||||
import com.chestnut.customform.domain.dto.CustomFormAddDTO;
|
||||
import com.chestnut.customform.domain.dto.CustomFormEditDTO;
|
||||
import com.chestnut.customform.domain.dto.CreateCustomFormRequest;
|
||||
import com.chestnut.customform.domain.dto.UpdateCustomFormRequest;
|
||||
import com.chestnut.customform.fixed.dict.CustomFormStatus;
|
||||
import com.chestnut.customform.mapper.CustomFormMapper;
|
||||
import com.chestnut.customform.publishpipe.PublishPipeProp_CustomFormTemplate;
|
||||
@ -84,7 +84,7 @@ public class CustomFormServiceImpl extends ServiceImpl<CustomFormMapper, CmsCust
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addCustomForm(CustomFormAddDTO dto) {
|
||||
public void addCustomForm(CreateCustomFormRequest dto) {
|
||||
CmsCustomForm customForm = new CmsCustomForm();
|
||||
customForm.setFormId(IdUtils.getSnowflakeId());
|
||||
customForm.setSiteId(dto.getSiteId());
|
||||
@ -111,7 +111,7 @@ public class CustomFormServiceImpl extends ServiceImpl<CustomFormMapper, CmsCust
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void editCustomForm(CustomFormEditDTO dto) {
|
||||
public void editCustomForm(UpdateCustomFormRequest dto) {
|
||||
CmsCustomForm form = this.getById(dto.getFormId());
|
||||
Assert.notNull(form, () -> CommonErrorCode.DATA_NOT_FOUND_BY_ID.exception("formId", dto.getFormId()));
|
||||
|
||||
|
||||
@ -114,19 +114,19 @@ public class CmsCustomFormTag extends AbstractTag {
|
||||
String siteRoot = SiteUtils.getSiteRoot(site, context.getPublishPipeCode());
|
||||
String staticFileName = form.getCode() + "." + site.getStaticSuffix(context.getPublishPipeCode());
|
||||
String staticFilePath = CustomFormConsts.STATICIZE_DIRECTORY + staticFileName;
|
||||
if (ssi) {
|
||||
// 读取自定义表单静态化内容
|
||||
String staticContent = templateService.getTemplateStaticContentCache(templateKey);
|
||||
if (Objects.isNull(staticContent) || !new File(siteRoot + staticFilePath).exists()) {
|
||||
staticContent = this.processTemplate(env, form, site, context.getPublishPipeCode(), templateKey);
|
||||
|
||||
String staticContent = templateService.getTemplateStaticContentCache(templateKey);
|
||||
if (Objects.isNull(staticContent) || !new File(siteRoot + staticFilePath).exists()) {
|
||||
staticContent = this.processTemplate(env, form, site, context.getPublishPipeCode(), templateKey);
|
||||
this.templateService.setTemplateStaticContentCache(templateKey, staticContent);
|
||||
if (ssi) {
|
||||
FileUtils.writeStringToFile(new File(siteRoot + staticFilePath), staticContent, StandardCharsets.UTF_8);
|
||||
this.templateService.setTemplateStaticContentCache(templateKey, staticContent);
|
||||
}
|
||||
String prefix = SiteUtils.getPublishPipePrefix(site, context.getPublishPipeCode(), context.isPreview());
|
||||
}
|
||||
if (ssi) {
|
||||
String prefix = CmsIncludeTag.getIncludePathPrefix(context.getPublishPipeCode(), site);
|
||||
env.getOut().write(StringUtils.messageFormat(CmsIncludeTag.SSI_INCLUDE_TAG, prefix + staticFilePath));
|
||||
} else {
|
||||
// 非ssi模式无法使用缓存
|
||||
String staticContent = this.processTemplate(env, form, site, context.getPublishPipeCode(), templateKey);
|
||||
env.getOut().write(staticContent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-dynamic</artifactId>
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
package com.chestnut.cms.dynamic.listener;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.chestnut.cms.dynamic.domain.CmsDynamicPage;
|
||||
import com.chestnut.cms.dynamic.service.IDynamicPageService;
|
||||
import com.chestnut.common.async.AsyncTaskManager;
|
||||
@ -26,6 +27,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@ -40,11 +43,21 @@ public class DynamicListener {
|
||||
try {
|
||||
long total = this.dynamicPageService
|
||||
.count(new LambdaQueryWrapper<CmsDynamicPage>().eq(CmsDynamicPage::getSiteId, site.getSiteId()));
|
||||
long lastId = 0;
|
||||
for (long i = 0; i * pageSize < total; i++) {
|
||||
AsyncTaskManager.setTaskProgressInfo((int) (i * pageSize * 100 / total),
|
||||
"正在删除自定义动态模板页面数据:" + (i * pageSize) + "/" + total);
|
||||
this.dynamicPageService.remove(new LambdaQueryWrapper<CmsDynamicPage>().eq(CmsDynamicPage::getSiteId, site.getSiteId())
|
||||
.last("limit " + pageSize));
|
||||
Page<CmsDynamicPage> pages = this.dynamicPageService.lambdaQuery()
|
||||
.select(CmsDynamicPage::getPageId)
|
||||
.eq(CmsDynamicPage::getSiteId, site.getSiteId())
|
||||
.gt(CmsDynamicPage::getPageId, lastId)
|
||||
.orderByAsc(CmsDynamicPage::getPageId)
|
||||
.page(Page.of(1, pageSize, false));
|
||||
if (!pages.getRecords().isEmpty()) {
|
||||
List<Long> pageIds = pages.getRecords().stream().map(CmsDynamicPage::getPageId).toList();
|
||||
this.dynamicPageService.removeBatchByIds(pageIds);
|
||||
lastId = pageIds.get(pageIds.size() - 1);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
AsyncTaskManager.addErrMessage("删除自定义动态模板页面数据错误:" + e.getMessage());
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
DYNAMIC_PAGE_INIT_DATA.Member=登錄會員
|
||||
DYNAMIC_PAGE_INIT_DATA.Pagination=分頁參數
|
||||
|
||||
FREEMARKER.FUNC.customDynamicPageLink.DESC=獲取自定義動態模板頁面鏈接,例如:`${customDynamicPageLink('Test','a=1&b=2',true)}`
|
||||
FREEMARKER.FUNC.customDynamicPageLink.DESC=獲取自定義動態模板頁面連結,例如:`${customDynamicPageLink('Test','a=1&b=2',true)}`
|
||||
FREEMARKER.FUNC.customDynamicPageLink.Arg1.Name=自定義動態模板編碼
|
||||
FREEMARKER.FUNC.customDynamicPageLink.Arg2.Name=鏈接參數
|
||||
FREEMARKER.FUNC.customDynamicPageLink.Arg2.Name=連結參數
|
||||
FREEMARKER.FUNC.customDynamicPageLink.Arg3.Name=忽略`sid/pp`參數
|
||||
|
||||
MONITORED.CACHE.DYNAMIC_PAGE=動態模板頁
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-exmodel</artifactId>
|
||||
|
||||
@ -168,14 +168,14 @@ public class EXModelCoreDataHandler implements ICoreDataHandler {
|
||||
try {
|
||||
Long dataId = switch (data.getDataType()) {
|
||||
case ExtendModelDataType.SITE -> context.getSite().getSiteId();
|
||||
case ExtendModelDataType.CATALOG -> context.getCatalogIdMap().get(data.getDataId());
|
||||
case ExtendModelDataType.CONTENT -> context.getContentIdMap().get(data.getDataId());
|
||||
case ExtendModelDataType.CATALOG -> context.getCatalogIdMap().get(ConvertUtils.toLong(data.getDataId()));
|
||||
case ExtendModelDataType.CONTENT -> context.getContentIdMap().get(ConvertUtils.toLong(data.getDataId()));
|
||||
default -> null;
|
||||
};
|
||||
if (Objects.isNull(dataId)) {
|
||||
throw new RuntimeException("Old `data_id` linked data is missing.");
|
||||
}
|
||||
data.setDataId(dataId);
|
||||
data.setDataId(dataId.toString());
|
||||
data.setModelId(modelIdMapping.get(data.getModelId()));
|
||||
// 处理图片和富文本内部链接
|
||||
MetaModel model = modelService.getMetaModel(data.getModelId());
|
||||
|
||||
@ -32,10 +32,10 @@ import com.chestnut.exmodel.CmsExtendMetaModelType;
|
||||
import com.chestnut.exmodel.permission.EXModelPriv;
|
||||
import com.chestnut.exmodel.service.ExModelService;
|
||||
import com.chestnut.system.security.AdminUserType;
|
||||
import com.chestnut.system.security.StpAdminUtil;
|
||||
import com.chestnut.system.validator.LongId;
|
||||
import com.chestnut.xmodel.domain.XModel;
|
||||
import com.chestnut.xmodel.dto.XModelDTO;
|
||||
import com.chestnut.xmodel.dto.CreateXModelRequest;
|
||||
import com.chestnut.xmodel.dto.UpdateXModelRequest;
|
||||
import com.chestnut.xmodel.dto.XModelFieldDataDTO;
|
||||
import com.chestnut.xmodel.service.IModelService;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
@ -95,29 +95,26 @@ public class EXModelController extends BaseRestController {
|
||||
@Log(title = "新增扩展模型", businessType = BusinessType.INSERT)
|
||||
@Priv(type = AdminUserType.TYPE, value = EXModelPriv.Add)
|
||||
@PostMapping
|
||||
public R<?> add(@RequestBody @Validated XModelDTO dto) {
|
||||
public R<?> add(@RequestBody @Validated CreateXModelRequest req) {
|
||||
CmsSite site = this.siteService.getCurrentSite(ServletUtils.getRequest());
|
||||
dto.setOwnerType(CmsExtendMetaModelType.TYPE);
|
||||
dto.setOwnerId(site.getSiteId().toString());
|
||||
dto.setOperator(StpAdminUtil.getLoginUser());
|
||||
this.modelService.addModel(dto);
|
||||
req.setOwnerType(CmsExtendMetaModelType.TYPE);
|
||||
req.setOwnerId(site.getSiteId().toString());
|
||||
this.modelService.addModel(req);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Log(title = "编辑扩展模板", businessType = BusinessType.UPDATE)
|
||||
@Priv(type = AdminUserType.TYPE, value = { EXModelPriv.Add, EXModelPriv.Edit })
|
||||
@PutMapping
|
||||
public R<?> edit(@RequestBody @Validated XModelDTO dto) {
|
||||
dto.setOperator(StpAdminUtil.getLoginUser());
|
||||
this.modelService.editModel(dto);
|
||||
public R<?> edit(@RequestBody @Validated UpdateXModelRequest req) {
|
||||
this.modelService.editModel(req);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Log(title = "删除扩展模型", businessType = BusinessType.DELETE)
|
||||
@Priv(type = AdminUserType.TYPE, value = EXModelPriv.Delete)
|
||||
@PostMapping("/delete")
|
||||
public R<?> remove(@RequestBody @Validated @NotEmpty List<XModelDTO> dtoList) {
|
||||
List<Long> modelIds = dtoList.stream().map(XModelDTO::getModelId).toList();
|
||||
public R<?> remove(@RequestBody @Validated @NotEmpty List<Long> modelIds) {
|
||||
this.modelService.deleteModel(modelIds);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ public class CmsExtendModelData extends BaseModelData {
|
||||
/**
|
||||
* 关联数据ID(联合主键)
|
||||
*/
|
||||
private Long dataId;
|
||||
private String dataId;
|
||||
|
||||
/**
|
||||
* 关联数据类型(联合主键)
|
||||
@ -51,7 +51,7 @@ public class CmsExtendModelData extends BaseModelData {
|
||||
@Override
|
||||
public void setFieldValue(String fieldName, Object fieldValue) {
|
||||
switch(fieldName) {
|
||||
case "data_id" -> this.setDataId(ConvertUtils.toLong(fieldValue));
|
||||
case "data_id" -> this.setDataId(ConvertUtils.toStr(fieldValue));
|
||||
case "data_type" -> this.setDataType(ConvertUtils.toStr(fieldValue));
|
||||
case "model_id" -> this.setModelId(ConvertUtils.toLong(fieldValue));
|
||||
default -> super.setFieldValue(fieldName, fieldValue);
|
||||
|
||||
@ -22,4 +22,4 @@ DICT.ExtendModelDataType.content=內容
|
||||
META.CONTROL_TYPE.CMSImage=圖片上傳
|
||||
META.CONTROL_TYPE.UEditor=富文本編輯器
|
||||
META.CONTROL_TYPE.CMSContentSelect=內容選擇
|
||||
META.CONTROL_TYPE.CMSResource=資源文件上傳
|
||||
META.CONTROL_TYPE.CMSResource=資源檔案上傳
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-image</artifactId>
|
||||
|
||||
@ -11,15 +11,14 @@ CMS.IMAGE.CONTENT_ID=所屬內容ID
|
||||
CMS.IMAGE.SITE_ID=所屬站點ID
|
||||
CMS.IMAGE.TITLE=標題
|
||||
CMS.IMAGE.DESC=簡介
|
||||
CMS.IMAGE.FILE_NAME=圖片文件名
|
||||
CMS.IMAGE.FILE_NAME=圖片原檔案名
|
||||
CMS.IMAGE.PATH=圖片資源路徑
|
||||
CMS.IMAGE.SRC=圖片訪問路徑
|
||||
CMS.IMAGE.TYPE=圖片類型
|
||||
CMS.IMAGE.FILE_SIZE=圖片大小
|
||||
CMS.IMAGE.WIDTH=圖片寬度
|
||||
CMS.IMAGE.HEIGHT=圖片高度
|
||||
CMS.IMAGE.REDIRECT_URL=跳轉鏈接
|
||||
|
||||
CMS.IMAGE.REDIRECT_URL=跳轉連結
|
||||
|
||||
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-link</artifactId>
|
||||
|
||||
@ -28,6 +28,6 @@ import freemarker.template.TemplateException;
|
||||
public class LinkGroupNotFoundTemplateException extends TemplateException {
|
||||
|
||||
public LinkGroupNotFoundTemplateException(String linkGroupCode, Environment env) {
|
||||
super(I18nUtils.get("FREEMARKER.ERR.LinkGroupNotFound"), env);
|
||||
super(I18nUtils.parse("FREEMARKER.ERR.LinkGroupNotFound", env.getLocale(), linkGroupCode), env);
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
package com.chestnut.link.listener;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.chestnut.common.async.AsyncTaskManager;
|
||||
import com.chestnut.contentcore.domain.CmsSite;
|
||||
import com.chestnut.contentcore.listener.event.BeforeSiteDeleteEvent;
|
||||
@ -28,6 +29,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@ -45,20 +48,40 @@ public class LinkListener {
|
||||
// 删除友链数据
|
||||
long total = this.linkService
|
||||
.count(new LambdaQueryWrapper<CmsLink>().eq(CmsLink::getSiteId, site.getSiteId()));
|
||||
long lastId = 0;
|
||||
for (long i = 0; i * pageSize < total; i++) {
|
||||
AsyncTaskManager.setTaskProgressInfo((int) (i * pageSize * 100 / total),
|
||||
"正在删除友链数据:" + (i * pageSize) + "/" + total);
|
||||
this.linkService.remove(new LambdaQueryWrapper<CmsLink>().eq(CmsLink::getSiteId, site.getSiteId())
|
||||
.last("limit " + pageSize));
|
||||
Page<CmsLink> links = this.linkService.lambdaQuery()
|
||||
.select(CmsLink::getLinkId)
|
||||
.eq(CmsLink::getSiteId, site.getSiteId())
|
||||
.gt(CmsLink::getLinkId, lastId)
|
||||
.orderByAsc(CmsLink::getLinkId)
|
||||
.page(Page.of(1, pageSize, false));
|
||||
if (!links.getRecords().isEmpty()) {
|
||||
List<Long> linkIds = links.getRecords().stream().map(CmsLink::getLinkId).toList();
|
||||
this.linkService.removeBatchByIds(linkIds);
|
||||
lastId = linkIds.get(linkIds.size() - 1);
|
||||
}
|
||||
}
|
||||
// 删除友链分组数据
|
||||
total = this.linkGroupService
|
||||
.count(new LambdaQueryWrapper<CmsLinkGroup>().eq(CmsLinkGroup::getSiteId, site.getSiteId()));
|
||||
lastId = 0;
|
||||
for (long i = 0; i * pageSize < total; i++) {
|
||||
AsyncTaskManager.setTaskProgressInfo((int) (i * pageSize * 100 / total),
|
||||
"正在删除友链分组数据:" + (i * pageSize) + "/" + total);
|
||||
this.linkGroupService.remove(new LambdaQueryWrapper<CmsLinkGroup>()
|
||||
.eq(CmsLinkGroup::getSiteId, site.getSiteId()).last("limit " + pageSize));
|
||||
Page<CmsLinkGroup> linkGroups = this.linkGroupService.lambdaQuery()
|
||||
.select(CmsLinkGroup::getLinkGroupId)
|
||||
.eq(CmsLinkGroup::getSiteId, site.getSiteId())
|
||||
.gt(CmsLinkGroup::getLinkGroupId, lastId)
|
||||
.orderByAsc(CmsLinkGroup::getLinkGroupId)
|
||||
.page(Page.of(1, pageSize, false));
|
||||
if (!linkGroups.getRecords().isEmpty()) {
|
||||
List<Long> linkGroupIds = linkGroups.getRecords().stream().map(CmsLinkGroup::getLinkGroupId).toList();
|
||||
this.linkGroupService.removeBatchByIds(linkGroupIds);
|
||||
lastId = linkGroupIds.get(linkGroupIds.size() - 1);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
AsyncTaskManager.addErrMessage("删除友链数据错误:" + e.getMessage());
|
||||
|
||||
@ -8,7 +8,7 @@ FREEMARKER.TAG.cms_link.NAME=友链列表标签
|
||||
FREEMARKER.TAG.cms_link.DESC=获取友链数据列表,内嵌`<#list DataList as link>${link.name}</#list>`遍历数据
|
||||
FREEMARKER.TAG.cms_link.code=友链分组编码
|
||||
|
||||
FREEMARKER.ERR.LinkGroupNotFound=友链分组数据不存在。
|
||||
FREEMARKER.ERR.LinkGroupNotFound=友链分组`{0}`不存在。
|
||||
|
||||
CMS.LINK_GROUP.ID=友链分组ID
|
||||
CMS.LINK_GROUP.SITE_ID=所属站点ID
|
||||
|
||||
@ -8,7 +8,7 @@ FREEMARKER.TAG.cms_link.NAME=Friend-link list tag
|
||||
FREEMARKER.TAG.cms_link.DESC=Fetch friend-link list, use `<#list>` in tag like `<#list DataList as link>${link.name}</#list>` to walk through the list of friend-links.
|
||||
FREEMARKER.TAG.cms_link.code=Friend-link group code
|
||||
|
||||
FREEMARKER.ERR.LinkGroupNotFound=Friend-link group not exists.
|
||||
FREEMARKER.ERR.LinkGroupNotFound=Friend-link group `{0}` not exists.
|
||||
|
||||
CMS.LINK_GROUP.ID=ID
|
||||
CMS.LINK_GROUP.SITE_ID=Site ID
|
||||
|
||||
@ -8,7 +8,7 @@ FREEMARKER.TAG.cms_link.NAME=友鏈列表標籤
|
||||
FREEMARKER.TAG.cms_link.DESC=獲取友鏈數據列表,內嵌`<#list DataList as link>${link.name}</#list>`遍曆數據
|
||||
FREEMARKER.TAG.cms_link.code=友鏈分組編碼
|
||||
|
||||
FREEMARKER.ERR.LinkGroupNotFound=友鏈分組數據不存在。
|
||||
FREEMARKER.ERR.LinkGroupNotFound=友鏈分組`{0}`不存在。
|
||||
|
||||
CMS.LINK_GROUP.ID=友鏈分組ID
|
||||
CMS.LINK_GROUP.SITE_ID=所屬站點ID
|
||||
@ -16,14 +16,12 @@ CMS.LINK_GROUP.NAME=分組名稱
|
||||
CMS.LINK_GROUP.CODE=分組編碼
|
||||
|
||||
CMS.LINK.ID=友鏈ID
|
||||
CMS.LINK.SITE_ID=所屬站點ID
|
||||
CMS.LINK.GROUP_ID=所屬分組ID
|
||||
CMS.LINK.SITE_ID=站點ID
|
||||
CMS.LINK.GROUP_ID=分組ID
|
||||
CMS.LINK.NAME=名稱
|
||||
CMS.LINK.URL=鏈接
|
||||
CMS.LINK.URL=連結
|
||||
CMS.LINK.LOGO=Logo
|
||||
CMS.LINK.SRC=Logo src
|
||||
|
||||
|
||||
CMS.LINK.SRC=Logo訪問地址
|
||||
|
||||
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-media</artifactId>
|
||||
|
||||
@ -11,25 +11,25 @@ FREEMARKER.TAG.cms_video.DESC=獲取視頻集視頻數據列表,內嵌`<#list
|
||||
FREEMARKER.TAG.cms_video.contentId=視頻內容ID
|
||||
|
||||
CMS.MEDIA.AUDIO.ID=音頻ID
|
||||
CMS.MEDIA.AUDIO.CONTENT_ID=關聯內容ID
|
||||
CMS.MEDIA.AUDIO.SITE_ID=關聯站點ID
|
||||
CMS.MEDIA.AUDIO.CONTENT_ID=所屬內容ID
|
||||
CMS.MEDIA.AUDIO.SITE_ID=所屬站點ID
|
||||
CMS.MEDIA.AUDIO.TITLE=音頻標題
|
||||
CMS.MEDIA.AUDIO.AUTHOR=作者
|
||||
CMS.MEDIA.AUDIO.DESC=簡介
|
||||
CMS.MEDIA.AUDIO.TYPE=音頻類型
|
||||
CMS.MEDIA.AUDIO.PATH=音頻資源路徑
|
||||
CMS.MEDIA.AUDIO.SRC=音頻訪問地址
|
||||
CMS.MEDIA.AUDIO.FILE_SIZE=文件大小,單位:字節
|
||||
CMS.MEDIA.AUDIO.FILE_SIZE=檔案大小,單位:位元組
|
||||
CMS.MEDIA.AUDIO.FORMAT=音頻格式
|
||||
CMS.MEDIA.AUDIO.DURATION=時長,單位:毫秒
|
||||
CMS.MEDIA.AUDIO.DECODER=編碼方式
|
||||
CMS.MEDIA.AUDIO.CHANNELS=聲道數
|
||||
CMS.MEDIA.AUDIO.BIT_RATE=比特率
|
||||
CMS.MEDIA.AUDIO.SAMPLING_RATE=采樣率
|
||||
CMS.MEDIA.AUDIO.SAMPLING_RATE=採樣率
|
||||
|
||||
CMS.MEDIA.VIDEO.ID=視頻ID
|
||||
CMS.MEDIA.VIDEO.CONTENT_ID=關聯內容ID
|
||||
CMS.MEDIA.VIDEO.SITE_ID=關聯站點ID
|
||||
CMS.MEDIA.VIDEO.CONTENT_ID=所屬內容ID
|
||||
CMS.MEDIA.VIDEO.SITE_ID=所屬站點ID
|
||||
CMS.MEDIA.VIDEO.COVER=視頻封面資源路徑
|
||||
CMS.MEDIA.VIDEO.COVER_SRC=視頻封面訪問地址
|
||||
CMS.MEDIA.VIDEO.TITLE=視頻標題
|
||||
@ -37,7 +37,7 @@ CMS.MEDIA.VIDEO.DESC=簡介
|
||||
CMS.MEDIA.VIDEO.TYPE=視頻類型
|
||||
CMS.MEDIA.VIDEO.PATH=視頻資源路徑/第三方引用代碼
|
||||
CMS.MEDIA.VIDEO.SRC=視頻訪問地址
|
||||
CMS.MEDIA.VIDEO.FILE_SIZE=文件大小,單位:字節
|
||||
CMS.MEDIA.VIDEO.FILE_SIZE=檔案大小,單位:位元組
|
||||
CMS.MEDIA.VIDEO.FORMAT=視頻格式
|
||||
CMS.MEDIA.VIDEO.DURATION=時長,單位:毫秒
|
||||
CMS.MEDIA.VIDEO.DECODER=編碼方式
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-member</artifactId>
|
||||
|
||||
@ -19,7 +19,9 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.chestnut.article.ArticleContent;
|
||||
import com.chestnut.article.ArticleContentType;
|
||||
import com.chestnut.article.IArticleBodyFormat;
|
||||
import com.chestnut.article.domain.CmsArticleDetail;
|
||||
import com.chestnut.article.format.ArticleBodyFormat_RichText;
|
||||
import com.chestnut.article.service.IArticleService;
|
||||
import com.chestnut.cms.member.domain.dto.ArticleContributeDTO;
|
||||
import com.chestnut.cms.member.domain.vo.MemberContentVO;
|
||||
@ -27,7 +29,7 @@ import com.chestnut.cms.member.properties.EnableContributeProperty;
|
||||
import com.chestnut.common.domain.R;
|
||||
import com.chestnut.common.exception.CommonErrorCode;
|
||||
import com.chestnut.common.security.anno.Priv;
|
||||
import com.chestnut.common.security.domain.LoginUser;
|
||||
import com.chestnut.common.security.domain.Operator;
|
||||
import com.chestnut.common.security.web.BaseRestController;
|
||||
import com.chestnut.common.utils.Assert;
|
||||
import com.chestnut.common.utils.IdUtils;
|
||||
@ -71,6 +73,7 @@ import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.chestnut.common.utils.SortUtils.getDefaultSortValue;
|
||||
|
||||
@ -111,13 +114,14 @@ public class MemberContributeApiController extends BaseRestController implements
|
||||
if (!ContentStatus.isDraft(xContent.getStatus())) {
|
||||
return R.fail("只能删除待审核的初稿");
|
||||
}
|
||||
if (xContent.getContributorId() != StpMemberUtil.getLoginIdAsLong()) {
|
||||
Operator operator = Operator.of(StpMemberUtil.getLoginUser());
|
||||
if (!Objects.equals(xContent.getContributorId(), operator.getUserId())) {
|
||||
return R.fail("内容ID错误");
|
||||
}
|
||||
|
||||
IContentType contentType = ContentCoreUtils.getContentType(xContent.getContentType());
|
||||
IContent<?> content = contentType.loadContent(xContent);
|
||||
content.setOperator(StpMemberUtil.getLoginUser());
|
||||
content.setOperator(operator);
|
||||
transactionTemplate.executeWithoutResult(transactionStatus -> content.delete());
|
||||
applicationContext.publishEvent(new AfterContentDeleteEvent(this, content));
|
||||
return R.ok();
|
||||
@ -144,10 +148,10 @@ public class MemberContributeApiController extends BaseRestController implements
|
||||
if (!EnableContributeProperty.getValue(catalog.getConfigProps())) {
|
||||
return R.fail("参数`catalogId`异常:" + dto.getCatalogId());
|
||||
}
|
||||
LoginUser loginUser = StpMemberUtil.getLoginUser();
|
||||
Operator operator = Operator.of(StpMemberUtil.getLoginUser());
|
||||
if (IdUtils.validate(dto.getContentId())) {
|
||||
CmsContent cmsContent = this.contentService.dao().getById(dto.getContentId());
|
||||
if (!loginUser.getUserId().equals(cmsContent.getContributorId())) {
|
||||
if (!operator.getUserId().equals(cmsContent.getContributorId())) {
|
||||
return R.fail("内容ID错误");
|
||||
}
|
||||
if (!ContentStatus.isDraft(cmsContent.getStatus())) {
|
||||
@ -163,7 +167,7 @@ public class MemberContributeApiController extends BaseRestController implements
|
||||
cmsContent.setTags(dto.getTags().toArray(String[]::new));
|
||||
// 重置发布状态
|
||||
cmsContent.setStatus(ContentStatus.DRAFT);
|
||||
cmsContent.updateBy(loginUser.getUsername());
|
||||
cmsContent.updateBy(operator.getUsername());
|
||||
if (!dto.getCatalogId().equals(cmsContent.getCatalogId())) {
|
||||
CmsCatalog fromCatalog = this.catalogService.getCatalog(cmsContent.getCatalogId());
|
||||
CmsCatalog toCatalog = this.catalogService.getCatalog(dto.getCatalogId());
|
||||
@ -178,11 +182,16 @@ public class MemberContributeApiController extends BaseRestController implements
|
||||
}
|
||||
CmsArticleDetail articleDetail = this.articleService.dao().getById(cmsContent.getContentId());
|
||||
articleDetail.setContentHtml(dto.getContentHtml());
|
||||
IArticleBodyFormat articleBodyFormat = articleService.getArticleBodyFormat(dto.getFormat());
|
||||
if (Objects.isNull(articleBodyFormat)) {
|
||||
dto.setFormat(ArticleBodyFormat_RichText.ID);
|
||||
}
|
||||
articleDetail.setFormat(dto.getFormat());
|
||||
|
||||
ArticleContent content = new ArticleContent();
|
||||
content.setContentEntity(cmsContent);
|
||||
content.setExtendEntity(articleDetail);
|
||||
content.setOperator(loginUser);
|
||||
content.setOperator(operator);
|
||||
applicationContext.publishEvent(new BeforeContentSaveEvent(this, content, false));
|
||||
content.save();
|
||||
applicationContext.publishEvent(new AfterContentSaveEvent(this, content, false));
|
||||
@ -218,7 +227,7 @@ public class MemberContributeApiController extends BaseRestController implements
|
||||
if (content.hasExtendEntity() && StringUtils.isEmpty(extendEntity.getContentHtml())) {
|
||||
throw CommonErrorCode.NOT_EMPTY.exception("contentHtml");
|
||||
}
|
||||
content.setOperator(StpMemberUtil.getLoginUser());
|
||||
content.setOperator(operator);
|
||||
applicationContext.publishEvent(new BeforeContentSaveEvent(this, content, true));
|
||||
content.add();
|
||||
applicationContext.publishEvent(new AfterContentSaveEvent(this, content, true));
|
||||
|
||||
@ -69,4 +69,9 @@ public class ArticleContributeDTO {
|
||||
* 引导图
|
||||
*/
|
||||
private String logo;
|
||||
|
||||
/**
|
||||
* 文章格式
|
||||
*/
|
||||
private String format;
|
||||
}
|
||||
|
||||
@ -4,10 +4,10 @@ ERRCODE.CMS.MEMBER.NO_CONTRIBUTE_PRIV=無投稿許可權
|
||||
# freemarker模板標籤
|
||||
FREEMARKER.TAG.cms_favorite_content.NAME=收藏內容列表標籤
|
||||
FREEMARKER.TAG.cms_favorite_content.DESC=獲取收藏內容數據列表,內嵌`<#list DataList as content>${content.title}</#list>`遍曆數據
|
||||
FREEMARKER.TAG.cms_favorite_content.uid=用户ID
|
||||
FREEMARKER.TAG.cms_favorite_content.uid=會員ID
|
||||
FREEMARKER.TAG.cms_member_follow.NAME=關注/粉絲列表標籤
|
||||
FREEMARKER.TAG.cms_member_follow.DESC=獲取關注/粉絲數據列表,內嵌`<#list DataList as member>${member.displayName}</#list>`遍曆數據
|
||||
FREEMARKER.TAG.cms_member_follow.uid=用户ID
|
||||
FREEMARKER.TAG.cms_member_follow.uid=會員ID
|
||||
FREEMARKER.TAG.cms_member_follow.type=類型
|
||||
FREEMARKER.TAG.cms_member_follow.type.follow=關注
|
||||
FREEMARKER.TAG.cms_member_follow.type.follower=粉絲
|
||||
@ -18,7 +18,7 @@ FREEMARKER.FUNC.accountUrl.Arg1.Name=會員ID
|
||||
FREEMARKER.FUNC.accountUrl.Arg2.Name=頁面類型
|
||||
FREEMARKER.FUNC.accountUrl.Arg3.Name=是否忽略`sid/pp`參數
|
||||
|
||||
# 动态模板
|
||||
# 動態模板
|
||||
DYNAMIC_PAGE_TYPE.AccountBindEmail.NAME=會員綁定郵箱頁
|
||||
DYNAMIC_PAGE_TYPE.AccountCentre.NAME=會員個人中心頁
|
||||
DYNAMIC_PAGE_TYPE.AccountCentre.ARG.memberId=會員ID
|
||||
@ -38,4 +38,4 @@ CMS.MEMBER.SLOGAN=標語
|
||||
CMS.MEMBER.STAT=統計數據<分類,數量>
|
||||
CMS.MEMBER.MENU=會員菜單
|
||||
CMS.MEMBER.MENU.NAME=會員菜單名稱
|
||||
CMS.MEMBER.MENU.URL=會員菜單鏈接
|
||||
CMS.MEMBER.MENU.URL=會員菜單連結
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-search</artifactId>
|
||||
|
||||
@ -26,7 +26,6 @@ import com.chestnut.common.utils.StringUtils;
|
||||
import com.chestnut.contentcore.domain.CmsSite;
|
||||
import com.chestnut.contentcore.service.ISiteService;
|
||||
import com.chestnut.search.domain.SearchLog;
|
||||
import com.chestnut.search.domain.SearchWord;
|
||||
import com.chestnut.search.service.ISearchLogService;
|
||||
import com.chestnut.system.security.AdminUserType;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -46,7 +45,7 @@ public class CMSSearchLogController extends BaseRestController {
|
||||
|
||||
@Priv(type = AdminUserType.TYPE)
|
||||
@GetMapping
|
||||
public R<?> getPageList(@RequestParam(value = "query", required = false) String query) {
|
||||
public R<?> getPageList(@RequestParam(required = false) String query) {
|
||||
PageRequest pr = this.getPageRequest();
|
||||
CmsSite site = this.siteService.getCurrentSite(ServletUtils.getRequest());
|
||||
Page<SearchLog> page = this.searchLogService.lambdaQuery()
|
||||
|
||||
@ -28,10 +28,11 @@ import com.chestnut.common.utils.StringUtils;
|
||||
import com.chestnut.contentcore.domain.CmsSite;
|
||||
import com.chestnut.contentcore.service.ISiteService;
|
||||
import com.chestnut.search.domain.SearchWord;
|
||||
import com.chestnut.search.domain.dto.CreateSearchWordRequest;
|
||||
import com.chestnut.search.service.ISearchWordService;
|
||||
import com.chestnut.system.security.AdminUserType;
|
||||
import com.chestnut.system.security.StpAdminUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Priv(type = AdminUserType.TYPE)
|
||||
@ -45,7 +46,7 @@ public class CMSSearchWordStatController extends BaseRestController {
|
||||
private final ISearchWordService searchWordStatService;
|
||||
|
||||
@GetMapping
|
||||
public R<?> getPageList(@RequestParam(value = "query", required = false) String query) {
|
||||
public R<?> getPageList(@RequestParam(required = false) String query) {
|
||||
PageRequest pr = this.getPageRequest();
|
||||
CmsSite site = this.siteService.getCurrentSite(ServletUtils.getRequest());
|
||||
Page<SearchWord> page = this.searchWordStatService.lambdaQuery()
|
||||
@ -58,11 +59,10 @@ public class CMSSearchWordStatController extends BaseRestController {
|
||||
|
||||
@Log(title = "新增搜索词", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public R<?> addWord(@RequestBody SearchWord wordStat) {
|
||||
public R<?> addWord(@RequestBody @Validated CreateSearchWordRequest req) {
|
||||
CmsSite site = this.siteService.getCurrentSite(ServletUtils.getRequest());
|
||||
wordStat.setSource(CmsSearchConstants.generateSearchSource(site.getSiteId()));
|
||||
wordStat.createBy(StpAdminUtil.getLoginUser().getUsername());
|
||||
this.searchWordStatService.addWord(wordStat);
|
||||
req.setSource(CmsSearchConstants.generateSearchSource(site.getSiteId()));
|
||||
this.searchWordStatService.addWord(req);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
@ -54,6 +54,7 @@ import com.chestnut.xmodel.core.IMetaModelType;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -85,9 +86,9 @@ public class ContentIndexController extends BaseRestController {
|
||||
}
|
||||
|
||||
@GetMapping("/contents")
|
||||
public R<?> selectDocumentList(@RequestParam(value = "query", required = false) String query,
|
||||
public R<?> selectDocumentList(@RequestParam(value = "query", required = false) @Length(max = 200) String query,
|
||||
@RequestParam(value = "onlyTitle", required = false ,defaultValue = "false") Boolean onlyTitle,
|
||||
@RequestParam(value = "contentType", required = false) String contentType) throws ElasticsearchException, IOException {
|
||||
@RequestParam(value = "contentType", required = false) @Length(max = 20) String contentType) throws ElasticsearchException, IOException {
|
||||
this.checkElasticSearchEnabled();
|
||||
PageRequest pr = this.getPageRequest();
|
||||
CmsSite site = this.siteService.getCurrentSite(ServletUtils.getRequest());
|
||||
|
||||
@ -19,7 +19,9 @@ import com.chestnut.cms.search.impl.SearchDynamicPageType;
|
||||
import com.chestnut.common.security.web.BaseRestController;
|
||||
import com.chestnut.common.utils.ServletUtils;
|
||||
import com.chestnut.contentcore.service.impl.DynamicPageService;
|
||||
import com.chestnut.system.validator.LongId;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
@ -44,11 +46,11 @@ public class CmsSearchController extends BaseRestController {
|
||||
private final DynamicPageService dynamicPageService;
|
||||
|
||||
@GetMapping(SearchDynamicPageType.REQUEST_PATH)
|
||||
public void searchPage(@RequestParam(value ="q", required = false, defaultValue = "") @Length(max = 50) String query,
|
||||
@RequestParam("sid") Long siteId,
|
||||
@RequestParam("pp") String publishPipeCode,
|
||||
public void searchPage(@RequestParam(value ="q", required = false, defaultValue = "") @Length(max = 200) String query,
|
||||
@RequestParam("sid") @LongId Long siteId,
|
||||
@RequestParam("pp") @NotBlank @Length(max = 50) String publishPipeCode,
|
||||
@RequestParam(value = "ot", required = false ,defaultValue = "false") Boolean onlyTitle,
|
||||
@RequestParam(value = "ct", required = false) String contentType,
|
||||
@RequestParam(value = "ct", required = false) @Length(max = 20) String contentType,
|
||||
@RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
|
||||
@RequestParam(required = false, defaultValue = "false") Boolean preview,
|
||||
HttpServletResponse response)
|
||||
|
||||
@ -40,8 +40,9 @@ import com.chestnut.search.SearchConsts;
|
||||
import com.chestnut.search.service.ISearchLogService;
|
||||
import com.chestnut.system.validator.LongId;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
@ -51,6 +52,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.List;
|
||||
@ -65,6 +67,9 @@ import java.util.stream.Collectors;
|
||||
@RequestMapping("/api/cms/search")
|
||||
public class SearchApiController extends BaseRestController {
|
||||
|
||||
private static final String SORT_SCORE = "1"; // 排序方式:相关度
|
||||
private static final String SORT_PUBLISH_DATE = "2"; // 排序方式:发布时间
|
||||
|
||||
private final ICatalogService catalogService;
|
||||
|
||||
private final ElasticsearchClient esClient;
|
||||
@ -75,50 +80,81 @@ public class SearchApiController extends BaseRestController {
|
||||
|
||||
@GetMapping("/query")
|
||||
public R<?> selectDocumentList(
|
||||
@RequestParam(value = "sid") Long siteId,
|
||||
@RequestParam(value = "pp") String publishPipeCode,
|
||||
@RequestParam(value = "q") @Length(max = 50) String query,
|
||||
@RequestParam(value = "ot", required = false ,defaultValue = "false") Boolean onlyTitle,
|
||||
@RequestParam(value = "ct", required = false) String contentType,
|
||||
@RequestParam(value = "page", required = false, defaultValue = "1") @Min(1) Integer page,
|
||||
@RequestParam(value = "sid") Long siteId, // 站点ID
|
||||
@RequestParam(value = "pp") String publishPipeCode, // 发布通道
|
||||
@RequestParam(value = "q") @Length(max = 50) String query, // 检索词
|
||||
@RequestParam(value = "ot", required = false ,defaultValue = "false") Boolean onlyTitle, // 是否只查标题
|
||||
@RequestParam(value = "ct", required = false) String contentType, // 类型类型
|
||||
@RequestParam(value = "ts", required = false) String[] tags, // 标签列表
|
||||
@RequestParam(value = "st", required = false, defaultValue = SORT_SCORE) String sortType, // 排序方式:1 = 相关度,2 = 发布时间
|
||||
@RequestParam(value = "bt", required = false) LocalDate beginTime, // 发布时间Begin
|
||||
@RequestParam(value = "et", required = false) LocalDate endTime, // 发布时间End
|
||||
@RequestParam(value = "page", required = false, defaultValue = "1") @Min(1) Integer page, // 页码
|
||||
@RequestParam(value = "size", required = false, defaultValue = "10") @Min(1) Integer pageSize, // 每页数量
|
||||
@RequestParam(value = "preview", required = false, defaultValue = "false") Boolean preview) throws ElasticsearchException, IOException {
|
||||
int pageSize = 10;
|
||||
String indexName = CmsSearchConstants.indexName(siteId.toString());
|
||||
SearchResponse<ObjectNode> sr = esClient.search(s -> {
|
||||
s.index(indexName) // 索引
|
||||
.query(q ->
|
||||
q.bool(b -> {
|
||||
if (StringUtils.isNotEmpty(contentType)) {
|
||||
b.must(must -> must.term(tq -> tq.field("contentType.keyword").value(contentType)));
|
||||
}
|
||||
if (StringUtils.isNotEmpty(query)) {
|
||||
if (onlyTitle) {
|
||||
b.must(must -> must
|
||||
.match(match -> match
|
||||
.analyzer(SearchConsts.IKAnalyzeType_Smart)
|
||||
.field("title")
|
||||
.query(query)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
b.must(must -> must
|
||||
.multiMatch(match -> match
|
||||
.analyzer(SearchConsts.IKAnalyzeType_Smart)
|
||||
.fields("title^10", "fullText^1")
|
||||
.query(query)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return b;
|
||||
})
|
||||
);
|
||||
.query(q ->
|
||||
q.bool(b -> {
|
||||
if (StringUtils.isNotEmpty(contentType)) {
|
||||
b.must(must -> must.term(tq -> tq.field("contentType.keyword").value(contentType)));
|
||||
}
|
||||
if (StringUtils.isNotEmpty(query)) {
|
||||
if (onlyTitle) {
|
||||
b.must(must -> must
|
||||
.match(match -> match
|
||||
.analyzer(SearchConsts.IKAnalyzeType_Smart)
|
||||
.field("title")
|
||||
.query(query)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
b.must(must -> must
|
||||
.multiMatch(match -> match
|
||||
.analyzer(SearchConsts.IKAnalyzeType_Smart)
|
||||
.fields("title^10", "fullText^1")
|
||||
.query(query)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
if (StringUtils.isNotEmpty(tags)) {
|
||||
b.must(should -> {
|
||||
for (String tag : tags) {
|
||||
should.constantScore(cs ->
|
||||
cs.boost(1F).filter(f ->
|
||||
f.match(m ->
|
||||
m.field("tags").query(tag))));
|
||||
}
|
||||
return should;
|
||||
});
|
||||
}
|
||||
if (Objects.nonNull(beginTime) || Objects.nonNull(endTime)) {
|
||||
b.must(must -> must.range(range ->
|
||||
range.number(num -> {
|
||||
num.field("publishDate");
|
||||
if (Objects.nonNull(beginTime)) {
|
||||
num.gte((double) beginTime.atStartOfDay().toEpochSecond(ZoneOffset.UTC));
|
||||
}
|
||||
if (Objects.nonNull(endTime)) {
|
||||
num.lte((double) endTime.atStartOfDay().toEpochSecond(ZoneOffset.UTC));
|
||||
}
|
||||
return num;
|
||||
})
|
||||
));
|
||||
}
|
||||
return b;
|
||||
})
|
||||
);
|
||||
if (StringUtils.isNotEmpty(query)) {
|
||||
s.highlight(h ->
|
||||
h.fields("title", f -> f.preTags("<font color='red'>").postTags("</font>"))
|
||||
.fields("fullText", f -> f.preTags("<font color='red'>").postTags("</font>")));
|
||||
s.highlight(h ->
|
||||
h.fields("title", f -> f.preTags("<font color='red'>").postTags("</font>"))
|
||||
.fields("fullText", f -> f.preTags("<font color='red'>").postTags("</font>")));
|
||||
}
|
||||
if (SORT_SCORE.equals(sortType)) {
|
||||
s.sort(sort -> sort.field(f -> f.field("_score").order(SortOrder.Desc)));
|
||||
}
|
||||
s.sort(sort -> sort.field(f -> f.field("_score").order(SortOrder.Desc)));
|
||||
s.sort(sort -> sort.field(f -> f.field("publishDate").order(SortOrder.Desc))); // 排序: _score:desc + publishDate:desc
|
||||
// s.source(source -> source.filter(f -> f.excludes("fullText"))); // 过滤字段
|
||||
s.from((page - 1) * pageSize).size(pageSize); // 分页,0开始
|
||||
@ -166,13 +202,13 @@ public class SearchApiController extends BaseRestController {
|
||||
|
||||
@GetMapping("/tag")
|
||||
public R<?> selectDocumentByTag(
|
||||
@RequestParam(value = "sid") Long siteId,
|
||||
@RequestParam(value = "sid") @LongId Long siteId,
|
||||
@RequestParam(value = "cid", required = false, defaultValue = "0") Long catalogId,
|
||||
@RequestParam(value = "pp") String publishPipeCode,
|
||||
@RequestParam(value = "q", required = false) @Length(max = 200) String query,
|
||||
@RequestParam(value = "ct", required = false) String contentType,
|
||||
@RequestParam(value = "pp") @NotBlank @Length(max = 50) String publishPipeCode,
|
||||
@RequestParam(value = "q", required = false) @NotBlank @Length(max = 200) String query,
|
||||
@RequestParam(value = "ct", required = false) @Length(max = 20) String contentType,
|
||||
@RequestParam(value = "page", required = false, defaultValue = "1") @Min(1) Integer page,
|
||||
@RequestParam(value = "size", required = false, defaultValue = "10") @Min(1) Integer size,
|
||||
@RequestParam(value = "size", required = false, defaultValue = "10") @Min(1) @Max(100) Integer size,
|
||||
@RequestParam(value = "preview", required = false, defaultValue = "false") Boolean preview) throws ElasticsearchException, IOException {
|
||||
String indexName = CmsSearchConstants.indexName(siteId.toString());
|
||||
SearchResponse<ObjectNode> sr = esClient.search(s -> {
|
||||
@ -238,9 +274,9 @@ public class SearchApiController extends BaseRestController {
|
||||
@GetMapping("/suggest")
|
||||
public R<List<String>> getSuggestWords(@RequestParam("sid") @LongId Long siteId,
|
||||
@RequestParam(value = "cid", required = false, defaultValue = "0") Long catalogId,
|
||||
@RequestParam(value = "q") @NotEmpty @Length(max = 50) String query,
|
||||
@RequestParam(value = "ct", required = false) String contentType,
|
||||
@RequestParam(value = "size", required = false) Integer size) throws IOException {
|
||||
@RequestParam(value = "q") @NotBlank @Length(max = 200) String query,
|
||||
@RequestParam(value = "ct", required = false) @Length(max = 20) String contentType,
|
||||
@RequestParam(value = "size", required = false) @Min(1) @Max(100) Integer size) throws IOException {
|
||||
String suggester = "title-suggest";
|
||||
String indexName = CmsSearchConstants.indexName(siteId.toString());
|
||||
SearchResponse<ObjectNode> sr = esClient.search(s ->
|
||||
@ -279,11 +315,11 @@ public class SearchApiController extends BaseRestController {
|
||||
|
||||
@GetMapping("/group/catalog")
|
||||
public R<?> groupBy(@RequestParam("sid") @LongId Long siteId,
|
||||
@RequestParam(value = "q") @Length(max = 50) String query,
|
||||
@RequestParam(value = "q") @NotBlank @Length(max = 200) String query,
|
||||
@RequestParam(value = "cid", defaultValue = "0") Long catalogId,
|
||||
@RequestParam(value = "level", defaultValue = "0") Integer level,
|
||||
@RequestParam(value = "ot", required = false ,defaultValue = "false") Boolean onlyTitle,
|
||||
@RequestParam(value = "ct", required = false) String contentType) throws ElasticsearchException, IOException {
|
||||
@RequestParam(value = "ct", required = false) @Length(max = 20) String contentType) throws ElasticsearchException, IOException {
|
||||
CmsCatalog catalog = IdUtils.validate(catalogId) ? catalogService.getCatalog(catalogId) : null;
|
||||
String indexName = CmsSearchConstants.indexName(siteId.toString());
|
||||
SearchResponse<ObjectNode> sr = esClient.search(s ->
|
||||
|
||||
@ -12,8 +12,8 @@ FREEMARKER.TAG.cms_search_content.mode.TagAnd=標籤與檢索,多個標籤英
|
||||
FREEMARKER.TAG.cms_search_content.level=數據獲取範圍(V1.5.6+)
|
||||
FREEMARKER.TAG.cms_search_content.level.Current=當前欄目
|
||||
FREEMARKER.TAG.cms_search_content.level.CurrentAndChild=當前欄目和子欄目
|
||||
FREEMARKER.TAG.cms_search_word.NAME=檢索詞熱詞標籤
|
||||
FREEMARKER.TAG.cms_search_word.DESC=檢索詞熱詞標籤
|
||||
FREEMARKER.TAG.cms_search_word.NAME=搜索熱詞標籤
|
||||
FREEMARKER.TAG.cms_search_word.DESC=搜索熱詞標籤
|
||||
|
||||
CONFIG.CMSSearchAnalyzeType=索引分詞方式
|
||||
|
||||
@ -25,9 +25,10 @@ DYNAMIC_PAGE_TYPE.Search.ARG.ct=內容類型
|
||||
DYNAMIC_PAGE_TYPE.Search.ARG.page=頁碼
|
||||
|
||||
PROGRESS.INFO.BUILDING_INDEX=正在重建欄目索引:{0}
|
||||
PROGRESS.INFO.BUILD_SUCCEED=重建索引完成
|
||||
|
||||
CMS.ES_CONTENT.FULL_TEXT=全文內容
|
||||
CMS.ES_CONTENT.PUBLISH_DATE_TIMESTAMP=發佈時間戳
|
||||
CMS.ES_CONTENT.CREATE_TIME_TIMESTAMP=創建時間戳
|
||||
CMS.ES_CONTENT.PUBLISH_DATE_TIMESTAMP=發布時間戳
|
||||
CMS.ES_CONTENT.CREATE_TIME_TIMESTAMP=建立時間戳
|
||||
CMS.ES_CONTENT.HIT_SCORE=匹配度
|
||||
CMS.ES_CONTENT.EXTEND_DATA=擴展模型數據
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-seo</artifactId>
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-stat</artifactId>
|
||||
|
||||
@ -21,6 +21,6 @@ STAT.MENU.ContentStatByUser=用戶發布統計
|
||||
|
||||
# TAG
|
||||
FREEMARKER.TAG.cms_stat.NAME=訪問統計標籤
|
||||
FREEMARKER.TAG.cms_stat.DESC=用於在模板頁面中插入內置訪問統計腳本代碼
|
||||
FREEMARKER.TAG.cms_stat.DESC=用於在模板頁面中插入內置訪問統計指令碼或直譯式程式代碼
|
||||
|
||||
SCHEDULED_TASK.StatContentCountByStatus=內容發佈統計任務
|
||||
SCHEDULED_TASK.StatContentCountByStatus=內容發布統計任務
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-vote</artifactId>
|
||||
|
||||
@ -3,6 +3,6 @@ FREEMARKER.TAG.cms_vote.NAME=調查問卷列表標籤
|
||||
FREEMARKER.TAG.cms_vote.DESC=獲取調查問卷數據列表,內嵌`<#list DataList as vote>${vote.title}</#list>`遍曆數據
|
||||
FREEMARKER.TAG.cms_vote_subject.NAME=調查問卷主題列表標籤
|
||||
FREEMARKER.TAG.cms_vote_subject.DESC=獲取調查問卷主題數據列表,內嵌`<#list DataList as subject>${subject.title}</#list>`遍曆數據
|
||||
FREEMARKER.TAG.cms_vote_subject.code=調查問卷編碼
|
||||
FREEMARKER.TAG.cms_vote_subject.code=問卷調查編碼
|
||||
|
||||
FREEMARKER.ERR.VOTE_NOT_FOUND=調查問卷數據不存在,code = {0}。
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.chestnut</groupId>
|
||||
<artifactId>chestnut-cms</artifactId>
|
||||
<version>1.5.7</version>
|
||||
<version>1.5.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>chestnut-cms-word</artifactId>
|
||||
|
||||
@ -26,8 +26,8 @@ import com.chestnut.common.utils.StringUtils;
|
||||
import com.chestnut.contentcore.domain.CmsSite;
|
||||
import com.chestnut.contentcore.service.ISiteService;
|
||||
import com.chestnut.system.security.AdminUserType;
|
||||
import com.chestnut.system.security.StpAdminUtil;
|
||||
import com.chestnut.word.domain.HotWordGroup;
|
||||
import com.chestnut.word.domain.dto.CreateHotWordGroupRequest;
|
||||
import com.chestnut.word.permission.WordPriv;
|
||||
import com.chestnut.word.service.IHotWordGroupService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -72,11 +72,7 @@ public class CMSHotWordGroupController extends BaseRestController {
|
||||
List<HotWordGroup> list = this.hotWordGroupService.lambdaQuery()
|
||||
.eq(HotWordGroup::getOwner, currentSite.getSiteId().toString())
|
||||
.list();
|
||||
List<Map<String, Object>> options = new ArrayList<>();
|
||||
list.forEach(g -> {
|
||||
options.add(Map.of("code", g.getCode(), "name", g.getName()));
|
||||
});
|
||||
return this.bindDataTable(options);
|
||||
return this.bindSelectOptions(list, HotWordGroup::getCode, HotWordGroup::getName);
|
||||
}
|
||||
|
||||
@Priv(type = AdminUserType.TYPE, value = WordPriv.View)
|
||||
@ -99,10 +95,9 @@ public class CMSHotWordGroupController extends BaseRestController {
|
||||
|
||||
@Priv(type = AdminUserType.TYPE, value = WordPriv.View)
|
||||
@PostMapping
|
||||
public R<?> add(@RequestBody @Validated HotWordGroup group) {
|
||||
public R<?> add(@RequestBody @Validated CreateHotWordGroupRequest req) {
|
||||
CmsSite site = siteService.getCurrentSite(ServletUtils.getRequest());
|
||||
group.setOwner(site.getSiteId().toString());
|
||||
group.createBy(StpAdminUtil.getLoginUser().getUsername());
|
||||
return R.ok(this.hotWordGroupService.addHotWordGroup(group));
|
||||
req.setOwner(site.getSiteId().toString());
|
||||
return R.ok(this.hotWordGroupService.addHotWordGroup(req));
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user