From 3e029c380edd7dc97f7231a1ba01c9d246400ace Mon Sep 17 00:00:00 2001 From: liweiyi <190785909@qq.com> Date: Sat, 31 Aug 2024 18:31:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../contentcore/config/CMSPublishConfig.java | 107 ------- .../listener/event/SiteThemeExportEvent.java | 22 -- .../listener/event/SiteThemeImportEvent.java | 25 -- .../publish/CatalogPublishTask.java | 202 -------------- .../publish/CmsStaticizeService.java | 39 --- .../publish/ContentPublishTask.java | 262 ------------------ .../contentcore/publish/IPublishStrategy.java | 48 ---- .../contentcore/publish/IPublishTask.java | 46 --- .../contentcore/publish/IStaticizeType.java | 30 -- .../publish/PublishTaskReceiver.java | 73 ----- .../contentcore/publish/SitePublishTask.java | 129 --------- .../staticize/CatalogStaticizeType.java | 182 ------------ .../staticize/ContentStaticizeType.java | 223 --------------- .../publish/staticize/SiteStaticizeType.java | 110 -------- .../strategies/PublishTaskReceiver.java | 80 ------ .../strategies/RedisSetPublishStrategy.java | 114 -------- .../RedisStreamPublishStrategy.java | 135 --------- .../strategies/ThreadPoolPublishStrategy.java | 90 ------ .../domain/dto/XModelFieldDataDTO.java | 38 --- .../com/chestnut/cms/stat/core/CmsStat.java | 14 - .../stat/core/impl/CmsContentViewStat.java | 25 -- .../async/AsyncTaskExceptionHandler.java | 32 --- .../java/com/chestnut/stat/IStatType.java | 21 -- .../java/com/chestnut/stat/RequestEvent.java | 86 ------ .../main/java/com/chestnut/stat/StatMenu.java | 11 - .../intercepter/DemoModeIntercepter.java | 42 --- .../system/mapper/DataBaseMapper.java | 67 ----- chestnut-ui/src/assets/images/alipay.png | Bin 63358 -> 0 bytes chestnut-ui/src/assets/images/wxpay.png | Bin 55098 -> 0 bytes 29 files changed, 2253 deletions(-) delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/config/CMSPublishConfig.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/event/SiteThemeExportEvent.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/event/SiteThemeImportEvent.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/CatalogPublishTask.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/CmsStaticizeService.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/ContentPublishTask.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IPublishStrategy.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IPublishTask.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IStaticizeType.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/PublishTaskReceiver.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/SitePublishTask.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/CatalogStaticizeType.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/ContentStaticizeType.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/SiteStaticizeType.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/PublishTaskReceiver.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/RedisSetPublishStrategy.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/RedisStreamPublishStrategy.java delete mode 100644 chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/ThreadPoolPublishStrategy.java delete mode 100644 chestnut-cms/chestnut-cms-exmodel/src/main/java/com/chestnut/exmodel/domain/dto/XModelFieldDataDTO.java delete mode 100644 chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/core/CmsStat.java delete mode 100644 chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/core/impl/CmsContentViewStat.java delete mode 100644 chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/async/AsyncTaskExceptionHandler.java delete mode 100644 chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/IStatType.java delete mode 100644 chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/RequestEvent.java delete mode 100644 chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/StatMenu.java delete mode 100644 chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/intercepter/DemoModeIntercepter.java delete mode 100644 chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/mapper/DataBaseMapper.java delete mode 100644 chestnut-ui/src/assets/images/alipay.png delete mode 100644 chestnut-ui/src/assets/images/wxpay.png diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/config/CMSPublishConfig.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/config/CMSPublishConfig.java deleted file mode 100644 index 75dc0f64..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/config/CMSPublishConfig.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.config; - -import com.chestnut.contentcore.config.properties.CMSPublishProperties; -import com.chestnut.contentcore.publish.IPublishTask; -import com.chestnut.contentcore.publish.PublishTaskReceiver; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.connection.stream.Consumer; -import org.springframework.data.redis.connection.stream.MapRecord; -import org.springframework.data.redis.connection.stream.ReadOffset; -import org.springframework.data.redis.connection.stream.StreamOffset; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.data.redis.stream.StreamMessageListenerContainer; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; - -import java.time.Duration; -import java.util.Map; - -/** - * 内容发布配置 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Slf4j -@Configuration -@EnableConfigurationProperties(CMSPublishProperties.class) -@RequiredArgsConstructor -public class CMSPublishConfig { - - private final CMSPublishProperties properties; - - private final StringRedisTemplate redisTemplate; - - private final Map> publishTaskMap; - - public static final String PublishStreamName = "ChestnutCMSPublishStream"; - - public static final String PublishConsumerGroup = "ChestnutCMSPublishConsumerGroup"; - - @Bean - public StreamMessageListenerContainer> streamMessageListenerContainer() { - // 启动清理消息队列数据 - if (properties.isClearOnStart()) { - redisTemplate.delete(PublishStreamName); - } - // 监听容器配置 - StreamMessageListenerContainer.StreamMessageListenerContainerOptions> streamMessageListenerContainerOptions = StreamMessageListenerContainer.StreamMessageListenerContainerOptions - .builder() - .batchSize(10) // 一次拉取消息数量 - .pollTimeout(Duration.ofSeconds(2)) // 拉取消息超时时间 - .executor(cmsPublishThreadPoolTaskExecutor()) - .build(); - // 创建监听容器 - StreamMessageListenerContainer> container = StreamMessageListenerContainer - .create(redisTemplate.getRequiredConnectionFactory(), streamMessageListenerContainerOptions); - //创建消费者组 - try { - redisTemplate.opsForStream().createGroup(PublishStreamName, PublishConsumerGroup); - } catch (Exception e) { - log.info("消费者组:{} 已存在", PublishConsumerGroup); - } - // 添加消费者 - for (int i = 0; i < properties.getConsumerCount(); i++) { - Consumer consumer = Consumer.from(PublishConsumerGroup, "cms-publish-consumer-" + i); - PublishTaskReceiver publishTaskReceiver = new PublishTaskReceiver(publishTaskMap, redisTemplate); - publishTaskReceiver.setConsumer(consumer); - container.receive(consumer, StreamOffset.create(PublishStreamName, ReadOffset.lastConsumed()), publishTaskReceiver); - } - container.start(); - return container; - } - - @Bean - ThreadPoolTaskExecutor cmsPublishThreadPoolTaskExecutor() { - ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - executor.setThreadNamePrefix(properties.getPool().getThreadNamePrefix()); - executor.setCorePoolSize(properties.getPool().getCoreSize()); - executor.setQueueCapacity(properties.getPool().getQueueCapacity()); - executor.setMaxPoolSize(properties.getPool().getMaxSize()); - executor.setKeepAliveSeconds((int) properties.getPool().getKeepAlive().getSeconds()); - executor.setAllowCoreThreadTimeOut(this.properties.getPool().isAllowCoreThreadTimeout()); - executor.setWaitForTasksToCompleteOnShutdown(properties.getShutdown().isAwaitTermination()); - executor.setAwaitTerminationSeconds((int) properties.getShutdown().getAwaitTerminationPeriod().toSeconds()); - log.info("Cms publish task executor initialize: {}", executor.getThreadNamePrefix()); - executor.initialize(); - return executor; - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/event/SiteThemeExportEvent.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/event/SiteThemeExportEvent.java deleted file mode 100644 index 1a194d1b..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/event/SiteThemeExportEvent.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.chestnut.contentcore.listener.event; - -import com.chestnut.contentcore.domain.CmsSite; -import jodd.io.ZipBuilder; -import lombok.Getter; -import org.springframework.context.ApplicationEvent; - -@Getter -public class SiteThemeExportEvent extends ApplicationEvent { - - private static final long serialVersionUID = 1L; - - private CmsSite site; - - private ZipBuilder zipBuilder; - - public SiteThemeExportEvent(Object source, CmsSite site, ZipBuilder zipBuilder) { - super(source); - this.site = site; - this.zipBuilder = zipBuilder; - } -} \ No newline at end of file diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/event/SiteThemeImportEvent.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/event/SiteThemeImportEvent.java deleted file mode 100644 index 8400abc0..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/event/SiteThemeImportEvent.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.chestnut.contentcore.listener.event; - -import com.chestnut.common.security.domain.LoginUser; -import com.chestnut.contentcore.domain.CmsSite; -import lombok.Getter; -import org.springframework.context.ApplicationEvent; - -@Getter -public class SiteThemeImportEvent extends ApplicationEvent { - - private static final long serialVersionUID = 1L; - - private CmsSite site; - - private String destDir; - - private LoginUser operator; - - public SiteThemeImportEvent(Object source, CmsSite site, String destDir, LoginUser operator) { - super(source); - this.site = site; - this.destDir = destDir; - this.operator = operator; - } -} \ No newline at end of file diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/CatalogPublishTask.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/CatalogPublishTask.java deleted file mode 100644 index 32a371b7..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/CatalogPublishTask.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.publish; - -import com.chestnut.common.async.AsyncTaskManager; -import com.chestnut.common.staticize.StaticizeService; -import com.chestnut.common.staticize.core.TemplateContext; -import com.chestnut.common.utils.IdUtils; -import com.chestnut.common.utils.StringUtils; -import com.chestnut.common.utils.file.FileExUtils; -import com.chestnut.contentcore.config.CMSPublishConfig; -import com.chestnut.contentcore.core.impl.CatalogType_Link; -import com.chestnut.contentcore.core.impl.PublishPipeProp_DefaultListTemplate; -import com.chestnut.contentcore.core.impl.PublishPipeProp_IndexTemplate; -import com.chestnut.contentcore.core.impl.PublishPipeProp_ListTemplate; -import com.chestnut.contentcore.domain.CmsCatalog; -import com.chestnut.contentcore.domain.CmsPublishPipe; -import com.chestnut.contentcore.domain.CmsSite; -import com.chestnut.contentcore.properties.MaxPageOnContentPublishProperty; -import com.chestnut.contentcore.service.ICatalogService; -import com.chestnut.contentcore.service.IPublishPipeService; -import com.chestnut.contentcore.service.ISiteService; -import com.chestnut.contentcore.service.ITemplateService; -import com.chestnut.contentcore.template.ITemplateType; -import com.chestnut.contentcore.template.impl.CatalogTemplateType; -import com.chestnut.contentcore.util.SiteUtils; -import com.chestnut.contentcore.util.TemplateUtils; -import freemarker.template.TemplateException; -import lombok.RequiredArgsConstructor; -import org.apache.commons.collections4.MapUtils; -import org.springframework.data.redis.connection.stream.MapRecord; -import org.springframework.data.redis.connection.stream.RecordId; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.stereotype.Component; - -import java.io.File; -import java.io.IOException; -import java.time.Instant; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -/** - * 栏目发布任务 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@RequiredArgsConstructor -@Component(IPublishTask.BeanPrefix + CatalogPublishTask.Type) -public class CatalogPublishTask implements IPublishTask { - - public final static String Type = "catalog"; - - private final ISiteService siteService; - - private final ICatalogService catalogService; - - private final IPublishPipeService publishPipeService; - - private final ITemplateService templateService; - - private final StaticizeService staticizeService; - - private final StringRedisTemplate redisTemplate; - - @Override - public String getType() { - return Type; - } - - @Override - public void publish(CmsCatalog catalog) { - if (!catalog.isStaticize() || !catalog.isVisible() || CatalogType_Link.ID.equals(catalog.getCatalogType())) { - return; - } - String dataId = catalog.getCatalogId().toString(); - MapRecord record = MapRecord.create(CMSPublishConfig.PublishStreamName, Map.of( - "type", Type, - "id", dataId - )); - redisTemplate.opsForStream().add(record); - } - - @Override - public void staticize(Map dataMap) { - Long catalogId = MapUtils.getLong(dataMap, "id"); - if (IdUtils.validate(catalogId)) { - CmsCatalog catalog = this.catalogService.getCatalog(catalogId); - if (Objects.nonNull(catalog)) { - this.catalogStaticize(catalog); - } - } - } - public void catalogStaticize(CmsCatalog catalog) { - CmsSite site = this.siteService.getSite(catalog.getSiteId()); - int maxPage = MaxPageOnContentPublishProperty.getValue(site.getConfigProps()); - this.catalogStaticize(catalog, maxPage); - } - - public void catalogStaticize(CmsCatalog catalog, int pageMax) { - if (!catalog.isStaticize() || !catalog.isVisible() || CatalogType_Link.ID.equals(catalog.getCatalogType())) { - return; - } - List publishPipes = this.publishPipeService.getPublishPipes(catalog.getSiteId()); - for (CmsPublishPipe pp : publishPipes) { - this.doCatalogStaticize(catalog, pp.getCode(), pageMax); - } - } - - private void doCatalogStaticize(CmsCatalog catalog, String publishPipeCode, int pageMax) { - CmsSite site = this.siteService.getSite(catalog.getSiteId()); - if (!catalog.isStaticize()) { - logger.warn("【{}】未启用静态化的栏目跳过静态化:{}", publishPipeCode, catalog.getName()); - return; - } - if (!catalog.isVisible()) { - logger.warn("【{}】不可见状态的栏目跳过静态化:{}", publishPipeCode, catalog.getName()); - return; - } - if (CatalogType_Link.ID.equals(catalog.getCatalogType())) { - logger.warn("【{}】链接类型栏目跳过静态化:{}", publishPipeCode, catalog.getName()); - return; - } - String indexTemplate = PublishPipeProp_IndexTemplate.getValue(publishPipeCode, catalog.getPublishPipeProps()); - String listTemplate = PublishPipeProp_ListTemplate.getValue(publishPipeCode, catalog.getPublishPipeProps()); - if (StringUtils.isEmpty(listTemplate)) { - listTemplate = PublishPipeProp_DefaultListTemplate.getValue(publishPipeCode, site.getPublishPipeProps()); // 取站点默认模板 - } - File indexTemplateFile = this.templateService.findTemplateFile(site, indexTemplate, publishPipeCode); - File listTemplateFile = this.templateService.findTemplateFile(site, listTemplate, publishPipeCode); - if (indexTemplateFile == null && listTemplateFile == null) { - logger.warn(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]栏目首页模板和列表页模板未配置或不存在:{1}", - publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName()))); - return; - } - String siteRoot = SiteUtils.getSiteRoot(site, publishPipeCode); - String dirPath = siteRoot + catalog.getPath(); - FileExUtils.mkdirs(dirPath); - String staticSuffix = site.getStaticSuffix(publishPipeCode); // 静态化文件类型 - - // 发布栏目首页 - long s = System.currentTimeMillis(); - if (Objects.nonNull(indexTemplateFile)) { - try { - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, indexTemplate); - TemplateContext templateContext = new TemplateContext(templateKey, false, publishPipeCode); - templateContext.setDirectory(dirPath); - templateContext.setFirstFileName("index" + StringUtils.DOT + staticSuffix); - // init template variables - TemplateUtils.initGlobalVariables(site, templateContext); - // init templateType variables - ITemplateType templateType = templateService.getTemplateType(CatalogTemplateType.TypeId); - templateType.initTemplateData(catalog.getCatalogId(), templateContext); - // staticize - this.staticizeService.process(templateContext); - logger.debug("[{}]栏目首页模板解析:{},耗时:{}ms", publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName(), (System.currentTimeMillis() - s)); - } catch (IOException | TemplateException e) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]栏目首页解析失败:{1}", - publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName())), e); - } - } - // 发布栏目列表页 - if (Objects.nonNull(listTemplateFile)) { - s = System.currentTimeMillis(); - try { - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, listTemplate); - TemplateContext templateContext = new TemplateContext(templateKey, false, publishPipeCode); - templateContext.setMaxPageNo(pageMax); - templateContext.setDirectory(dirPath); - String name = Objects.nonNull(indexTemplateFile) ? "list" : "index"; - templateContext.setFirstFileName(name + StringUtils.DOT + staticSuffix); - templateContext.setOtherFileName( - name + "_" + TemplateContext.PlaceHolder_PageNo + StringUtils.DOT + staticSuffix); - // init template variables - TemplateUtils.initGlobalVariables(site, templateContext); - // init templateType variables - ITemplateType templateType = templateService.getTemplateType(CatalogTemplateType.TypeId); - templateType.initTemplateData(catalog.getCatalogId(), templateContext); - // staticize - this.staticizeService.process(templateContext); - logger.debug("[{}]栏目列表模板解析:{},耗时:{}ms", publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName(), (System.currentTimeMillis() - s)); - } catch (Exception e1) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]栏目列表页解析失败:{1}", - publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName())), e1); - } - } - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/CmsStaticizeService.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/CmsStaticizeService.java deleted file mode 100644 index ca1512ce..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/CmsStaticizeService.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.publish; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -import java.util.Map; - -/** - * CmsStaticizeService - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Service -@RequiredArgsConstructor -public class CmsStaticizeService { - - private final Map staticizeTypeMap; - - public IStaticizeType getStaticizeType(String type) { - return staticizeTypeMap.get(IStaticizeType.BEAN_PREFIX + type); - } -} - diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/ContentPublishTask.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/ContentPublishTask.java deleted file mode 100644 index 747f333e..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/ContentPublishTask.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.publish; - -import com.chestnut.common.async.AsyncTaskManager; -import com.chestnut.common.staticize.StaticizeService; -import com.chestnut.common.staticize.core.TemplateContext; -import com.chestnut.common.utils.IdUtils; -import com.chestnut.common.utils.StringUtils; -import com.chestnut.contentcore.config.CMSPublishConfig; -import com.chestnut.contentcore.core.IPublishPipeProp; -import com.chestnut.contentcore.core.impl.PublishPipeProp_ContentTemplate; -import com.chestnut.contentcore.domain.CmsCatalog; -import com.chestnut.contentcore.domain.CmsContent; -import com.chestnut.contentcore.domain.CmsPublishPipe; -import com.chestnut.contentcore.domain.CmsSite; -import com.chestnut.contentcore.service.*; -import com.chestnut.contentcore.template.ITemplateType; -import com.chestnut.contentcore.template.impl.ContentTemplateType; -import com.chestnut.contentcore.util.ContentUtils; -import com.chestnut.contentcore.util.SiteUtils; -import com.chestnut.contentcore.util.TemplateUtils; -import freemarker.template.TemplateException; -import lombok.RequiredArgsConstructor; -import org.apache.commons.collections4.MapUtils; -import org.springframework.data.redis.connection.stream.MapRecord; -import org.springframework.data.redis.connection.stream.RecordId; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.stereotype.Component; - -import java.io.File; -import java.io.IOException; -import java.time.Instant; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -/** - * 内容发布任务 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@RequiredArgsConstructor -@Component(IPublishTask.BeanPrefix + ContentPublishTask.Type) -public class ContentPublishTask implements IPublishTask { - - public final static String Type = "content"; - - private final ISiteService siteService; - - private final ICatalogService catalogService; - - private final IContentService contentService; - - private final IPublishPipeService publishPipeService; - - private final ITemplateService templateService; - - private final StaticizeService staticizeService; - - private final StringRedisTemplate redisTemplate; - - @Override - public String getType() { - return Type; - } - - - @Override - public void publish(CmsContent content) { - CmsCatalog catalog = catalogService.getCatalog(content.getCatalogId()); - if (!catalog.isStaticize() || content.isLinkContent()) { - return; // 不静态化直接跳过,标题内容不需要静态化 - } - CmsSite site = siteService.getSite(content.getSiteId()); - List publishPipes = publishPipeService.getPublishPipes(content.getSiteId()); - // 判断内容是否有设置模板 - boolean hasTemplate = false; - for (CmsPublishPipe pp : publishPipes) { - final String detailTemplate = getDetailTemplate(site, catalog, content, pp.getCode()); - File templateFile = this.templateService.findTemplateFile(site, detailTemplate, pp.getCode()); - if (Objects.nonNull(templateFile)) { - hasTemplate = true; - break; - } - } - if (!hasTemplate) { - return; // 没有可用模板不需要静态化 - } - // 加入消息队列 - String dataId = content.getContentId().toString(); - MapRecord record = MapRecord.create(CMSPublishConfig.PublishStreamName, Map.of( - "type", Type, - "id", dataId - )); - redisTemplate.opsForStream().add(record); - } - - @Override - public void staticize(Map dataMap) { - Long contentId = MapUtils.getLong(dataMap, "id"); - if (IdUtils.validate(contentId)) { - CmsContent content = this.contentService.getById(contentId); - if (Objects.nonNull(content)) { - this.contentStaticize(content); - } - } - } - - public void contentStaticize(CmsContent cmsContent) { - List publishPipes = publishPipeService.getPublishPipes(cmsContent.getSiteId()); - // 发布内容 - for (CmsPublishPipe pp : publishPipes) { - doContentStaticize(cmsContent, pp.getCode()); - // 内容扩展模板静态化 - doContentExStaticize(cmsContent, pp.getCode()); - } - } - - private void doContentStaticize(CmsContent content, String publishPipeCode) { - CmsSite site = this.siteService.getSite(content.getSiteId()); - CmsCatalog catalog = this.catalogService.getCatalog(content.getCatalogId()); - if (!catalog.isStaticize()) { - logger.warn("[ {} ]栏目设置不静态化[ {}#{} ]:{}", publishPipeCode, site.getName(), - catalog.getName(), content.getTitle()); - return; // 不静态化直接跳过 - } - if (content.isLinkContent()) { - logger.warn("[ {} ]标题内容不需要静态化[ {}#{} ]:{}", publishPipeCode, site.getName(), - catalog.getName(), content.getTitle()); - return; // 标题内容不需要静态化 - } - final String detailTemplate = getDetailTemplate(site, catalog, content, publishPipeCode); - File templateFile = this.templateService.findTemplateFile(site, detailTemplate, publishPipeCode); - if (templateFile == null) { - logger.warn(AsyncTaskManager.addErrMessage( - StringUtils.messageFormat("[ {0} ]内容模板未设置或文件不存在[ {1}#{2} ]:{3}", - publishPipeCode, site.getName(), catalog.getName(), content.getTitle()))); - return; - } - try { - long s = System.currentTimeMillis(); - // 自定义模板上下文 - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, detailTemplate); - TemplateContext templateContext = new TemplateContext(templateKey, false, publishPipeCode); - // init template datamode - TemplateUtils.initGlobalVariables(site, templateContext); - // init templateType data to datamode - ITemplateType templateType = this.templateService.getTemplateType(ContentTemplateType.TypeId); - templateType.initTemplateData(content.getContentId(), templateContext); - // 静态化文件地址 - this.setContentStaticPath(site, catalog, content, templateContext); - // 静态化 - this.staticizeService.process(templateContext); - logger.debug("[ {} ]内容详情页模板解析[ {}#{} ]:{},耗时:{}ms", publishPipeCode, site.getName(), - catalog.getName(), content.getTitle(), (System.currentTimeMillis() - s)); - } catch (TemplateException | IOException e) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]内容详情页解析失败:[{1}]{2}", - publishPipeCode, catalog.getName(), content.getTitle())), e); - } - } - - private void setContentStaticPath(CmsSite site, CmsCatalog catalog, CmsContent content, TemplateContext context) { - String siteRoot = SiteUtils.getSiteRoot(site, context.getPublishPipeCode()); - if (StringUtils.isNotBlank(content.getStaticPath())) { - String dir = ""; - String filename = content.getStaticPath(); - if (filename.indexOf("/") > 0) { - dir = filename.substring(0, filename.lastIndexOf("/") + 1); - filename = filename.substring(filename.lastIndexOf("/") + 1); - } - context.setDirectory(siteRoot + dir); - context.setFirstFileName(filename); - String name = filename.substring(0, filename.lastIndexOf(".")); - String suffix = filename.substring(filename.lastIndexOf(".")); - context.setOtherFileName(name + "_" + TemplateContext.PlaceHolder_PageNo + suffix); - } else { - context.setDirectory(siteRoot + catalog.getPath()); - String suffix = site.getStaticSuffix(context.getPublishPipeCode()); - context.setFirstFileName(content.getContentId() + StringUtils.DOT + suffix); - context.setOtherFileName( - content.getContentId() + "_" + TemplateContext.PlaceHolder_PageNo + StringUtils.DOT + suffix); - } - } - - private void doContentExStaticize(CmsContent content, String publishPipeCode) { - CmsSite site = this.siteService.getSite(content.getSiteId()); - CmsCatalog catalog = this.catalogService.getCatalog(content.getCatalogId()); - if (!catalog.isStaticize()) { - logger.warn("[{}]栏目设置不静态化[{}#{}]:{}", publishPipeCode, site.getName(), catalog.getName(), content.getTitle()); - return; // 不静态化直接跳过 - } - if (content.isLinkContent()) { - logger.warn("[{}]标题内容不需要静态化[ {}#{} ]:{}", publishPipeCode, site.getName(), catalog.getName(), content.getTitle()); - return; // 标题内容不需要静态化 - } - String exTemplate = ContentUtils.getContentExTemplate(content, catalog, publishPipeCode); - if (StringUtils.isEmpty(exTemplate)) { - return; // 未设置扩展模板直接跳过 - } - File templateFile = this.templateService.findTemplateFile(site, exTemplate, publishPipeCode); - if (templateFile == null) { - logger.warn("[{}]内容扩展模板未设置或文件不存在[ {}#{} ]:{}", publishPipeCode, site.getName(), catalog.getName(), content.getTitle()); - return; - } - try { - long s = System.currentTimeMillis(); - // 自定义模板上下文 - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, exTemplate); - TemplateContext templateContext = new TemplateContext(templateKey, false, publishPipeCode); - // 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 siteRoot = SiteUtils.getSiteRoot(site, publishPipeCode); - templateContext.setDirectory(siteRoot + catalog.getPath()); - String fileName = ContentUtils.getContextExFileName(content.getContentId(), site.getStaticSuffix(publishPipeCode)); - templateContext.setFirstFileName(fileName); - // 静态化 - this.staticizeService.process(templateContext); - logger.debug("[{}]内容扩展模板解析[ {}#{} ]:{},耗时:{}ms", publishPipeCode, site.getName(), - catalog.getName(), content.getTitle(), (System.currentTimeMillis() - s)); - } catch (TemplateException | IOException e) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}] 内容扩展模板解析失败 [{1}#{2}]:{3}", - publishPipeCode, site.getName(), catalog.getName(), content.getTitle())), e); - } - } - - private String getDetailTemplate(CmsSite site, CmsCatalog catalog, CmsContent content, String publishPipeCode) { - String detailTemplate = PublishPipeProp_ContentTemplate.getValue(publishPipeCode, - content.getPublishPipeProps()); - if (StringUtils.isEmpty(detailTemplate)) { - // 无内容独立模板取栏目配置 - detailTemplate = this.publishPipeService.getPublishPipePropValue( - IPublishPipeProp.DetailTemplatePropPrefix + content.getContentType(), publishPipeCode, - catalog.getPublishPipeProps()); - if (StringUtils.isEmpty(detailTemplate)) { - // 无栏目配置去站点默认模板配置 - detailTemplate = this.publishPipeService.getPublishPipePropValue( - IPublishPipeProp.DefaultDetailTemplatePropPrefix + content.getContentType(), publishPipeCode, - site.getPublishPipeProps()); - } - } - return detailTemplate; - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IPublishStrategy.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IPublishStrategy.java deleted file mode 100644 index ea889969..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IPublishStrategy.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.publish; - -/** - * IPublishStrategy - * - * @author 兮玥 - * @email 190785909@qq.com - */ -public interface IPublishStrategy { - - /** - * 发布策略ID - */ - String getId(); - - /** - * 创建发布任务 - * - * @param dataType 数据类型 - * @param dataId 数据ID - */ - void publish(String dataType, String dataId); - - /** - * 获取待处理发布任务数量 - */ - long getTaskCount(); - - /** - * 清空所有待处理发布任务 - */ - void cleanTasks(); -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IPublishTask.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IPublishTask.java deleted file mode 100644 index c780f49b..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IPublishTask.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.publish; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; - -/** - * - * - * @author 兮玥 - * @email 190785909@qq.com - */ -public interface IPublishTask { - - Logger logger = LoggerFactory.getLogger("publish"); - - String BeanPrefix = "PublishTask_"; - - String getType(); - - /** - * 创建发布任务 - */ - void publish(T data); - - /** - * 静态化 - */ - void staticize(Map dataMap); -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IStaticizeType.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IStaticizeType.java deleted file mode 100644 index 5397f6c5..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IStaticizeType.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.publish; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public interface IStaticizeType { - - Logger logger = LoggerFactory.getLogger("publish"); - - String BEAN_PREFIX = "CmsStaticizeType"; - - String getType(); - - void staticize(String dataId); -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/PublishTaskReceiver.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/PublishTaskReceiver.java deleted file mode 100644 index 3e3e689a..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/PublishTaskReceiver.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.publish; - -import com.chestnut.contentcore.config.CMSPublishConfig; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.MapUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.redis.connection.stream.Consumer; -import org.springframework.data.redis.connection.stream.MapRecord; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.data.redis.stream.StreamListener; - -import java.util.Map; -import java.util.Objects; - -/** - * 发布任务消费监听 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Slf4j -@RequiredArgsConstructor -public class PublishTaskReceiver implements StreamListener> { - - private final static Logger logger = LoggerFactory.getLogger("publish"); - - private final Map> publishTaskMap; - - private final StringRedisTemplate redisTemplate; - - @Setter - @Getter - private Consumer consumer; - - @Override - public void onMessage(MapRecord message) { - String stream = message.getStream(); - if (Objects.nonNull(stream)) { - try { - Map map = message.getValue(); - String type = MapUtils.getString(map, "type"); - IPublishTask publishTask = publishTaskMap.get(IPublishTask.BeanPrefix + type); - if (Objects.nonNull(publishTask)) { - publishTask.staticize(map); - } - } catch(Exception e) { - logger.error("Publish err.", e); - } finally { - redisTemplate.opsForStream().acknowledge(stream, CMSPublishConfig.PublishConsumerGroup, message.getId().getValue()); - redisTemplate.opsForStream().delete(stream, message.getId().getValue()); - } - } - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/SitePublishTask.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/SitePublishTask.java deleted file mode 100644 index 46465f7c..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/SitePublishTask.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.publish; - -import com.chestnut.common.async.AsyncTaskManager; -import com.chestnut.common.staticize.StaticizeService; -import com.chestnut.common.staticize.core.TemplateContext; -import com.chestnut.common.utils.IdUtils; -import com.chestnut.common.utils.JacksonUtils; -import com.chestnut.common.utils.StringUtils; -import com.chestnut.contentcore.config.CMSPublishConfig; -import com.chestnut.contentcore.domain.CmsSite; -import com.chestnut.contentcore.service.IPublishPipeService; -import com.chestnut.contentcore.service.ISiteService; -import com.chestnut.contentcore.service.ITemplateService; -import com.chestnut.contentcore.template.ITemplateType; -import com.chestnut.contentcore.template.impl.SiteTemplateType; -import com.chestnut.contentcore.util.SiteUtils; -import com.chestnut.contentcore.util.TemplateUtils; -import lombok.RequiredArgsConstructor; -import org.apache.commons.collections4.MapUtils; -import org.springframework.data.redis.connection.stream.MapRecord; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.stereotype.Component; - -import java.io.File; -import java.util.Map; -import java.util.Objects; - -/** - * 站点发布任务 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@RequiredArgsConstructor -@Component(IPublishTask.BeanPrefix + SitePublishTask.Type) -public class SitePublishTask implements IPublishTask { - - public final static String Type = "site"; - - private final ISiteService siteService; - - private final IPublishPipeService publishPipeService; - - private final ITemplateService templateService; - - private final StaticizeService staticizeService; - - private final StringRedisTemplate redisTemplate; - - @Override - public String getType() { - return Type; - } - - @Override - public void publish(CmsSite site) { - String dataId = site.getSiteId().toString(); - MapRecord record = MapRecord.create(CMSPublishConfig.PublishStreamName, Map.of( - "type", Type, - "id", dataId - )); - redisTemplate.opsForStream().add(record); - } - - @Override - public void staticize(Map dataMap) { - logger.info("开始发布:" + JacksonUtils.to(dataMap)); - Long siteId = MapUtils.getLong(dataMap, "id"); - if (IdUtils.validate(siteId)) { - CmsSite site = this.siteService.getSite(siteId); - if (Objects.nonNull(site)) { - this.siteStaticize(site); - } - } - logger.info("结束发布:" + JacksonUtils.to(dataMap)); - } - - public void siteStaticize(CmsSite site) { - this.publishPipeService.getPublishPipes(site.getSiteId()) - .forEach(pp -> doSiteStaticize(site, pp.getCode())); - } - - private void doSiteStaticize(CmsSite site, String publishPipeCode) { - try { - AsyncTaskManager - .setTaskMessage(StringUtils.messageFormat("[{0}]正在发布站点首页:{1}", publishPipeCode, site.getName())); - - String indexTemplate = site.getIndexTemplate(publishPipeCode); - File templateFile = this.templateService.findTemplateFile(site, indexTemplate, publishPipeCode); - if (Objects.isNull(templateFile)) { - logger.warn(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]站点首页模板未配置或不存在:{1}", - publishPipeCode, site.getSiteId() + "#" + site.getName()))); - return; - } - // 模板ID = 通道:站点目录:模板文件名 - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, indexTemplate); - TemplateContext context = new TemplateContext(templateKey, false, publishPipeCode); - // init template datamode - TemplateUtils.initGlobalVariables(site, context); - // init templateType data to datamode - ITemplateType templateType = templateService.getTemplateType(SiteTemplateType.TypeId); - templateType.initTemplateData(site.getSiteId(), context); - - long s = System.currentTimeMillis(); - context.setDirectory(SiteUtils.getSiteRoot(site, publishPipeCode)); - context.setFirstFileName("index" + StringUtils.DOT + site.getStaticSuffix(publishPipeCode)); - this.staticizeService.process(context); - logger.debug("[{}]首页模板解析:{},耗时:{}ms", publishPipeCode, site.getName(), (System.currentTimeMillis() - s)); - } catch (Exception e) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}][{1}]站点首页解析失败:{2}", - publishPipeCode, site.getName(), e.getMessage())), e); - } - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/CatalogStaticizeType.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/CatalogStaticizeType.java deleted file mode 100644 index c29d5cba..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/CatalogStaticizeType.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.publish.staticize; - -import com.chestnut.common.async.AsyncTaskManager; -import com.chestnut.common.staticize.StaticizeService; -import com.chestnut.common.staticize.core.TemplateContext; -import com.chestnut.common.utils.IdUtils; -import com.chestnut.common.utils.StringUtils; -import com.chestnut.common.utils.file.FileExUtils; -import com.chestnut.contentcore.core.impl.CatalogType_Link; -import com.chestnut.contentcore.core.impl.PublishPipeProp_DefaultListTemplate; -import com.chestnut.contentcore.core.impl.PublishPipeProp_IndexTemplate; -import com.chestnut.contentcore.core.impl.PublishPipeProp_ListTemplate; -import com.chestnut.contentcore.domain.CmsCatalog; -import com.chestnut.contentcore.domain.CmsPublishPipe; -import com.chestnut.contentcore.domain.CmsSite; -import com.chestnut.contentcore.properties.MaxPageOnContentPublishProperty; -import com.chestnut.contentcore.publish.IStaticizeType; -import com.chestnut.contentcore.service.ICatalogService; -import com.chestnut.contentcore.service.IPublishPipeService; -import com.chestnut.contentcore.service.ISiteService; -import com.chestnut.contentcore.service.ITemplateService; -import com.chestnut.contentcore.template.ITemplateType; -import com.chestnut.contentcore.template.impl.CatalogTemplateType; -import com.chestnut.contentcore.util.SiteUtils; -import com.chestnut.contentcore.util.TemplateUtils; -import freemarker.template.TemplateException; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Objects; - -/** - * CatalogStaticizeType - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@RequiredArgsConstructor -@Component(IStaticizeType.BEAN_PREFIX + CatalogStaticizeType.TYPE) -public class CatalogStaticizeType implements IStaticizeType { - - public static final String TYPE = "catalog"; - - private final ISiteService siteService; - - private final ICatalogService catalogService; - - private final IPublishPipeService publishPipeService; - - private final ITemplateService templateService; - - private final StaticizeService staticizeService; - - @Override - public String getType() { - return TYPE; - } - - @Override - public void staticize(String dataId) { - Long catalogId = Long.valueOf(dataId); - if (IdUtils.validate(catalogId)) { - CmsCatalog catalog = this.catalogService.getCatalog(catalogId); - if (Objects.nonNull(catalog)) { - this.catalogStaticize(catalog); - } - } - } - - public void catalogStaticize(CmsCatalog catalog) { - CmsSite site = this.siteService.getSite(catalog.getSiteId()); - int maxPage = MaxPageOnContentPublishProperty.getValue(site.getConfigProps()); - this.catalogStaticize(catalog, maxPage); - } - - public void catalogStaticize(CmsCatalog catalog, int pageMax) { - if (!catalog.isStaticize() || !catalog.isVisible() || CatalogType_Link.ID.equals(catalog.getCatalogType())) { - return; - } - List publishPipes = this.publishPipeService.getPublishPipes(catalog.getSiteId()); - for (CmsPublishPipe pp : publishPipes) { - this.doCatalogStaticize(catalog, pp.getCode(), pageMax); - } - } - - private void doCatalogStaticize(CmsCatalog catalog, String publishPipeCode, int pageMax) { - CmsSite site = this.siteService.getSite(catalog.getSiteId()); - if (!catalog.isStaticize()) { - logger.warn("【{}】未启用静态化的栏目跳过静态化:{}", publishPipeCode, catalog.getName()); - return; - } - if (!catalog.isVisible()) { - logger.warn("【{}】不可见状态的栏目跳过静态化:{}", publishPipeCode, catalog.getName()); - return; - } - if (CatalogType_Link.ID.equals(catalog.getCatalogType())) { - logger.warn("【{}】链接类型栏目跳过静态化:{}", publishPipeCode, catalog.getName()); - return; - } - String indexTemplate = PublishPipeProp_IndexTemplate.getValue(publishPipeCode, catalog.getPublishPipeProps()); - String listTemplate = PublishPipeProp_ListTemplate.getValue(publishPipeCode, catalog.getPublishPipeProps()); - if (StringUtils.isEmpty(listTemplate)) { - listTemplate = PublishPipeProp_DefaultListTemplate.getValue(publishPipeCode, site.getPublishPipeProps()); // 取站点默认模板 - } - File indexTemplateFile = this.templateService.findTemplateFile(site, indexTemplate, publishPipeCode); - File listTemplateFile = this.templateService.findTemplateFile(site, listTemplate, publishPipeCode); - if (indexTemplateFile == null && listTemplateFile == null) { - logger.warn(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]栏目首页模板和列表页模板未配置或不存在:{1}", - publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName()))); - return; - } - String siteRoot = SiteUtils.getSiteRoot(site, publishPipeCode); - String dirPath = siteRoot + catalog.getPath(); - FileExUtils.mkdirs(dirPath); - String staticSuffix = site.getStaticSuffix(publishPipeCode); // 静态化文件类型 - - // 发布栏目首页 - long s = System.currentTimeMillis(); - if (Objects.nonNull(indexTemplateFile)) { - try { - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, indexTemplate); - TemplateContext templateContext = new TemplateContext(templateKey, false, publishPipeCode); - templateContext.setDirectory(dirPath); - templateContext.setFirstFileName("index" + StringUtils.DOT + staticSuffix); - // init template variables - TemplateUtils.initGlobalVariables(site, templateContext); - // init templateType variables - ITemplateType templateType = templateService.getTemplateType(CatalogTemplateType.TypeId); - templateType.initTemplateData(catalog.getCatalogId(), templateContext); - // staticize - this.staticizeService.process(templateContext); - logger.debug("[{}]栏目首页模板解析:{},耗时:{}ms", publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName(), (System.currentTimeMillis() - s)); - } catch (IOException | TemplateException e) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]栏目首页解析失败:{1}", - publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName())), e); - } - } - // 发布栏目列表页 - if (Objects.nonNull(listTemplateFile)) { - s = System.currentTimeMillis(); - try { - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, listTemplate); - TemplateContext templateContext = new TemplateContext(templateKey, false, publishPipeCode); - templateContext.setMaxPageNo(pageMax); - templateContext.setDirectory(dirPath); - String name = Objects.nonNull(indexTemplateFile) ? "list" : "index"; - templateContext.setFirstFileName(name + StringUtils.DOT + staticSuffix); - templateContext.setOtherFileName( - name + "_" + TemplateContext.PlaceHolder_PageNo + StringUtils.DOT + staticSuffix); - // init template variables - TemplateUtils.initGlobalVariables(site, templateContext); - // init templateType variables - ITemplateType templateType = templateService.getTemplateType(CatalogTemplateType.TypeId); - templateType.initTemplateData(catalog.getCatalogId(), templateContext); - // staticize - this.staticizeService.process(templateContext); - logger.debug("[{}]栏目列表模板解析:{},耗时:{}ms", publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName(), (System.currentTimeMillis() - s)); - } catch (Exception e1) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]栏目列表页解析失败:{1}", - publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName())), e1); - } - } - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/ContentStaticizeType.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/ContentStaticizeType.java deleted file mode 100644 index 0df893ee..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/ContentStaticizeType.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.publish.staticize; - -import com.chestnut.common.async.AsyncTaskManager; -import com.chestnut.common.staticize.StaticizeService; -import com.chestnut.common.staticize.core.TemplateContext; -import com.chestnut.common.utils.IdUtils; -import com.chestnut.common.utils.StringUtils; -import com.chestnut.contentcore.core.IPublishPipeProp; -import com.chestnut.contentcore.core.impl.PublishPipeProp_ContentTemplate; -import com.chestnut.contentcore.domain.CmsCatalog; -import com.chestnut.contentcore.domain.CmsContent; -import com.chestnut.contentcore.domain.CmsPublishPipe; -import com.chestnut.contentcore.domain.CmsSite; -import com.chestnut.contentcore.publish.IStaticizeType; -import com.chestnut.contentcore.service.*; -import com.chestnut.contentcore.template.ITemplateType; -import com.chestnut.contentcore.template.impl.ContentTemplateType; -import com.chestnut.contentcore.util.ContentUtils; -import com.chestnut.contentcore.util.SiteUtils; -import com.chestnut.contentcore.util.TemplateUtils; -import freemarker.template.TemplateException; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Objects; - -/** - * ContentStaticizeType - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@RequiredArgsConstructor -@Component(IStaticizeType.BEAN_PREFIX + ContentStaticizeType.TYPE) -public class ContentStaticizeType implements IStaticizeType { - - public static final String TYPE = "content"; - - private final ISiteService siteService; - - private final ICatalogService catalogService; - - private final IContentService contentService; - - private final IPublishPipeService publishPipeService; - - private final ITemplateService templateService; - - private final StaticizeService staticizeService; - - @Override - public String getType() { - return TYPE; - } - - @Override - public void staticize(String dataId) { - Long contentId = Long.valueOf(dataId); - if (IdUtils.validate(contentId)) { - CmsContent content = this.contentService.dao().getById(contentId); - if (Objects.nonNull(content)) { - this.contentStaticize(content); - } - } - } - - public void contentStaticize(CmsContent cmsContent) { - List publishPipes = publishPipeService.getPublishPipes(cmsContent.getSiteId()); - // 发布内容 - for (CmsPublishPipe pp : publishPipes) { - doContentStaticize(cmsContent, pp.getCode()); - // 内容扩展模板静态化 - doContentExStaticize(cmsContent, pp.getCode()); - } - } - - private void doContentStaticize(CmsContent content, String publishPipeCode) { - CmsSite site = this.siteService.getSite(content.getSiteId()); - CmsCatalog catalog = this.catalogService.getCatalog(content.getCatalogId()); - if (!catalog.isStaticize()) { - logger.warn("[ {} ]栏目设置不静态化[ {}#{} ]:{}", publishPipeCode, site.getName(), - catalog.getName(), content.getTitle()); - return; // 不静态化直接跳过 - } - if (content.isLinkContent()) { - logger.warn("[ {} ]标题内容不需要静态化[ {}#{} ]:{}", publishPipeCode, site.getName(), - catalog.getName(), content.getTitle()); - return; // 标题内容不需要静态化 - } - final String detailTemplate = getDetailTemplate(site, catalog, content, publishPipeCode); - File templateFile = this.templateService.findTemplateFile(site, detailTemplate, publishPipeCode); - if (templateFile == null) { - logger.warn(AsyncTaskManager.addErrMessage( - StringUtils.messageFormat("[ {0} ]内容模板未设置或文件不存在[ {1}#{2} ]:{3}", - publishPipeCode, site.getName(), catalog.getName(), content.getTitle()))); - return; - } - try { - long s = System.currentTimeMillis(); - // 自定义模板上下文 - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, detailTemplate); - TemplateContext templateContext = new TemplateContext(templateKey, false, publishPipeCode); - // init template datamode - TemplateUtils.initGlobalVariables(site, templateContext); - // init templateType data to datamode - ITemplateType templateType = this.templateService.getTemplateType(ContentTemplateType.TypeId); - templateType.initTemplateData(content.getContentId(), templateContext); - // 静态化文件地址 - this.setContentStaticPath(site, catalog, content, templateContext); - // 静态化 - this.staticizeService.process(templateContext); - logger.debug("[ {} ]内容详情页模板解析[ {}#{} ]:{},耗时:{}ms", publishPipeCode, site.getName(), - catalog.getName(), content.getTitle(), (System.currentTimeMillis() - s)); - } catch (TemplateException | IOException e) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]内容详情页解析失败:[{1}]{2}", - publishPipeCode, catalog.getName(), content.getTitle())), e); - } - } - - private void setContentStaticPath(CmsSite site, CmsCatalog catalog, CmsContent content, TemplateContext context) { - String siteRoot = SiteUtils.getSiteRoot(site, context.getPublishPipeCode()); - if (StringUtils.isNotBlank(content.getStaticPath())) { - String dir = ""; - String filename = content.getStaticPath(); - if (filename.indexOf("/") > 0) { - dir = filename.substring(0, filename.lastIndexOf("/") + 1); - filename = filename.substring(filename.lastIndexOf("/") + 1); - } - context.setDirectory(siteRoot + dir); - context.setFirstFileName(filename); - String name = filename.substring(0, filename.lastIndexOf(".")); - String suffix = filename.substring(filename.lastIndexOf(".")); - context.setOtherFileName(name + "_" + TemplateContext.PlaceHolder_PageNo + suffix); - } else { - context.setDirectory(siteRoot + catalog.getPath()); - String suffix = site.getStaticSuffix(context.getPublishPipeCode()); - context.setFirstFileName(content.getContentId() + StringUtils.DOT + suffix); - context.setOtherFileName( - content.getContentId() + "_" + TemplateContext.PlaceHolder_PageNo + StringUtils.DOT + suffix); - } - } - - private void doContentExStaticize(CmsContent content, String publishPipeCode) { - CmsSite site = this.siteService.getSite(content.getSiteId()); - CmsCatalog catalog = this.catalogService.getCatalog(content.getCatalogId()); - if (!catalog.isStaticize()) { - logger.warn("[{}]栏目设置不静态化[{}#{}]:{}", publishPipeCode, site.getName(), catalog.getName(), content.getTitle()); - return; // 不静态化直接跳过 - } - if (content.isLinkContent()) { - logger.warn("[{}]标题内容不需要静态化[ {}#{} ]:{}", publishPipeCode, site.getName(), catalog.getName(), content.getTitle()); - return; // 标题内容不需要静态化 - } - String exTemplate = ContentUtils.getContentExTemplate(content, catalog, publishPipeCode); - if (StringUtils.isEmpty(exTemplate)) { - return; // 未设置扩展模板直接跳过 - } - File templateFile = this.templateService.findTemplateFile(site, exTemplate, publishPipeCode); - if (templateFile == null) { - logger.warn("[{}]内容扩展模板未设置或文件不存在[ {}#{} ]:{}", publishPipeCode, site.getName(), catalog.getName(), content.getTitle()); - return; - } - try { - long s = System.currentTimeMillis(); - // 自定义模板上下文 - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, exTemplate); - TemplateContext templateContext = new TemplateContext(templateKey, false, publishPipeCode); - // 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 siteRoot = SiteUtils.getSiteRoot(site, publishPipeCode); - templateContext.setDirectory(siteRoot + catalog.getPath()); - String fileName = ContentUtils.getContextExFileName(content.getContentId(), site.getStaticSuffix(publishPipeCode)); - templateContext.setFirstFileName(fileName); - // 静态化 - this.staticizeService.process(templateContext); - logger.debug("[{}]内容扩展模板解析[ {}#{} ]:{},耗时:{}ms", publishPipeCode, site.getName(), - catalog.getName(), content.getTitle(), (System.currentTimeMillis() - s)); - } catch (TemplateException | IOException e) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}] 内容扩展模板解析失败 [{1}#{2}]:{3}", - publishPipeCode, site.getName(), catalog.getName(), content.getTitle())), e); - } - } - - private String getDetailTemplate(CmsSite site, CmsCatalog catalog, CmsContent content, String publishPipeCode) { - String detailTemplate = PublishPipeProp_ContentTemplate.getValue(publishPipeCode, - content.getPublishPipeProps()); - if (StringUtils.isEmpty(detailTemplate)) { - // 无内容独立模板取栏目配置 - detailTemplate = this.publishPipeService.getPublishPipePropValue( - IPublishPipeProp.DetailTemplatePropPrefix + content.getContentType(), publishPipeCode, - catalog.getPublishPipeProps()); - if (StringUtils.isEmpty(detailTemplate)) { - // 无栏目配置去站点默认模板配置 - detailTemplate = this.publishPipeService.getPublishPipePropValue( - IPublishPipeProp.DefaultDetailTemplatePropPrefix + content.getContentType(), publishPipeCode, - site.getPublishPipeProps()); - } - } - return detailTemplate; - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/SiteStaticizeType.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/SiteStaticizeType.java deleted file mode 100644 index 3c5fe841..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/SiteStaticizeType.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.publish.staticize; - -import com.chestnut.common.async.AsyncTaskManager; -import com.chestnut.common.staticize.StaticizeService; -import com.chestnut.common.staticize.core.TemplateContext; -import com.chestnut.common.utils.IdUtils; -import com.chestnut.common.utils.StringUtils; -import com.chestnut.contentcore.domain.CmsSite; -import com.chestnut.contentcore.publish.IStaticizeType; -import com.chestnut.contentcore.service.IPublishPipeService; -import com.chestnut.contentcore.service.ISiteService; -import com.chestnut.contentcore.service.ITemplateService; -import com.chestnut.contentcore.template.ITemplateType; -import com.chestnut.contentcore.template.impl.SiteTemplateType; -import com.chestnut.contentcore.util.SiteUtils; -import com.chestnut.contentcore.util.TemplateUtils; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -import java.io.File; -import java.util.Objects; - -/** - * SiteStaticizeType - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@RequiredArgsConstructor -@Component(IStaticizeType.BEAN_PREFIX + SiteStaticizeType.TYPE) -public class SiteStaticizeType implements IStaticizeType { - - public static final String TYPE = "site"; - - private final ISiteService siteService; - - private final IPublishPipeService publishPipeService; - - private final ITemplateService templateService; - - private final StaticizeService staticizeService; - - @Override - public String getType() { - return TYPE; - } - - @Override - public void staticize(String dataId) { - Long siteId = Long.valueOf(dataId); - if (IdUtils.validate(siteId)) { - CmsSite site = this.siteService.getSite(siteId); - if (Objects.nonNull(site)) { - this.siteStaticize(site); - } - } - } - - public void siteStaticize(CmsSite site) { - this.publishPipeService.getPublishPipes(site.getSiteId()) - .forEach(pp -> doSiteStaticize(site, pp.getCode())); - } - - private void doSiteStaticize(CmsSite site, String publishPipeCode) { - try { - AsyncTaskManager - .setTaskMessage(StringUtils.messageFormat("[{0}]正在发布站点首页:{1}", publishPipeCode, site.getName())); - - String indexTemplate = site.getIndexTemplate(publishPipeCode); - File templateFile = this.templateService.findTemplateFile(site, indexTemplate, publishPipeCode); - if (Objects.isNull(templateFile)) { - logger.warn(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]站点首页模板未配置或不存在:{1}", - publishPipeCode, site.getSiteId() + "#" + site.getName()))); - return; - } - // 模板ID = 通道:站点目录:模板文件名 - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, indexTemplate); - TemplateContext context = new TemplateContext(templateKey, false, publishPipeCode); - // init template datamode - TemplateUtils.initGlobalVariables(site, context); - // init templateType data to datamode - ITemplateType templateType = templateService.getTemplateType(SiteTemplateType.TypeId); - templateType.initTemplateData(site.getSiteId(), context); - - long s = System.currentTimeMillis(); - context.setDirectory(SiteUtils.getSiteRoot(site, publishPipeCode)); - context.setFirstFileName("index" + StringUtils.DOT + site.getStaticSuffix(publishPipeCode)); - this.staticizeService.process(context); - logger.debug("[{}]首页模板解析:{},耗时:{}ms", publishPipeCode, site.getName(), (System.currentTimeMillis() - s)); - } catch (Exception e) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}][{1}]站点首页解析失败:{2}", - publishPipeCode, site.getName(), e.getMessage())), e); - } - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/PublishTaskReceiver.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/PublishTaskReceiver.java deleted file mode 100644 index 6743c3ec..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/PublishTaskReceiver.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.publish.strategies; - -import com.chestnut.contentcore.publish.CmsStaticizeService; -import com.chestnut.contentcore.publish.IStaticizeType; -import com.chestnut.contentcore.publish.strategies.RedisStreamPublishStrategy; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.MapUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.redis.connection.stream.Consumer; -import org.springframework.data.redis.connection.stream.MapRecord; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.data.redis.stream.StreamListener; - -import java.util.Map; -import java.util.Objects; - -/** - * 发布任务消费监听 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Slf4j -@RequiredArgsConstructor -public class PublishTaskReceiver implements StreamListener> { - - private final static Logger logger = LoggerFactory.getLogger("publish"); - - private final CmsStaticizeService cmsStaticizeService; - - private final StringRedisTemplate redisTemplate; - - @Setter - @Getter - private Consumer consumer; - - @Override - public void onMessage(MapRecord message) { - String stream = message.getStream(); - if (Objects.nonNull(stream)) { - try { - Map map = message.getValue(); - String type = MapUtils.getString(map, "type"); - - IStaticizeType staticizeType = cmsStaticizeService.getStaticizeType(type); - if (Objects.nonNull(staticizeType)) { - staticizeType.staticize(map.get("id")); - } - } catch(Exception e) { - logger.error("Publish err.", e); - } finally { - redisTemplate.opsForStream().acknowledge( - stream, - RedisStreamPublishStrategy.PublishConsumerGroup, - message.getId().getValue() - ); - redisTemplate.opsForStream().delete(stream, message.getId().getValue()); - } - } - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/RedisSetPublishStrategy.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/RedisSetPublishStrategy.java deleted file mode 100644 index d0ae6034..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/RedisSetPublishStrategy.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.publish.strategies; - -import com.chestnut.common.async.AsyncTask; -import com.chestnut.contentcore.config.properties.CMSPublishProperties; -import com.chestnut.contentcore.publish.CmsStaticizeService; -import com.chestnut.contentcore.publish.IPublishStrategy; -import com.chestnut.contentcore.publish.IStaticizeType; -import lombok.RequiredArgsConstructor; -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; -import org.springframework.scheduling.support.PeriodicTrigger; -import org.springframework.stereotype.Component; - -import java.time.Duration; -import java.util.Objects; - -/** - * 发布策略:Redis Set - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Component -@RequiredArgsConstructor -@ConditionalOnProperty(prefix = CMSPublishProperties.PREFIX, name = "strategy", havingValue = RedisSetPublishStrategy.ID) -public class RedisSetPublishStrategy implements IPublishStrategy, CommandLineRunner { - - public static final String ID = "RedisSet"; - - static final String CACHE_NAME = "cms:publish:list"; - - private final StringRedisTemplate redisTemplate; - - private final CMSPublishProperties properties; - - private final CmsStaticizeService cmsStaticizeService; - - private final ThreadPoolTaskScheduler threadPoolTaskScheduler; - - @Override - public String getId() { - return ID; - } - - @Override - public void publish(String dataType, String dataId) { - redisTemplate.opsForSet().add(CACHE_NAME, dataType+"-"+dataId); - } - - @Override - public long getTaskCount() { - Long size = redisTemplate.opsForSet().size(CACHE_NAME); - return Objects.requireNonNullElse(size, 0L); - } - - @Override - public void cleanTasks() { - redisTemplate.opsForSet().remove(CACHE_NAME); - } - - @Override - public void run(String... args) throws Exception { - for (int i = 1; i <= properties.getConsumerCount(); i++) { - // 创建一个3秒间隔执行的定时任务 - PeriodicTrigger periodicTrigger = new PeriodicTrigger(Duration.ofSeconds(3L)); - periodicTrigger.setFixedRate(false); - - AsyncTask task = new AsyncTask() { - - @Override - public void run0() { - String data = null; - do { - try { - data = redisTemplate.opsForSet().pop(CACHE_NAME); - if (Objects.nonNull(data)) { - String[] split = data.split("-"); - String dataType = split[0]; - String dataId = split[1]; - - IStaticizeType staticizeType = cmsStaticizeService.getStaticizeType(dataType); - if (Objects.nonNull(staticizeType)) { - staticizeType.staticize(dataId); - } - } - } catch (Exception e) { - IStaticizeType.logger.error("静态化失败", e); - } - } while(Objects.nonNull(data)); - } - }; - task.setTaskId("cms-publish-" + i); - task.setType("CMS-PUBLISH"); - threadPoolTaskScheduler.schedule(task, periodicTrigger); - } - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/RedisStreamPublishStrategy.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/RedisStreamPublishStrategy.java deleted file mode 100644 index 9691460c..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/RedisStreamPublishStrategy.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.publish.strategies; - -import com.chestnut.contentcore.config.properties.CMSPublishProperties; -import com.chestnut.contentcore.publish.CmsStaticizeService; -import com.chestnut.contentcore.publish.IPublishStrategy; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.data.redis.connection.stream.*; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.data.redis.stream.StreamMessageListenerContainer; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import org.springframework.stereotype.Component; - -import java.time.Duration; -import java.util.Map; - -/** - * 发布策略:Redis Stream - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Slf4j -@Component -@RequiredArgsConstructor -@ConditionalOnProperty(prefix = CMSPublishProperties.PREFIX, name = "strategy", havingValue = RedisStreamPublishStrategy.ID) -public class RedisStreamPublishStrategy implements IPublishStrategy { - - public static final String ID = "RedisStream"; - - public static final String PublishStreamName = "ChestnutCMSPublishStream"; - - public static final String PublishConsumerGroup = "ChestnutCMSPublishConsumerGroup"; - - private final CMSPublishProperties properties; - - private final StringRedisTemplate redisTemplate; - - private final CmsStaticizeService cmsStaticizeService; - - @Override - public String getId() { - return ID; - } - - @Override - public void publish(String dataType, String dataId) { - MapRecord record = MapRecord.create(PublishStreamName, Map.of( - "type", dataType, - "id", dataId - )); - redisTemplate.opsForStream().add(record); - } - - @Override - public long getTaskCount() { - StreamInfo.XInfoStream info = redisTemplate.opsForStream().info(PublishStreamName); - return info.streamLength(); - } - - @Override - public void cleanTasks() { - try { - redisTemplate.delete(PublishStreamName); - redisTemplate.opsForStream().createGroup(PublishStreamName, PublishConsumerGroup); - } catch (Exception ignored) { - } - } - - @Bean - public StreamMessageListenerContainer> streamMessageListenerContainer() { - // 启动清理消息队列数据 - if (properties.isClearOnStart()) { - redisTemplate.delete(PublishStreamName); - } - // 监听容器配置 - StreamMessageListenerContainer.StreamMessageListenerContainerOptions> streamMessageListenerContainerOptions = StreamMessageListenerContainer.StreamMessageListenerContainerOptions - .builder() - .batchSize(10) // 一次拉取消息数量 - .pollTimeout(Duration.ofSeconds(2)) // 拉取消息超时时间 - .executor(cmsPublishThreadPoolTaskExecutor()) - .build(); - // 创建监听容器 - StreamMessageListenerContainer> container = StreamMessageListenerContainer - .create(redisTemplate.getRequiredConnectionFactory(), streamMessageListenerContainerOptions); - //创建消费者组 - try { - redisTemplate.opsForStream().createGroup(PublishStreamName, PublishConsumerGroup); - } catch (Exception e) { - log.info("消费者组:{} 已存在", PublishConsumerGroup); - } - // 添加消费者 - for (int i = 0; i < properties.getConsumerCount(); i++) { - Consumer consumer = Consumer.from(PublishConsumerGroup, "cms-publish-consumer-" + i); - PublishTaskReceiver publishTaskReceiver = new PublishTaskReceiver(cmsStaticizeService, redisTemplate); - publishTaskReceiver.setConsumer(consumer); - container.receive(consumer, StreamOffset.create(PublishStreamName, ReadOffset.lastConsumed()), publishTaskReceiver); - } - container.start(); - return container; - } - - @Bean - ThreadPoolTaskExecutor cmsPublishThreadPoolTaskExecutor() { - ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - executor.setThreadNamePrefix(properties.getPool().getThreadNamePrefix()); - executor.setCorePoolSize(properties.getPool().getCoreSize()); - executor.setQueueCapacity(properties.getPool().getQueueCapacity()); - executor.setMaxPoolSize(properties.getPool().getMaxSize()); - executor.setKeepAliveSeconds((int) properties.getPool().getKeepAlive().getSeconds()); - executor.setAllowCoreThreadTimeOut(this.properties.getPool().isAllowCoreThreadTimeout()); - executor.setWaitForTasksToCompleteOnShutdown(properties.getShutdown().isAwaitTermination()); - executor.setAwaitTerminationSeconds((int) properties.getShutdown().getAwaitTerminationPeriod().toSeconds()); - log.info("Cms publish task executor initialize: {}", executor.getThreadNamePrefix()); - executor.initialize(); - return executor; - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/ThreadPoolPublishStrategy.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/ThreadPoolPublishStrategy.java deleted file mode 100644 index 491514b1..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/ThreadPoolPublishStrategy.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.publish.strategies; - -import com.chestnut.contentcore.config.properties.CMSPublishProperties; -import com.chestnut.contentcore.publish.CmsStaticizeService; -import com.chestnut.contentcore.publish.IPublishStrategy; -import com.chestnut.contentcore.publish.IStaticizeType; -import lombok.RequiredArgsConstructor; -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import org.springframework.stereotype.Component; - -import java.util.Objects; -import java.util.concurrent.ThreadPoolExecutor; - -/** - * 发布策略:ThreadPool - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Component -@RequiredArgsConstructor -@ConditionalOnProperty(prefix = CMSPublishProperties.PREFIX, name = "strategy", havingValue = ThreadPoolPublishStrategy.ID) -public class ThreadPoolPublishStrategy implements IPublishStrategy, CommandLineRunner { - - public static final String ID = "ThreadPool"; - - private final CMSPublishProperties properties; - - private final CmsStaticizeService cmsStaticizeService; - - private ThreadPoolTaskExecutor threadPoolTaskExecutor; - - @Override - public String getId() { - return ID; - } - - @Override - public void publish(String dataType, String dataId) { - IStaticizeType staticizeType = cmsStaticizeService.getStaticizeType(dataType); - if (Objects.nonNull(staticizeType)) { - threadPoolTaskExecutor.execute(() -> staticizeType.staticize(dataId)); - } - } - - @Override - public long getTaskCount() { - // 返回线程池队列信息 - return threadPoolTaskExecutor.getQueueSize(); - } - - @Override - public void cleanTasks() { - // 清空线程池队列 - threadPoolTaskExecutor.getThreadPoolExecutor().getQueue().clear(); - } - - @Override - public void run(String... args) throws Exception { - ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - executor.setThreadNamePrefix(properties.getPool().getThreadNamePrefix()); - executor.setCorePoolSize(properties.getPool().getCoreSize()); - executor.setQueueCapacity(properties.getPool().getQueueCapacity()); - executor.setMaxPoolSize(properties.getPool().getMaxSize()); - executor.setKeepAliveSeconds((int) properties.getPool().getKeepAlive().getSeconds()); - executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 默认池满使用调用线程执行 - executor.setAllowCoreThreadTimeOut(this.properties.getPool().isAllowCoreThreadTimeout()); - executor.setWaitForTasksToCompleteOnShutdown(properties.getShutdown().isAwaitTermination()); - executor.setAwaitTerminationSeconds((int) properties.getShutdown().getAwaitTerminationPeriod().toSeconds()); - executor.initialize(); - this.threadPoolTaskExecutor = executor; - } -} diff --git a/chestnut-cms/chestnut-cms-exmodel/src/main/java/com/chestnut/exmodel/domain/dto/XModelFieldDataDTO.java b/chestnut-cms/chestnut-cms-exmodel/src/main/java/com/chestnut/exmodel/domain/dto/XModelFieldDataDTO.java deleted file mode 100644 index 2ea8804e..00000000 --- a/chestnut-cms/chestnut-cms-exmodel/src/main/java/com/chestnut/exmodel/domain/dto/XModelFieldDataDTO.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.chestnut.exmodel.domain.dto; - -import com.chestnut.exmodel.CmsExtendMetaModelType; -import com.chestnut.xmodel.domain.XModelField; -import lombok.Getter; -import lombok.Setter; - -import java.util.List; -import java.util.Map; - -@Getter -@Setter -public class XModelFieldDataDTO { - - private String label; - - private String fieldName; - - private String controlType; - - private List> validations; - - private List> options; - - private Object value; - - private String valueSrc; - - public static XModelFieldDataDTO newInstance(XModelField field, String value) { - XModelFieldDataDTO dto = new XModelFieldDataDTO(); - dto.setLabel(field.getName()); - dto.setFieldName(CmsExtendMetaModelType.DATA_FIELD_PREFIX + field.getCode()); - dto.setControlType(field.getControlType()); - dto.setValidations(field.getValidations()); - dto.setValue(value); - return dto; - } -} \ No newline at end of file diff --git a/chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/core/CmsStat.java b/chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/core/CmsStat.java deleted file mode 100644 index 8afa7d2c..00000000 --- a/chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/core/CmsStat.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.chestnut.cms.stat.core; - -import com.chestnut.cms.stat.domain.CmsSiteVisitLog; - -/** - * - * - * @author 兮玥 - * @email 190785909@qq.com - */ -public interface CmsStat { - - void deal(CmsSiteVisitLog log); -} \ No newline at end of file diff --git a/chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/core/impl/CmsContentViewStat.java b/chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/core/impl/CmsContentViewStat.java deleted file mode 100644 index fb71146f..00000000 --- a/chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/core/impl/CmsContentViewStat.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.chestnut.cms.stat.core.impl; - -import com.chestnut.cms.stat.core.CmsStat; -import com.chestnut.cms.stat.domain.CmsSiteVisitLog; -import com.chestnut.contentcore.service.impl.ContentDynamicDataService; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -/** - * 内容动态浏览量统计 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Component -@RequiredArgsConstructor -public class CmsContentViewStat implements CmsStat { - - private final ContentDynamicDataService contentDynamicDataService; - - @Override - public void deal(final CmsSiteVisitLog log) { - this.contentDynamicDataService.increaseViewCount(log.getContentId()); - } -} \ No newline at end of file diff --git a/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/async/AsyncTaskExceptionHandler.java b/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/async/AsyncTaskExceptionHandler.java deleted file mode 100644 index c87b4989..00000000 --- a/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/async/AsyncTaskExceptionHandler.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.chestnut.common.async; - -import java.lang.reflect.Method; -import java.time.LocalDateTime; - -import org.apache.commons.lang3.ArrayUtils; -import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; - -import com.chestnut.common.async.enums.TaskStatus; - -import lombok.extern.slf4j.Slf4j; - -/** - * 异步任务异常处理器 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Slf4j -public class AsyncTaskExceptionHandler implements AsyncUncaughtExceptionHandler { - - @Override - public void handleUncaughtException(Throwable ex, Method method, Object... params) { - if (ArrayUtils.isNotEmpty(params) && params[0] instanceof AsyncTask task) { - task.setStatus(TaskStatus.FAILED); - task.setEndTime(LocalDateTime.now()); - task.addErrorMessage(ex.getMessage()); - AsyncTaskManager.setTaskMessage("Async task failed:" + ex.getMessage()); - log.error("Async task failed:{}", ex.getMessage()); - } - } -} \ No newline at end of file diff --git a/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/IStatType.java b/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/IStatType.java deleted file mode 100644 index 4a3bb382..00000000 --- a/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/IStatType.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.chestnut.stat; - -import java.util.List; - -/** - * 统计类型 - * - *

- * 每一个统计类型对应一种统计数据的存储及展示,前端根据统计类型进行分类展示 - *

- * - * @author 兮玥 - * @email 190785909@qq.com - */ -public interface IStatType { - - /** - * 统计菜单树 - */ - public List getStatMenus(); -} \ No newline at end of file diff --git a/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/RequestEvent.java b/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/RequestEvent.java deleted file mode 100644 index 848f598a..00000000 --- a/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/RequestEvent.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.chestnut.stat; - -import java.time.LocalDateTime; - -import com.chestnut.common.utils.IP2RegionUtils; -import com.chestnut.common.utils.ServletUtils; -import com.chestnut.common.utils.StringUtils; - -import eu.bitwalker.useragentutils.UserAgent; -import jakarta.servlet.http.HttpServletRequest; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class RequestEvent { - - /** - * 请求域 - */ - private String host; - - /** - * IP地址 - */ - private String ip; - - /** - * IP所属地区 - */ - private String address; - - /** - * 来源地址 - */ - private String referer; - - /** - * 浏览器类型 - */ - private String browser; - - /** - * UserAgent - */ - private String userAgent; - - /** - * 操作系统 - */ - private String os; - - /** - * 设备类型 - */ - private String deviceType; - - /** - * 语言 - */ - private String locale; - - /** - * 事件发生时间 - */ - private LocalDateTime evtTime; - - /** - * 提取request请求信息到RequestEvent - * - * @param request - */ - public void fill(HttpServletRequest request) { - this.setHost(request.getRemoteHost()); - this.setIp(ServletUtils.getIpAddr(request)); - this.setAddress(IP2RegionUtils.ip2Region(this.getIp())); - this.setReferer(ServletUtils.getReferer(request)); - this.setLocale(StringUtils.substringBefore(ServletUtils.getAcceptLanaguage(request), ",")); - - this.setUserAgent(ServletUtils.getUserAgent(request)); - UserAgent ua = ServletUtils.parseUserAgent(request); - this.setBrowser(ua.getBrowser().getName()); - this.setOs(ua.getOperatingSystem().getName()); - this.setDeviceType(ua.getOperatingSystem().getDeviceType().getName()); - } -} \ No newline at end of file diff --git a/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/StatMenu.java b/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/StatMenu.java deleted file mode 100644 index 4e71d3b6..00000000 --- a/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/StatMenu.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.chestnut.stat; - -/** - * 统计菜单 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -public record StatMenu(String menuId, String parentId, String name, int sort) { - -} \ No newline at end of file diff --git a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/intercepter/DemoModeIntercepter.java b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/intercepter/DemoModeIntercepter.java deleted file mode 100644 index 3f5c2da4..00000000 --- a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/intercepter/DemoModeIntercepter.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.chestnut.system.intercepter; - -import java.util.Objects; - -import org.springframework.http.HttpMethod; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.HandlerInterceptor; - -import com.chestnut.common.security.SecurityUtils; -import com.chestnut.common.security.exception.SecurityErrorCode; -import com.chestnut.system.annotation.IgnoreDemoMode; -import com.chestnut.system.security.StpAdminUtil; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; - -/** - * 演示模式拦截器 - */ -@RequiredArgsConstructor -public class DemoModeIntercepter implements HandlerInterceptor { - - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) - throws Exception { - String method = request.getMethod(); - if (StpAdminUtil.isLogin() && SecurityUtils.isSuperAdmin(StpAdminUtil.getLoginIdAsLong())) { - return true; // 超级管理员允许操作 - } - // 非Get且无忽略演示模式注解则抛出异常 - if (HttpMethod.POST.matches(method) || HttpMethod.PUT.matches(method) || HttpMethod.DELETE.matches(method)) { - if (handler instanceof HandlerMethod handlerMethod) { - IgnoreDemoMode ignoreDemoMode = handlerMethod.getMethodAnnotation(IgnoreDemoMode.class); - if (Objects.isNull(ignoreDemoMode)) { - throw SecurityErrorCode.DEMO_EXCEPTION.exception(); - } - } - } - return true; - } -} \ No newline at end of file diff --git a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/mapper/DataBaseMapper.java b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/mapper/DataBaseMapper.java deleted file mode 100644 index 1ed25b32..00000000 --- a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/mapper/DataBaseMapper.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(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.system.mapper; - -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; -import org.apache.ibatis.annotations.Update; - -public interface DataBaseMapper { - - /** - * 表字段是否存在 - * - * @param tableName - * @param columnName - * @return - */ - @Select("select count(*) from information_schema.columns where table_name = #{tableName} and column_name = #{columnName}") - public Integer isTableColumnExists(@Param("tableName") String tableName, @Param("columnName") String columnName); - - /** - * 添加表字段 - * - * @param tableName 表明 - * @param columnName 字段名 - * @param columnType 字段类型 - */ - @Update("alter table #{tableName} add column #{columnName} #{columnType}") - public void addTableColumn(@Param("tableName") String tableName, @Param("columnName") String columnName, - @Param("columnType") String columnType); - - /** - * 重命名表 - * - * @param oldName - * @param newName - */ - @Update("alter table #{oldTableName} rename #{newTableName}") - public void renameTable(String oldTableName, String newTableName); - - /** - * 清空表数据,自增清零 - * - * @param tableName - */ - @Update("truncate table ${tableName}") - public void truncateTable(@Param("tableName") String tableName); - - /** - * 当前数据库名 - */ - @Select("select database()") - public void getDatabaseName(); -} diff --git a/chestnut-ui/src/assets/images/alipay.png b/chestnut-ui/src/assets/images/alipay.png deleted file mode 100644 index 43b37926b36dc23ceba94d378072f21d00b1f261..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63358 zcmbTe30zEX`#*ltGA$~VN{a>|Bw1R}GPV|y$Pz_^kTxTv(lm$CqLq9UMI#|0Q(Co6 zX``e_`!>zAXw#XN>C~J#^SgVV=lgx0@Av!s|F7@wH#kPGbMA9r*L`2t^}gQMbrZG; zS>u}oG5_`fZ&?^=;ceh=!hHxLfNx@(w{G3?0Q`I5 zyT~F@==p#Ae9Pv|&qe+@;`2rSF``)JbJ73!PLO;l@sE4J0Du1oJE6VMA`y{=-~afC zii<9MB*er-#R(Dw!onX(DH$nANoh#}L0VQ?T4pi$5TxYfWf#jWd|w!3;qis1!0*M9 z1j&Uv{_j4*GDtyE#972yRAd#jNI^tYK}1*y5rO>TK=TXA|HlUiE+#GkrX(!`Zpd8% zrY|bG2uxO745(2ga6vI*3gU_@x9pZsI&zM%%6sY7I}cJMwfAI|E8G7-R&P6hEl5gQ zMRl2)`kJ*m>(*~DFf=mWzGLU!eHNBh*82|}J$C$r!^u;QE*CCda=q;4e*K2eOrs5d<0pwPQeVD$o%SaE?Z@n#+`RmPPlcZ=Dyyn%zI?6y+4QTq zrM0cSqmRw$9~d0^Jv_ploSL5D&7yPj3vz+g`ny>FDcOIMO99BW2&{n^VL>jDMZVyV zsDhaI$}JL#yN?jgc`L2jdPj2Uo(Cye=EVj*M3N=tTyOd!(9;VZ<77*1Pl6q zlI%YP`=?wT&|*;$uy~>h5DA)3#pSjLp&%A^3S4)i`F&=w6=ZqLq;(~CAU^FnjcR+& z{~D5;-MPWvvS$PmQ8MzC_`N0O`rJDqr0^F1C4{C|;0;0u)ovC-bFR)+LWocaf3*}m zg~wDG@b6CPxmaBGI~ZIW(+Ah`%S_cY^d8$z3#CyY+m}{pLg@1jUpMLRn_8yp2Jejz zZnSDo?acYGwf(y#WWqqBop`T>Pzr$u3!!o?h7hXTNn#sPI+F0a#C9Phgv4$!h0w;) ziETni!XE#|5<*|C(P1GJY^E!O?ynO<;p>@~DD&%ynnDP1eFaa7LsT^|`FFHmz5iwI zR+wc5|0vuT%qIyUR;+^%8h92sB!re6rG4w2wm07ae%f$A2=z;o*wW;7Iv!zFL&DUC z$=ID;L4?$V5qv~q!V#ZJM8 zSKhwfFWl6lj4Q@?+ZvWd4>BLAZnb=})~NQ6s92~LQ3#0_0Vyuiq=4Ytm@K;U3N(ww zP@^7gDc<{XW?j^$-?t;T@L#AeYaT$l2^LfP4SrmE*;2cDJYQuL~#sy>{H zj^7t?@+lV6wz67Ie#H`66l1+0PY7LL%H!S4kG)amifG!A7K02zb$q&qzt5}vOMUOZ zt&I!Tu#UO?Cra)ZVhh10M6P<;xUCS{BR{sVSV3lFAr$X3&O~e*(4DiqNWn)Eg&0DX zq3&n(1{KnRIrJr+!w$3Rmtxav{1ZxS`>W$#}M4*gx5*X<`qfMKg zP-Q3UH_DMnWB6(B3p`NWY5&V$c;mo*>&Sa2OjchjaQR&Ll#^UD*@;Wq2%+^Mf@eZ# z?0OFFwTswlH{QqXbrd`%ohL_<6mujEI!msX(G-8p2+U;<=)`|_8_!6-aLV4;>cW~` zE6*I-sX%T>xC^tU;EsotxbDyC7DT^nnZx0ti1ueU^v*;Ou6`2bA9Pjwt~O-;Z?$n|D=D1RsApx@Ug z#$sBL`~$feRgu&ksA~VC%W?+w4mZ1$g%BMt;4!|KIUM$KI$BWp;E2}9iARsN<=QA( zs|{&35@vIeq0^tZ#sJTP@Ak$plUK z^DCrA5adOg-s7;pB=EAx>VA2KBYqRU0;47rUYsDF>B)>B%NdX)sPd&hFnM->K&6_^ zw`f)$Jh|c-XYWc|i({qDY8&24eT8lie{9Rt<`Ta%?~%}r1niXw@2(Ka;sZPVnZ8bR zf`~>t@X~6q@PAt1&wpc-Kj_GzUeutK2MZX?bMz3BQt@6+LzE-!6NfI_F{;X&r=`4p z^>W*RPZ#ewf9+Z^ruLZM3T(P^X>Yc%U}%}jU7{1Vtz2w@5% z;F8Vg)JIp6u%$ZHy~xqnHmw>qqf*xRbD>?hzG0`ppwsVGOF)2Ogv9Zqd2WM&L#rP$ zHKRm&`$hlmy!x&SAsHek4PQLXz;`hcnC`vk2Avott1ULN39s!Hy%wl5d)m8y9u8 zE6SasPCt9OH7PQE7Jj!YWe;cY>yBlD%{^uw{dVXYBBt=JkBKQN?d86vBU6>hMqDxT z?a3`{1dU*~Tnfo(u^{Vz3EC(+s5xXtI55Y@mi&8U=MY*|a}-bT*lwNXU;B`?PGMQGXCKrkAVUJ8me1_6@P@ zaOoK`e$pWw|3b=ljU=%~nGyNKY~PxCK#)a?dxPm0$Jm%pw)nJ}v-@`1`-C?9{&r&eQ-9_`U%j=1G$Vi@uq8 z*2{*Sb_cu2-RszzVfaqgP%pQxQ_Az(^&;K4%#MBh+nQ8#M&h>l9iW7DaCu!Xk;HmM zLJr4DV>;aY5ZaR8xJJvyi4Pw>7}#nbiQsQ`G7Wz-Mg9_*AQR_u1t6i_#8+hGlU*n4dC`Y{{}Aq;=sdNW(c8|6f%h0$PI-CY)L*Rjh{%w={X$`MqSVg>A$&)=Rm{}X6|+& z^yFU=4(bXZ1Ygb16_-{3>d-_fNIf)bJ9pNO8-B;3M|SAK|1r_tOoBkOg^dnEX1ul=KPwL@6h0x4YA44E|{Da;9>bB?d*(4UL7uByTjMYAjoU*$*(RS_P96LnD4{!Lhiki`00r;!?W5!3&O(UmGun$# zN!V?YtKIxuD|1>y9S^)L%FF(rH_l983i7zz0W=z{^g%%Z3w2_{VYm#^^Kfl&z&nkS ztsY?o@`Qw3Z*Aoc->2NC#3suY88bWWfu zglz1YiVORbGH2UbLFP+%(C0lqF*@x~lcV_ITn>pZ|C>4Q_y|n^(I*wIy;7IE;-_b_9gKSXoPLtGtWc zikO!%ZH)r^c^Bz|2D!6|XU47htRZk8t;nMpW!vm9)bLaB*W2?gE=VC<7Jt83ac3i8 zDw=;8JkiEn%JibNAFUxt`!GZBML!Lg%iW@1cR9CrbsO+%&p2I^IR6qW7>e;2pr9-D ziO5MxdoNyNVmH`44}8dyU4D{6sNRnY|F>%>KqybZaD~y@BCxW?qow?On zh?X|H(`*sYOGHcOi8#4^iU(pG4L#{kc5DBmN059P8Y_KUdlH+hK)P!FT`Z=kl!UM?h`@;LFSp=CeH#w(!3B8ca=x zrK@NDhl`u~l_aj~IWKX?>noH;YH^sV`EXKJ$FV5)#8$oc6O!jQJ9#KPrGW+4>6<{! z^f{`brp9T*@j^(_Tz&4A&&v~8McvMddaxhDx<$r8GNO+u#PU!s0b5$f6GeKf8Wevg+J*UeT@ylwa{}}X zUwZhp^bA@b3+m6a-eqUzQAT2=5fLw91s&ZWKkgL3C0F(;6ub4++fUi%G}*=^d3o}F z$B!I8scPTu*+0kx5egVN0^lWx>rY5oEx}0eey}4Nlu!Nk^-b`2(>>DES+}L&+2D#7 zDWY!FtNx2hgMc&dEnPvJdydNiBb@>MP2;&NB^E~P$sj6~zboA-ghHKAm%edTwri+k zyQzyHo9!E?F=0Ntj_Z}Lt5wC{$>NZ;zQj^*3$C!F1T>HL-^=&(2)U7?RHQ7t1O4)oj3JGhicQ*U;IbdR4yrPRyaa*xCm zEeyP_#QmXcRw~+PwQQL(|0~Ftf!PL```O`AA}pesAN-lNkt-jmhh2PA{-$B=yTw~_ zvn>>&Hu#^tpc!|4{0LmG$zw(a99nx@ z18h|>uoTx#y%&fOE~CQC__MhT!iY%WRy~?&t{a&;6nmv*Li){aHBm9^>-62^U=ngt z9@V2q!K_S98KJ627HPQK*(ZcLtFnGxO0>(BVP^m79aM^Dx}J97S2OpQDx+#Ji+hoZgKdO|W!C(MINLDUJFhs&2>BrqWgC8RC| zojS?QrtVUILLYBY=ny;{3vIp99p!t4zx(?wucacDVEUp=Ry?i(p3K8r0Ytyf?p5^Y zQO*2ey4;(+{mS%T_Xho6lxF2ie%@vIIscGfc`c(6e?n^{WnKycHkpL3lJ9WpbN=*} zdYG#dKB3fy&D%w|SZ{ohTeM$a%g3mXT<_47dRVG6j2h$}n*_6J8FL5pE9LoXfKAN% z{?wh;#pTUO+_w}NxcxvAX}b6AVL~N|t6^6S&ucS5o`-Ch1#9=AhUI`M>wp;}H}oqd z;fut3$r_EN8YuZ>sGXvDZeK#Y2Re|cb>33t+K;jGm0H`Hlu-+E8WXu3hP^(z2ZU;; zlK`98>>_4@F>D#A(Ke7KDB19`f6(+$54Ke_b@$uLdHE;OUEXv$tto!t7j+@tLbhzj zvJX?Z9L=7I>|w+_8O`1cA~Y|FOmiq>A~%TG^M8SvI2C5KG3E}rmeJ=Y-V34O*u#tw z4O}{!f7%@Y)Yvf@t~R?T_|@=y3xoA+r*4slF3%^w!1Yt8qULK2$l6ZqnmDXaLOdO? zv~4Uqfo}^uUGv6a`W)D4s&MU6b91;&u@i*Q@ynu<#050-jWig8Z4*Le?|Sh~v1oJ} zha^zw4TVwV03lS>%6>9x0nz#v_Cs(ZzSXa(rcf(Z=QA-hv*w+<3Xig?tLLIv+*?I+ z+H-Y0;?Kag%W+#cKA$`T9fS~rTs~1opVLd01ydhSz+(^K2*?KSFQ(5-2%(Sa5H9{F zcK#rJf;dF(t%9Lh5_d|6Uo+P_%LQSGh!KICT0`Uk+sJe-5<;n-xk)&qgUkUWipdo?I_^K|Qg#K!QY5aHZ*-+gn622lH<2+lTX%cJx+I@(wXGtPpmxNVWc^g{8-|)SrIPx3yiGi*ML{d>*MjSXlsDo zz3H7yVuUhzi(5(4t=GwUbmV3lmf}$j^N2s->0Di|J}zqs9_yxp4Dp{lVgiYkPRtjt z!IYAC>fDBE6Iix_J#4C#=UI3x;q})m82^h`%tgt8n{!2_ec!u$zhEHlgmZGiIv91n z7D9bj08E*{@KdZunFe z{8bccB>WfyGJesUqG7l>Y(5%U~hjhoa!A1MkNtJy&y<{T}fKh11;w3F#TT!3<#yoRvO>T z1M#`xQ$!2lNvdt5cvrck+KLNN_jfRADYBO-Y*^u>Tb8N!*EgqYJY(iMLfY2pXtG>0 z>ml0c2nnI8WTX$bs*LlEhwFIZ9j1VT_rxwJ2qAOl8Pw{1uMqO^P<3#kGII}3j(xxR z=e#%Fvvn*7MlQ70xVfAlN5Yc4OfgM&5*7<6i|{qLDg46`wGu*)*yBc%E*FP)$OAfbWn?j2ig}x;ph7JCYPZm-ZT`T77UHxoWZbm)L`sv+}FnonK@O zm1!z&-I+K`2_qrb>7VK78v5-VxSd%Ai18JE4?%bk^>RTDy?gt6uz^oH@+p((8h6>W zJ>G78yUeDU6Xj}9<08C^jQCck^EL4{qC%-kTG<&AIkxQ9%=f6mNWV|xiPQT!_l1%^ z8hyUS@vcc{lsABUDxK09%&S0yx$d^IR0G_!nSN}iW4GY_sVm3NBwwlQoxL^gT(SX1 z*IA8gyuw?1^M0dg$V<9$-mP%VsZ|mpswT0pV4cO8oo*2NY zO2)jbmQn>Y)#(Ry@B7Pn@d?*@hW8xtWV6Me?3z+`T6tQudK>u|T)quvbxjkjP@O$OU>^SxX> zxX(23(#ROykl+Jedj{%e2T8peMKCGBv&+Xn7&@O4+TgebJ0cQBKi2llb^E{yDu_fzQ^QDOh5| z^i6uojq`*GA6Xgw z#y{D%sNxR(V-M=tcaeSabss(+J?2;8ITft@>5+s(!O&=Bs|vPv-pyNsifs{}?>@ zF_Y3$`7TE?#=pU^2~6n)aq@|+3|{5s0ziWv1Ut+i`q*-U5L%~)4&#FW2d9l2mCn~w zWq{zj>F5vF8oOBol7KXvBZ8q|fGqOl(}p{wnch)`lX` z&t(jeaM=hD?+2-XO8PM0fIps*##2DFXMQ}C%fE@25fy>C`yTr_ea54@gL)!9KQZA6 z@1)wMbB_}yo0G&{v~T;bx=jkd-Vz~rK}NT_a4LhZqPa*c0sjm_g%!42kITU$TERcw zz>{VWZ65|+6xYt`<;%6hzo!`!izsu@S0My20e>Z9Xj|VbrUrBC%FWFiXYQ5iVr%1; z>m121ez4SCdY~^+O921dQU{W8GycHw_?f@RlQOZrD~&e`5R8~ zqEqfSXE~Mmvo{&Kr}ujvtzF_+e_u>5uIg6QC8ogw9||bDG(0T!HjJ7!!*fo%h%_Q< zX2Uz9gYO5^ZNQX-xV1-Xbp+4Px@rLGhi#BI5FfWc)-U;RRey0k0fj-eDr3K7#5r zgqtg&#Lr|E1G<8HM>0J?_Ipv98`8ePscYj0wUpvVv&ze$m0~liO2KXmJ`#&v8R|RiUosu$=Kh={} z@G((r-NRG+?h+pCuZvpDFJe^mwYqD#Aw?Fo8LR%&v@b%9 z@=~d*>dGq>xARfs{*Pi#Q{Q?&ybbHZmno<|K6rkt+-gyh}U0Mx%XMkVf9M!Q?d;_$Oofbi*AeZmjM)LF zuc`L$^47#vEy>zwKJ{jn@r=p3TLIGczmuM%L67-*prI7nH}e&O9QdqV1X&u>^+|0* zBda^K-SU)1viHkAwO3Qf)~(Tuc^6{(cFXtejL-0GI&!7Ax);^Xuhy5tf031nZIOIO z6h@4=rVfmgey&GL3tKjgpXCpGX!5Rpo_va|PBb)YJ52baim5;@xD<(R4YwNrGP~Cd zR$)q$`qTY9@XvY7`5hkf5(1E5vBt^m`Ml?Xd!>3*!$wmgH?I|BMRyHtMeULS0B_RH z2@Oa(wKDqE1*Y$@#hf+A!_~^nbmt}zONM+X=JwKEb&+L$W=ZJa?q%Y&+V3?#Fw~C2(cOZY385 z`Tz=I6T5G~ma|xNi?;TIWWd<-JCWD<#0aWk+Q|JHgUur+ew?v<=<+T4!mctSDUI7# zu3CThH}jYbu3oSj)v+cPaoNbc@@xe#F5;CRluMZfTihINbe<@EG-?v0e(6dhD9_Uo z7~iiSN*Ysk1@XY18A|F1pm!W)>j@!BK z$MYll*CnnSie7X4>Z^pS4$%1dZBLb2n32T)Q4iOh)c{2PwZ zCPJrmmv3d;1S;8V{<=|xTUjOJzG8f1ni|B(WW<$j25};Lfh&ANRHp9bTT)3}yU$*_ zAl=bm402zGTx5(S@a8izo=s_lyA;M~tUtg1k*37Sfd_kC#$KM04OjxsbNNO_M>Z}+{@9mPgyu`yWJV7i)5~6G zxRf?GpaLhL_cHv9Pd69uPnEsaLzX+;)wNr5t^YacanmK4fsLQa>^EDPg^f9kc>|?u zAS6tkg9PAeVZ1v{rVi|0qTzJuWJhltS|uSxaUIs#p0Q?XcYa{S*A9`>+pfo& z2=Yl68B4&Aedq);c!aTp5|Dj9rXbx9Xdo zORGyiRo_=+q8sjFJuul$ZYT^1z7YKR{%%d4CI!=AfT%)8AAsuvK{Cko?ARwVSS2op zxmMw+&F}k>f${oZ>lHg!@7s|qY3)^e2-058cZh?_tH{Wn*eF1E=tt3IvE4|oGkX0+ z8%nbH)WlG&OpG4L`DnA6y~|~Z<2UJ$<@*U{MU4c|Ja&MNZj7yJy~=%=7v-RN@KYCm7L zM6oF~KjSQ}o|9d$BrxI2lo<2!r@K*t6r=I(S*PtB^DO{n_X8C#HwP8;m6$fy?hyJY z!%y{8Qgv%$U{$c+mHCljmy?PYVdIAUyFmvdqf-jC9svYFAj0J;G+nsd`43Hj9(rr2 zLZD_UQTXN;+_#2Vl)E*Fku?XJ7QBqc{N;;oc3t#NzA7?8L=F7|3W} zYY4vf@~xJz=eFz}e@v}hTqy1>+|!*-e;pO?`hG#*M-6&&TKAfq2#}LEoZ3_B-03S8su%Ap`IQ($&e9np zvl*ztD7$2KT$XR?{M&pBVi!G~Zod3vJGLYFjLq@LBcBpw_w2Y3GjFoJsvzuOfqk9! zcHeNZ71{dFfO^V$k*mGscIbwhvHhu3W7M~g8KG`jlIB<1K#r#O~OIY-q9Y(l1pI6N}!WHI8hCdYn97ZWc`$V z7FTRvz4~MPAM*C3mm3y4S)ZuWhvw|Y62Oit0`#JWGB=3Wk;-v z_x!FSgk_v9D4Kd5*ZnA>-e7&EWRlL!>oIbNNXLYbClQpDKw)kWIJ9lFS|J2Y)0crx z7?mtv`S8A9rhy)mwBL1<^9LVl+qjx_^|(lA?7Ex2Vj!V_&;n2@6WtNXg0ZEsyyrh? zil}NiQ`LaE#N#Sx`tiwVb89@c>;ArADQ*>Ys1 zNci{D-lJsD&T)#^RtMTS4%5-K4VCm@T&A?~#)J}D<`(pw@#F8$b8xqRqV>P^&4A_qO~(Sk4l)P6r%oM}!B;Q@Z{gp5C;==`y#wIg za{e8XzHN>Hv`-%^?xqnJ`cMAxe9Qzce@KwK~DG7uID~}@ZkHl1^!(hu&ffNXw3i_f|*U@-Oc_&sMZTUEXjWsW&j#5 zE!1AzHV3l}N`TAHnk&NP>zY0*Qh_G!Cb>o@4&UIsbnEpP?6Mf7%q39f`)e5Hk0u$I zr7C}=5DH+Eaivrt6w~^Rh*0gY+c4;?KwDwZS%Cp2G{_e&*Tpx%bKHXH$iv zW~tU=kE1sJn(waG4y&#!b$nRBeJU-m6oimirOa#ww$znV3CrTkMtas2b4?Se^N(!= zayHh~$2TYD+Bl@`WzXd)f)eHxhB#clljQ0&5kXwyaFQZ3oFAVDvbsx7GLazx_rxym zQ91qQ{I>7jZPSbpn7x_Nz8D6a9j0RinrIj_AR11qayA2h-vPoIVHQYTUq(FrjUVG! z^K{*t^Tj3Lods7;>|a*I{T$@|t99x+-yJS5?#)RXBk)ZoJL98f&= z$U1XS-9K&_SACM^dpM9_ATkf$Bn}oLI1bDTlnrZesdTPRpTnKr8Zz?8?}drTdHv}l zlq&~~c~hlBQ*!3kNt)NZ$xndGzQVv>C$Wfvu(g14)r~;kARgmn)Yt((YKzF@6%XNI z^9Do+47FtHaY5baX!Kf9*f3P*JOMuc(Q8oyUFJRF(@ zB54(L!l?7sLM|yPcUew}k#4NKjhNoHWaA>u4g5v|`wNiKoaE6;8o|}!K1&#F*2i{_ z@}21{6j*2o*Z`d4f@77PVWLY%ApAIqEpOK`#iz@XkQXG({Q;BJK<+^G6|ik2vH~49 zBsX6)IvN5fRFW)Q-a-H9TT!B9hx~b^QyEg)$cj8vxW13|WlhLFN^DPmbglOYNQ}bK zc6Obe7Iq0lxU@Ou*_PaQb$p89P3EJGe})Tgnw-4gFl-e|Vl~-yYE+h*wdBgca(
~5d`7WyKvT5q%F%{f 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 Z`Xh96p-;On@&^5slex;)g!FIc{{jj!9JBxc diff --git a/chestnut-ui/src/assets/images/wxpay.png b/chestnut-ui/src/assets/images/wxpay.png deleted file mode 100644 index bf6676055187700e243da3e72968b2531184073f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55098 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