Skip to content

模块手册 · 社区域(community) ​

收录 4 个模块的权威开发手册(源自各模块 CLAUDE.md,随仓库同步)。

本文目录 ​

    1. feed
    1. follow
    1. favorite
    1. review

1. feed 模块 ​

源:src/app/feed/CLAUDE.md(随仓库同步)

src/app/feed/ ​

feed 模块 — V1 运动动态 9 action 迁移(V2 DDD 4 层 + InMemory + 行为兼容),L3-A 社交域。

模块职责 ​

feed 承接 C 端运动动态域(对齐 V1 server/src/modules/feed/),路由风格 = action 协议:

  • 入口:POST /api/v1/feed + body {action, payload}(V1 POST /api/feed 路径平移,协议 100% 兼容)
  • 9 action(routes.ts switch 权威 — 比 V1 CLAUDE.md 记载的 7 action 多 2): list / myFeeds / publish / like / unlike / comment / listComments / hotTopics / shoesForPicker
  • 鉴权:全部需已登录(Authorization: Bearer <access_token>)
  • 错误码区段:40420xxx(与 upload 40419xxx / follow 40421xxx 相邻隔离)
    • ⚠️ 2026-09-16 撞码治理时从 40413xxx 迁出(该段现属 group_buy)
  • HTTP 状态:400 / 401 / 404(V1 行为 100% 兼容)

DDD 4 层结构 ​

src/app/feed/
├── domain/                          # 零 web 依赖
│   ├── entities/feed.py             # Feed / FeedLike / FeedComment + CZ_FEED_NOTIFY_CONTENT_MAX(50)
│   └── exceptions.py                # FeedErrorCode (40420xxx) + cz_feed_error_to_http_status
│
├── application/
│   ├── ports/repositories.py        # FeedRepositoryPort + FeedUser/FeedShoe/FeedFollow 最小端口
│   ├── ports/services.py            # AccessTokenDecoderPort + NotificationPort
│   ├── usecase/feed_timeline.py     # list / myFeeds / listComments / hotTopics(4)
│   ├── usecase/feed_publish.py      # publish / shoesForPicker(2)
│   ├── usecase/feed_interactions.py # like / unlike / comment(3)
│   └── factories/create_feed_usecases.py
│
├── infrastructure/persistence/inmemory_feed_repositories.py  # 主仓储 + 4 适配器 + 种子
└── interface/{api/feed_actions.py, handlers.py}

对外接口(9 action 一览) ​

actionpayload返回(data)说明
list{page=1, pageSize=20(1..50), sort=latest|hot, topic?, userId?}{list, total, page, pageSize, hasMore}动态流;hot=likeCount desc;含作者 + shoe + liked
myFeeds{page, pageSize}同上我的动态(createdAt desc)
publish{content 1..500, images ≤9, checkinId?, distanceKm? 0..200, topic? ≤30, videoUrl?(url), shoeId?}{id}发布(shoeId 归属校验不属则忽略 + fan-out 粉丝通知)
like{feedId}{ok: true, liked: true}幂等点赞(事务计数 +1;notify type=like)
unlike{feedId}{ok: true, liked: false}幂等取消(不校验 feed 存在 — V1 口径)
comment{feedId, content 1..200}{id}评论(事务计数 +1;notify content 50 字截断 + '…')
listComments{feedId, page=1, pageSize=50}{list, total}评论列表(createdAt desc + user)
hotTopics—{topics: [{topic, count}]}groupBy topic(非空)count desc take 10
shoesForPicker—{shoes: [...]}active 跑鞋(createdAt desc — 发动态 picker)

关键行为约束(V1 对拍) ​

$transaction 计数原子(like/unlike/comment — 02 §6 铁律) ​

  • cz_like_feed / cz_unlike_feed / cz_add_comment:create|delete + 计数 ±1 收敛到同一 async 方法内(无 await 间隙 → asyncio 单线程原子 — V1 $transaction 回调等价)
  • 幂等:like 先 findUnique 检查(已赞不重复计数);unlike 未赞也返 ok;重复 PublishLike 由 @@unique([feedId, userId]) 语义兜底(仓储 upsert 式跳过)

fan-out(publish + V0.2.125) ​

publish 后给作者所有粉丝推 type=new_post 通知:粉丝列表查询失败 → 静默(外层); 单条 notify 失败 → 独立吞错(Promise.allSettled 等价 — 不影响其他粉丝与主返回)。

