lili f85ae6c434 feat(feed): U5 限曝光降权 + 精选池导出
限曝光(boost 的反向运营操作):
- Flyway V25.0.0 加 game_feed_rank.exposure_limit DECIMAL(10,4) NOT NULL DEFAULT 0(additive,
  镜像 contracts/db-schemas);FeedRankDO 加 exposureLimit 字段。
- 排序口径升级为 sort_score = quality + boost - exposure_limit,统一收敛在 deriveSortScore()——
  setFeatured/setExposureLimit/发布基线重发布/算分回灌四写入点共用,保证 boost/exposure_limit 两个
  运营维度在任意写入路径都被保留(限曝光穿越 telemetry 算分回灌存活,已单测验证)。
- 两层效果:① 普通降权(0<x<9999)持久化进 sort_score 使游戏下沉(cursor 分页仍正确);
  ② 硬限曝光哨兵(>=9999)在 buildStream 出流处剔除(复用既有二次过滤续取机制,不动 status、可随时改回)。
- 新端点 POST /admin-api/feed/exposure-limit(复用 feed:featured:update 权限 + @ApiAccessLog UPDATE 审计),
  门禁=仅已发布且已有排序行(不新建孤儿降权行);错误码段 1-103-005-***。

导出:GET /admin-api/feed/featured/export-excel(feed:featured:export + EXPORT 审计)经 ExcelUtils
导出精选/限曝光排序覆盖层运营字段;空数据写表头。feed-server 加 starter-excel 依赖。

测试:FeedServiceImplTest 25→35(限曝光门禁/降权扣减/硬限曝光出流剔除/普通降权不剔/回灌保留限曝光/导出列表空与非空)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 11:06:35 -07:00

101 lines
4.0 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.wanxiang</groupId>
<artifactId>game-module-feed</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>game-module-feed-server</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
feed 模块业务实现:controller(app/admin) / service / dal(DO·Mapper) / convert。
被 huijing-server 聚合启动(随单体一起加载,无需独立 bootstrap)。
</description>
<dependencies>
<!-- Spring Cloud 基础环境 -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-env</artifactId>
</dependency>
<!-- 本模块对外契约层 -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>game-module-feed-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 跨模块契约:project -api(GAP-3 分享回填 currentVersionId;§3.1/§3.2 可见态 enforce 读 project.status,仅依赖 -api 不依赖 -server) -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>game-module-project-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 跨模块契约:runtime -api(§3.1 C1 可见态第三条件:upsertRank(PUBLISH_BASELINE) 写侧 enforce 读 runtime_package.status,仅依赖 -api 不依赖 -server,守门④无环) -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>game-module-runtime-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 业务组件:数据权限 + 多租户(DO 继承 TenantBaseDO) -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-biz-data-permission</artifactId>
</dependency>
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-biz-tenant</artifactId>
</dependency>
<!-- Web + 安全:@RestController / @PreAuthorize / 当前登录用户 -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-security</artifactId>
</dependency>
<!-- DB:MyBatis Plus(BaseMapperX / LambdaQueryWrapperX / BaseDO) -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-mybatis</artifactId>
</dependency>
<!-- Excel 导出(U5 精选池/限曝光排序覆盖层导出 ExcelUtils + @ExcelProperty) -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-excel</artifactId>
</dependency>
<!-- 缓存(游戏流排序快照 Redis TTL 兜底,MVP 阶段先占位) -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-redis</artifactId>
</dependency>
<!-- RPC 远程调用(跨模块互调,预留消费 project/telemetry/compliance 的 -api) -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-rpc</artifactId>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>com.wanxiang</groupId>
<artifactId>huijing-spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
</build>
</project>