装修视角(Theme View)

在同一主题、同一页面下,按访客条件(设备、国家、UTM 等)决定展示哪些积木块。
组装修(按商品/专辑对象分装修)正交:组装修选「哪套 blocks」;视角在已选 blocks 内做「显隐」。
上级文档:theme-decoration-and-liquid-rendering.md


一、概念

概念说明
视角(Theme View)一条 o_theme_view 记录,含名称 + 受众条件 params
积木 display 绑定单个 block 的 params.display 存「在哪些视角下显示
当前视角前台运行时解析出的 view_id;决定每个 block 是否渲染

视角 不是 另一套完整装修数据,而是对现有 blocks 的 条件显隐

每主题最多 20 个视角(ThemeViewService::STORE_THEME_MAX_VIEWER)。


二、数据表 o_theme_view

Model:ThemeViewModel → 表 o_theme_view

字段说明
store_id / theme_id租户 + 主题
name视角名称(同 theme 下不可重名)
paramsJSON 字符串,受众条件(见 § 四)
position排序(列表 order by position desc

不单独存积木;积木仍在 o_theme_block,通过 params.display 关联视角 ID。


三、积木上的 display 字段

存在 o_theme_block.params / preview_params 内,与 section settings 同级。

display 值含义
未设置 / true(bool)所有视角都显示(无视角限制)
"3,5,7"(字符串,逗号分隔 view id)在视角 3、5、7 下显示;其他视角隐藏

3.1 运行时如何变成显隐

TagGetBlocks::view() 在拉完 blocks 后处理:

正常访客is_theme_edit != 1):

  1. currentViewId = URL view_idThemeViewService::getPatchViewId()
  2. 若 block 的 display 为非空字符串:
    • 当前视角 不在 display 列表 → 设 params.display = true隐藏
    • 当前视角 列表 → 设 params.display = false显示

装修模式is_theme_edit=1):

  • 同上,但当「当前视角在 display 列表」时,额外读该视角的 params.device,与 URL ?device= 比较;设备不匹配则仍 隐藏(便于编辑器内按 PC/移动预览)。

3.2 前台 Liquid 如何隐藏

templates/block_main.liquid

{% unless section.display %}
  <div id="block-section-{{block.id}}">...</div>
{% endunless %}

display=true → 不输出该 block DOM。

装修预览模式用 display:none 保留 DOM 便于编辑。


四、视角受众条件 params

创建/更新时 JSON 存入 o_theme_view.paramsThemeViewCreateRequest 要求必填)。

匹配逻辑复用 AbPlanService::checkParams()(与 AB 落地页受众相同)。

4.1 字段结构(解码后)

字段说明
device[]允许的设备类型,如 computerphone;当前设备须在列表内
country_type1 = 不限制国家;>1 且配置了 country 时校验 IP 国家
country[]{ country_code_2: "US" }
utm_type1 = 不限制;2 = 指定 utm_source;3 = 指定 utm_source/utm_medium
utm_value字符串或数组,小写匹配

校验顺序:设备 → 国家(若启用)→ UTM(若启用)。全部通过返回 true

4.2 当前视角 ID 如何确定

ThemeViewService::getPatchViewId()

1. ThemeViewCacheService::getList() 取当前 theme 全部视角(按 position desc)
2. 遍历,对每个 view.params 调 AbPlanService::checkParams()
3. 第一个通过的 view.id 即为 currentViewId
4. 无一通过 → 0

也可 URL 强制:?view_id=123(装修器切换视角预览)。

注意:遍历顺序由 DB position desc, id desc 决定;多个视角同时命中时 先匹配者优先