notify 集成(V1 notification.notify 对拍) ​

  • 自己触发自己跳过(user_id === actor_id → 不写通知 — 在端口实现内,V1 notify 首行)
  • 调用方 contextlib.suppress(Exception) 包裹(通知失败不阻塞点赞/评论/发布主链路)
  • V1 另有 realtime 推送(publishToUser)— V2 InMemory 阶段不模拟(与缓存同决策)

list 过滤组合(V1 where spread 语义) ​

where = {...topic?, ...userId?} — topic 空串/缺省不过滤(topic ? {topic} : {});sort=hot 按 likeCount desc 否则 createdAt desc;liked = viewer 对 feed 的点赞集合(批量查询等价 V1 include likes.where(userId))。

评论 notify 截断(50 字) ​

V1 content.length > 50 → slice(0, 50) + '…'(>50 才截 — 恰好 50 不截)。 ⚠️ V1 length 为 UTF-16 code units;V2 用 Python len(code points)— 中文/拉丁文一致, 增补平面 emoji 边缘差异已接受。

postman/videoUrl 校验 ​

V1 z.string().url()(JS new URL() try/catch — 绝对 URL)→ V2 pydantic field_validator (urlparse().scheme 非空判定 — 语义近似)。

跨模块最小端口(对应模块未接真实现 — 生产阶段替换) ​

端口InMemory 实现将来接入
FeedUserPort(作者 id/nickname/avatarUrl)InMemoryFeedUserAdapteruser 模块共库
FeedShoePort(归属校验 / picker / include 批量)InMemoryFeedShoeAdaptershoes 模块真实现(共读 shoes 表)
FeedFollowPort(粉丝 userIds — fan-out)InMemoryFeedFollowAdapterfollow 模块真实现(共读 follows 表)
NotificationPort(notify 集成)InMemoryFeedNotificationAdapter(记录 + skip-self)notification 模块迁移时接真实现

与 V1 行为差异(已接受) ​

项V1V2
时间序列化toISOString()(UTC 带 Z)naive 本地 isoformat(全局口径 — 显示层等价)
缓存list 无缓存;V1 部分读走 Cache.wrap不模拟(与 goal/shoes/training/mall 同决策)
realtime 推送notify 后 publishToUser(WS)不模拟(InMemory 阶段无 WS 通道)
listComments 入参校验route 层无 zod(TS 仅类型断言 — 垃圾入参未定义行为)pydantic 宽容归一(feedId 必传 + 默认 1/50 — 防御性增强)
截断口径(评论 notify)UTF-16 code unitsPython len(code points — emoji 边缘差异)
事务Prisma $transaction 回调InMemory 单方法原子(生产 Prisma 阶段经端口恢复真事务)

未迁移项(标注) ​

  • V1 feed 的 redis 缓存/热度排行(如有):本批未涉及(V1 侦察确认无)
  • 跨模块调用方(frontend hot/topic 页)只消费 HTTP 契约 — 无后端缺口

测试与质量 ​

文件范围
tests/integration/test_feed_actions.py9 action E2E(鉴权 / 契约 / publish→like→comment 链 / 404)
tests/unit/application/test_feed_usecases.py9 action 全分支(幂等 / fan-out / 截断 / hot 排序)
bash
PYTHONPATH=src python3 -m pytest tests/integration/test_feed_actions.py \
  tests/unit/application/test_feed_usecases.py -q

相关文件 ​

src/app/feed/                       ← 本文件所在模块
tests/integration/test_feed_actions.py
tests/unit/application/test_feed_usecases.py
src/main.py                         # 装配("── 13. L3-A 社交域"段)

变更记录 (Asia/Shanghai) ​

日期版本变更
2026-09-161.0.0首版 — V1 运动动态 9 action 迁移(DDD 4 层 + 40413xxx + 原子计数 + fan-out + 4 最小端口)

2. follow 模块 ​

源:src/app/follow/CLAUDE.md(随仓库同步)

src/app/follow/ ​

follow 模块 — V1 关注/粉丝 6 action 迁移(V2 DDD 4 层 + InMemory + 行为兼容),L3-A 社交域。

模块职责 ​

