From 79226998d3ef13a10e312a235c57a90500e2e9d8 Mon Sep 17 00:00:00 2001 From: Golden Supreme Salted Fish <167095167+GoldenSupremeSaltedFish@users.noreply.github.com> Date: Fri, 4 Jul 2025 12:33:41 +0800 Subject: [PATCH] refactor: exclude post preview page from data tracking (#7582) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What type of PR is this? /kind bug /area core /milestone 2.21.x What this PR does / why we need it: Prevents published post view counts from being incorrectly increased when previewing posts in the admin panel. Previously, the preview mode would load the tracking script, which resulted in inflated view counts. This PR adds a condition to detect preview mode and disables the tracking logic to avoid counting views for unpublished content. Does this PR introduce user-facing changes? ```release-note 文章预览页面不再统计访问数据 ``` --- .../run/halo/app/theme/dialect/HaloTrackerProcessor.java | 9 +++++++++ .../run/halo/app/theme/router/PreviewRouterFunction.java | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/application/src/main/java/run/halo/app/theme/dialect/HaloTrackerProcessor.java b/application/src/main/java/run/halo/app/theme/dialect/HaloTrackerProcessor.java index beb7d624c..7e9e0be3c 100644 --- a/application/src/main/java/run/halo/app/theme/dialect/HaloTrackerProcessor.java +++ b/application/src/main/java/run/halo/app/theme/dialect/HaloTrackerProcessor.java @@ -1,5 +1,6 @@ package run.halo.app.theme.dialect; +import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import org.thymeleaf.context.ITemplateContext; @@ -21,6 +22,8 @@ import run.halo.app.infra.utils.PathUtils; @Component public class HaloTrackerProcessor implements TemplateHeadProcessor { + public static final String SKIP_TRACKER = HaloTrackerProcessor.class.getName() + ".SKIP_TRACKER"; + private final ExternalUrlSupplier externalUrlGetter; public HaloTrackerProcessor(ExternalUrlSupplier externalUrlGetter) { @@ -30,6 +33,12 @@ public class HaloTrackerProcessor implements TemplateHeadProcessor { @Override public Mono process(ITemplateContext context, IModel model, IElementModelStructureHandler structureHandler) { + // Check if tracker should be skipped + var isSkip = (Boolean) context.getVariable(SKIP_TRACKER); + if (BooleanUtils.isTrue(isSkip)) { + return Mono.empty(); + } + final IModelFactory modelFactory = context.getModelFactory(); return Mono.just(getTrackerScript(context)) .filter(StringUtils::isNotBlank) diff --git a/application/src/main/java/run/halo/app/theme/router/PreviewRouterFunction.java b/application/src/main/java/run/halo/app/theme/router/PreviewRouterFunction.java index eb87d912a..29d1e7deb 100644 --- a/application/src/main/java/run/halo/app/theme/router/PreviewRouterFunction.java +++ b/application/src/main/java/run/halo/app/theme/router/PreviewRouterFunction.java @@ -25,6 +25,7 @@ import run.halo.app.infra.AnonymousUserConst; import run.halo.app.infra.exception.NotFoundException; import run.halo.app.theme.DefaultTemplateEnum; import run.halo.app.theme.ViewNameResolver; +import run.halo.app.theme.dialect.HaloTrackerProcessor; import run.halo.app.theme.finders.PostPublicQueryService; import run.halo.app.theme.finders.SinglePageConversionService; import run.halo.app.theme.finders.vo.ContributorVo; @@ -81,6 +82,9 @@ public class PreviewRouterFunction { .flatMap(postVo -> { String template = postVo.getSpec().getTemplate(); Map model = ModelMapUtils.postModel(postVo); + // Mark as preview mode for downstream view processing + request.exchange().getAttributes() + .put(HaloTrackerProcessor.SKIP_TRACKER, Boolean.TRUE); return viewNameResolver.resolveViewNameOrDefault(request, template, DefaultTemplateEnum.POST.getValue()) .flatMap(templateName -> ServerResponse.ok().render(templateName, model)); @@ -148,6 +152,9 @@ public class PreviewRouterFunction { .switchIfEmpty(Mono.error(() -> new NotFoundException("Single page not found."))) .flatMap(singlePageVo -> { Map model = ModelMapUtils.singlePageModel(singlePageVo); + // Mark as preview mode for downstream view processing + request.exchange().getAttributes() + .put(HaloTrackerProcessor.SKIP_TRACKER, Boolean.TRUE); String template = singlePageVo.getSpec().getTemplate(); return viewNameResolver.resolveViewNameOrDefault(request, template, DefaultTemplateEnum.SINGLE_PAGE.getValue())