五、后台 API(themes-view

方法路径说明
GET/列表;params JSON 解码(ThemesViewListResponse
GET/:id详情
POST/新增视角
PUT/:id更新
DELETE/:id删除;可选 display 参数清理 block 绑定

Body 示例(POST/PUT):

{
  "theme_id": 1,
  "name": "美国移动端",
  "position": 10,
  "params": {
    "device": ["phone"],
    "country_type": 2,
    "country": [{ "country_code_2": "US" }],
    "utm_type": 1,
    "utm_value": ""
  }
}

5.1 删除视角

ThemeViewService::del($id, $displayParam=false)

  • 扫描该 theme 全部 o_theme_block
  • params.display / preview_params.display 等于 被删 view id(单 id 绑定写法):
    • 默认:移除 display 字段
    • display=true 查询参数:改为 display: true(恢复全员可见)
  • o_theme_view 行,清 ThemeViewCacheService 缓存

复制主题时 ThemeViewService::copy() 会复制 view 行,不会改 block 上 display 绑定(代码注释:暂不处理)。

复制/新增 block 时 themeBlockViewIdHandler() 会把非 bool 的 display 重置为 true(去掉视角绑定)。


六、缓存

Key内容TTL
CacheKeyHelper::themeView($themeId)该主题视角列表 JSON1 天;空列表占位 1 小时

增删改视角 → delCache()(expire 等待主从同步)。

删除默认主题的视角时,还会 expire themeData('default')themeSections('default') 等。


七、完整前台链路

sequenceDiagram
    participant U as 访客
    participant HPV as HomePublicVarsService
    participant GB as TagGetBlocks
    participant TD as ThemesService::themeData
    participant TV as ThemeViewService
    participant AB as AbPlanService
    participant BM as block_main.liquid

    U->>HPV: 请求商品页
    HPV->>HPV: theme_id, theme_preview
    U->>GB: get_blocks
    GB->>TD: themeData → o_theme_block
    GB->>TV: getPatchViewId 或 ?view_id=
    TV->>AB: checkParams 各视角 params
    AB-->>TV: 命中 view_id
    GB->>GB: view() 按 display 设显隐
    GB->>BM: blocks
    BM->>U: unless display 输出 HTML

八、后台 UI 对应(推断)

后台区域行为
主题装修 → 视角管理GET/POST/PUT/DELETE themes-view
积木块设置 → 显示条件 / 视角写入 block params.display = 选中的 view id(或多 id 逗号分隔,取决于前端实现)
装修预览工具栏 → 切换视角?view_id=&is_theme_edit=1&device=
装修预览工具栏 → 设备与视角 params.device 联动校验

九、与组装修的关系

维度组装修视角
划分依据业务对象(商品 ID…)访客条件(设备/国家/UTM)
数据不同 group_id 的多套 blocks同一套 blocks 上的 display
决策点ThemesService::themeData 选 groupTagGetBlocks::view 过滤
o_theme_route_group* + o_theme_block.group_ido_theme_view + block.params.display

两者可同时生效:先按 obj 选定 group 的 blocks,再按视角过滤显隐。


十、示例场景

10.1 仅美国移动端看到某 banner block

  1. 创建视角「US Mobile」:device=[phone], country_type=2, country=[US]
  2. 在该 block 的装修参数里设置 display: "12"(假设视角 id=12)
  3. 美国手机访客:getPatchViewId() → 12,block display 列表含 12 → 显示
  4. 其他国家或 PC:currentViewId 不是 12 或匹配不到 → 隐藏

10.2 所有访客都看(默认)

block 不设置 display,或 display: true


十一、关键代码索引

组件路径
视角 CRUDcommon/services/ThemeViewService.php
受众匹配common/services/AbPlanService.phpcheckParams()
缓存common/services/ThemeViewCacheService.php
前台过滤extend/liquidExtend/tags/TagGetBlocks.phpview()
display 重置common/services/ThemeBlockService.phpthemeBlockViewIdHandler()
APIapp/api/controller/ThemeView.php
模板显隐public/theme/default/templates/block_main.liquid

十二、排障

现象排查
block 所有人都不显示display 是否绑定了 view id 但无人命中视角;getPatchViewId 是否恒为 0
视角条件不生效AbPlanService 设备/国家/UTM;Context->sourceDevice
编辑器与线上一致是否带 is_theme_edit=1;device 参数是否与视角 params 一致
删视角后 block 仍隐藏删除 API 是否清理 display;或 display 存的是逗号多 id 而 del 只处理单 id 相等
复制主题后视角失效block display 未随 view id 映射(copy 未处理绑定)