follow 承接 C 端关注关系域(对齐 V1 server/src/modules/follow/),路由风格 = action 协议:

  • 入口:POST /api/v1/follow + body {action, payload}(V1 POST /api/follow 路径平移,协议 100% 兼容)
  • 6 action:follow / unfollow / isFollowing / myFollowing / myFollowers / myCounts
  • 鉴权:全部需已登录(Authorization: Bearer <access_token>)
  • 错误码区段:40421xxx(与 feed 40420xxx 相邻隔离)
    • ⚠️ 2026-09-16 撞码治理时从 40414xxx 迁出(该段现属 distribution)
  • HTTP 状态:400 / 401 / 404(V1 行为 100% 兼容)

DDD 4 层结构 ​

src/app/follow/
├── domain/                          # 零 web 依赖
│   ├── entities/follow.py           # Follow(followerId / followeeId / createdAt)
│   └── exceptions.py                # FollowErrorCode (40421xxx) + cz_follow_error_to_http_status
│
├── application/
│   ├── ports/repositories.py        # FollowRepositoryPort + FollowUserPort
│   ├── ports/services.py            # AccessTokenDecoderPort + NotificationPort
│   ├── usecase/follow_relations.py  # follow / unfollow / isFollowing(3)
│   ├── usecase/follow_queries.py    # myFollowing / myFollowers / myCounts(3)
│   └── factories/create_follow_usecases.py
│
├── infrastructure/persistence/inmemory_follow_repositories.py  # 主仓储 + 2 适配器 + 种子
└── interface/{api/follow_actions.py, handlers.py}

对外接口(6 action 一览) ​

actionpayload返回(data)说明
follow{userId}{ok: true, following: true}upsert 幂等;'不能关注自己' 400 / '用户不存在' 404;notify type=follow
unfollow{userId}{ok: true, following: false}deleteMany 幂等(不存在也 ok)
isFollowing{userIds 1..50}{results: [{userId, following}]}批量(保 input 顺序)
myFollowing{page, pageSize}{list: [{userId, createdAt, user}], total, page, pageSize, hasMore}我关注的人(createdAt desc)
myFollowers{page, pageSize}同上我的粉丝(createdAt desc)
myCounts{userId}{user, followingCount, followerCount, isFollowing, isSelf}用户主页一次拿全(可查任意 userId)

关键行为约束(V1 对拍) ​

follow 校验链(顺序严格) ​

① 自己关注自己 → 400 不能关注自己(先于目标存在校验);② 目标不存在 → 404 用户不存在; ③ upsert(已存在则 update {} 不重复建 — @@unique([followerId, followeeId]) 语义)。

notify(fail-safe) ​

follow 成功后 notify 被关注者(type=follow — 无 targetType/targetId);通知失败静默 (contextlib.suppress — 不阻塞关注主链路);自己触发自己跳过在端口内(V1 notify 首行)。 ⚠️ 幂等重复 follow 依然调 notify(V1 无重查短路 — 逐字对齐)。

myCounts 视图逻辑(V1 三元表达式逐字) ​

viewerId && viewerId !== userId ? findUnique : null — viewerId 恒存在(已登录)→ viewer === user 时跳过查询(isFollowing 恒 false,isSelf true);user 不存在 → 404 用户不存在(Promise.all 后判空 — V1 顺序)。

分页 ​

myFollowing / myFollowers:createdAt desc + hasMore = page * pageSize < total; user include select {id, nickname, avatarUrl}。

跨模块最小端口(对应模块未接真实现 — 生产阶段替换) ​

端口InMemory 实现将来接入
FollowUserPort(目标校验 + user include)InMemoryFollowUserAdapteruser 模块共库
NotificationPort(notify 集成)InMemoryFollowNotificationAdapter(记录 + skip-self)notification 模块迁移时接真实现

与 V1 行为差异(已接受) ​

项V1V2
时间序列化toISOString()(UTC 带 Z)naive 本地 isoformat(全局口径)
realtime 推送notify 后 publishToUser(WS)不模拟(InMemory 阶段无 WS 通道)
事务Prisma upsert/deleteMany 原子InMemory 单方法(等价)

测试与质量 ​

文件范围
tests/integration/test_follow_actions.py6 action E2E(鉴权 / 幂等 / 400+401+404)
tests/unit/application/test_follow_usecases.py6 action 全分支(校验收敛 / 保序 / isSelf)
bash
PYTHONPATH=src python3 -m pytest tests/integration/test_follow_actions.py \
  tests/unit/application/test_follow_usecases.py -q

相关文件 ​

src/app/follow/                     ← 本文件所在模块
tests/integration/test_follow_actions.py
tests/unit/application/test_follow_usecases.py
src/main.py                         # 装配("── 13. L3-A 社交域"段)

变更记录 (Asia/Shanghai) ​

日期版本变更
2026-09-161.0.0首版 — V1 关注/粉丝 6 action 迁移(DDD 4 层 + 40414xxx + 最小端口 ×2)

3. favorite 模块 ​

源:src/app/favorite/CLAUDE.md(随仓库同步)

src/app/favorite/ ​

favorite 模块 — V1 收藏 4 action 迁移(V2 DDD 4 层 + InMemory + 行为兼容),L3-A 社交域。

模块职责 ​

favorite 承接 C 端 Content/Product 收藏域(对齐 V1 server/src/modules/favorite/), 路由风格 = action 协议:

  • 入口:POST /api/v1/favorite + body {action, payload}(V1 POST /api/favorite 路径平移,协议 100% 兼容)
  • 4 action:list / add / remove / isFavorited
  • 鉴权:全部需已登录(Authorization: Bearer <access_token>)
  • 错误码区段:40415xxx(与 follow 40421xxx / review 40416xxx 相邻隔离)
  • HTTP 状态:400 / 401(4 action 无业务抛出 — V1 口径)

DDD 4 层结构 ​

src/app/favorite/
├── domain/                          # 零 web 依赖
│   ├── entities/favorite.py         # Favorite + CZ_FAVORITE_TYPES(content | product)
│   ├── services/money.py            # cz_js_decimal_string(product price — 各模块自带一份)
│   └── exceptions.py                # FavoriteErrorCode (40415xxx) + cz_favorite_error_to_http_status
│
├── application/
│   ├── ports/repositories.py        # FavoriteRepositoryPort + FavoriteContent/FavoriteProduct 最小端口
│   ├── ports/services.py            # AccessTokenDecoderPort
│   ├── usecase/favorite_actions.py  # list / add / remove / isFavorited(4)
│   └── factories/create_favorite_usecases.py
│
├── infrastructure/persistence/inmemory_favorite_repositories.py  # 主仓储 + 2 适配器 + 种子
└── interface/{api/favorite_actions.py, handlers.py}

对外接口(4 action 一览) ​

actionpayload返回(data)说明
list{targetType?: content|product}{favorites: [{id, targetType, targetId, createdAt, detail}]}我的收藏(createdAt desc,无分页 — V1 口径);detail 为精确 select 或 null
add{targetType, targetId}{ok: true}upsert 幂等;不校验目标存在 — V1 口径
remove{targetType, targetId}{ok: true}deleteMany 幂等(不存在也 ok)
isFavorited{items 1..50: [{targetType, targetId}]}{results: [{targetType, targetId, favorited}]}批量红心(保 input 顺序)

关键行为约束(V1 对拍) ​

list 批量关联(避免 N+1) ​

先查 favorites → 拆 content/product ids → 批量查详情(Map 关联);id 列表为空时短路不查 (V1 length === 0 ? [] : findMany 逐字);目标已删除 → detail: null(前端据此隐藏)。

detail 精确键集(V1 select) ​

  • content:{id, title, cover, summary, type, location, date}(可空字段 null 直通)
  • product:{id, name, price, images, category, status} — price → decimal.js toString 字符串 (Decimal('199.00') → '199' 去尾随零 — cz_js_decimal_string)

add 不校验目标存在(V1 口径) ​

V1 upsert 直写不校验 content/product 存在 — 幽灵目标可收藏(list detail=null)。

isFavorited key 格式 ​

'type:id' 集合匹配(V1 ${targetType}:${targetId})— results 保 input 顺序。

跨模块最小端口(对应模块未接真实现 — 生产阶段替换) ​

端口InMemory 实现将来接入
FavoriteContentPort(内容详情 select)InMemoryFavoriteContentAdaptercontent 模块迁移时接真实现
FavoriteProductPort(商品详情 select)InMemoryFavoriteProductAdaptermall 模块真实现(共读 products 表)

与 V1 行为差异(已接受) ​

项V1V2
时间序列化toISOString()(UTC 带 Z)naive 本地 isoformat(全局口径)
可选键 nullJS undefined 键被丢弃输出 null(JS falsy 等价 — detail 显式 null 是 V1 行为)

测试与质量 ​

文件范围
tests/integration/test_favorite_actions.py4 action E2E(price 字符串契约 / detail null / 校验 400)
tests/unit/application/test_favorite_usecases.py4 action 全分支(幂等 / 幽灵目标 / 保序)
tests/unit/domain/test_favorite_money.pydecimal.js toString 纯函数
bash
PYTHONPATH=src python3 -m pytest tests/integration/test_favorite_actions.py \
  tests/unit/application/test_favorite_usecases.py tests/unit/domain/test_favorite_money.py -q

相关文件 ​

src/app/favorite/                   ← 本文件所在模块
tests/{integration/test_favorite_actions.py, unit/application/test_favorite_usecases.py, unit/domain/test_favorite_money.py}
src/main.py                         # 装配("── 13. L3-A 社交域"段)

变更记录 (Asia/Shanghai) ​

日期版本变更
2026-09-161.0.0首版 — V1 收藏 4 action 迁移(DDD 4 层 + 40415xxx + 最小端口 ×2 + Decimal price 口径)

4. review 模块 ​

源:src/app/review/CLAUDE.md(随仓库同步)

src/app/review/ ​

review 模块 — V1 C 端评价域 7 action 迁移(V2 DDD 4 层 + InMemory + 行为兼容),L3-A 社交域。

模块职责 ​

review 承接 C 端评价域(对齐 V1 server/src/modules/review/ — V0.1.113 电商评价闭环 + V0.1.137 鞋评),路由风格 = action 协议:

  • 入口:POST /api/v1/review + body {action, payload}(V1 POST /api/review 路径平移,协议 100% 兼容)
  • 7 action:create / list / listByTarget / stats / targetStats / myReviews / remove
  • 鉴权:全部需已登录(Authorization: Bearer <access_token>)
  • 错误码区段:40416xxx(避开 admin 侧 review 管理 40201500-599 — 后台审核链路独立)
  • HTTP 状态:400 / 401 / 403 / 404(V1 行为 100% 兼容)

DDD 4 层结构 ​

src/app/review/
├── domain/                          # 零 web 依赖
│   ├── entities/review.py           # Review + CZ_REVIEWABLE_ORDER_STATUS + CZ_SHOE_REVIEW_PREFIX
│   ├── services/review_calc.py      # syntheticId / tag 前缀 / 剥前缀 / cz_js_round1
│   └── exceptions.py                # ReviewErrorCode (40416xxx) + cz_review_error_to_http_status
│
├── application/
│   ├── ports/repositories.py        # ReviewRepositoryPort + ReviewOrder/Shoe/User/Product 最小端口
│   ├── ports/services.py            # AccessTokenDecoderPort
│   ├── usecase/review_create.py     # create(product 7 步链 / shoe 路径)
│   ├── usecase/review_queries.py    # list / listByTarget / stats / targetStats / myReviews(5)
│   ├── usecase/review_remove.py     # remove(1)
│   └── factories/create_review_usecases.py
│
├── infrastructure/persistence/inmemory_review_repositories.py  # 主仓储 + 4 适配器 + 种子
└── interface/{api/review_actions.py, handlers.py}

对外接口(7 action 一览) ​

actionpayload返回(data)说明
create{targetType=product|shoe, targetId, productId?, orderId?, rating 1..5, content? ≤500, images? ≤9}product: {id} / shoe: {id, reviewType: 'shoe'}商品(已购校验)/ 鞋评(归属校验)双路径
list{productId, page=1, pageSize=10}{list, total, page, pageSize}旧商品入口(不剥 [shoe-review] 前缀 — V1 口径)
listByTarget{targetType, targetId, page, pageSize}同上V0.1.137 通用(syntheticId 查询 + 剥前缀)
stats{productId}{avg, count, distribution{1..5}}商品评分汇总(= targetStats(productId))
targetStats{targetType, targetId}同上通用汇总(shoe → syntheticId)
myReviews{page, pageSize}{list, total, page, pageSize}我的评价(含 product select;无 user 键 — V1 口径)
remove{id}{ok: true}仅本人可删('评价不存在' 404 / '不是你的评价' 403)

关键行为约束(V1 对拍) ​

create — product 校验链(顺序严格不可调换) ​

① productId = input.productId ?? input.targetId 缺 → 400 productId required(防御 — zod 拦截在前); ② orderId 缺 → 400 orderId required;③ 订单不存在 → 404 订单不存在;④ 非本人 → 403 不是你的订单;⑤ status ∉ {paid, shipped, done} → 400 订单未支付,不可评价; ⑥ 商品不在订单 → 400 该商品不在此订单;⑦ 三元组防重 → 400 已评价过该商品。

create — shoe 路径(V0.1.137) ​

归属校验('跑鞋不存在或不属于你' 404)→ syntheticId shoe:{shoeId} 防重('已评价过该跑鞋' 400) → content 存 tag `[shoe-review] ${content ?? ''}`.trim()(V1 模板拼接语义 — content=None → '[shoe-review]'(去尾空格);content=' 缓震一流 ' → '[shoe-review] 缓震一流'(中间双空格保留))。

前缀剥除不对称(V1 生产行为 — 逐字复刻) ​

  • listByTarget:content.startsWith('[shoe-review] ') 才剥(含尾空格;裸 tag '[shoe-review]' 不满足 → 不剥)
  • list(旧 productId 入口)/ myReviews:不剥前缀(V1 实现差异)

评分汇总(JS Math.round 语义) ​

avg = agg._avg.rating ? Math.round(x * 10) / 10 : 0 — 空态 0;无评价 distribution 全 0 键 {1..5}。⚠️ 不可用 Python round(银行家舍入)→ cz_js_round1 = floor(v*10 + 0.5)/10 (4.25 → 4.3 — 单测锁定)。

输出键集(V1 include 差异) ​

  • list / listByTarget:{id, userId, productId, orderId, rating, content, images, createdAt, replyContent, repliedAt, user}(user=include select {id, nickname, avatarUrl};repliedAt 恒输出 null/ISO)
  • myReviews:同字段集但 无 user 键 + product: {id, name, images} | null(鞋评 → null)

跨模块最小端口(对应模块未接真实现 — 生产阶段替换) ​

端口InMemory 实现将来接入
ReviewOrderPort(订单存在/归属/状态/商品在单)InMemoryReviewOrderAdapterorder 模块共库
ReviewShoePort(跑鞋归属)InMemoryReviewShoeAdaptershoes 模块真实现
ReviewUserPort(评价列表 user include)InMemoryReviewUserAdapteruser 模块共库
ReviewProductPort(myReviews product include)InMemoryReviewProductAdaptermall 模块真实现

与 V1 行为差异(已接受) ​

项V1V2
时间序列化toISOString()(UTC 带 Z)naive 本地 isoformat(全局口径)
content 截断口径zod max(500) 按 UTF-16pydantic max_length 按 code points(emoji 边缘差异)
distribution 键类型JS 对象数字键(JSON 序列化为字符串键)Python int 键(JSON 序列化同为字符串键 — 等价)

未迁移项(标注) ​

  • admin 侧评价审核(P2-A src/app/admin/application/usecase/review_mgmt.py — 40201500-599) 与本模块独立;admin 审核的 [shoe-review] tag 识别由 admin 迁移批承载

测试与质量 ​

文件范围
tests/integration/test_review_actions.py7 action E2E(错误链 HTTP 状态 400/403/404 / 鞋评 tag / 统计契约)
tests/unit/application/test_review_usecases.py7 action 全分支(校验链逐项 / avg JS 语义 4.25→4.3 / 前缀不对称)
tests/unit/domain/test_review_calc.pysyntheticId / tag / 剥前缀 / round1 纯函数
bash
PYTHONPATH=src python3 -m pytest tests/integration/test_review_actions.py \
  tests/unit/application/test_review_usecases.py tests/unit/domain/test_review_calc.py -q

相关文件 ​

src/app/review/                     ← 本文件所在模块
tests/{integration/test_review_actions.py, unit/application/test_review_usecases.py, unit/domain/test_review_calc.py}
src/main.py                         # 装配("── 13. L3-A 社交域"段 — InMemoryReviewRepository 别名防 admin 同名遮蔽)

变更记录 (Asia/Shanghai) ​

日期版本变更
2026-09-161.0.0首版 — V1 C 端评价域 7 action 迁移(DDD 4 层 + 40416xxx + 鞋评 syntheticId/tag + 最小端口 ×4)