---
name: ai-shifu/chat-layout-width-detection
source: https://app.decimal.ai/s/ai-shifu-chat-layout-width-detection@1/SKILL.md
source_sha256: c6019b275db6
---

# 聊天布局宽度判定

## 核心规则

对于 `ai-shifu/src/cook-web/src/app/c/[[...id]]`，优先把聊天布局视为“视口问题”，而不只是“容器问题”。
若业务语义明确要求 `FRAME_LAYOUT_MOBILE` 只代表真实移动设备，而不是窄桌面窗口，则应把“是否返回 `FRAME_LAYOUT_MOBILE`”改为基于 user agent / 设备能力判断，同时保留 `FRAME_LAYOUT_PC`、`FRAME_LAYOUT_PAD`、`FRAME_LAYOUT_PAD_INTENSIVE` 的既有返回方式，避免影响现有消费方。

## 工作流

1. 从多个 DOM 来源计算布局宽度：`#root.clientWidth`、`document.documentElement.clientWidth`、`window.innerWidth`、`window.visualViewport?.width`。
2. 选择最小的正数宽度作为有效布局宽度，避免移动端 WebView 在“桌面网站模式”下被误判为桌面布局。
3. 将断点映射集中维护在 `uiConstants`，并在 store 与页面间复用。
4. 在 `resize`、`orientationchange`、`visualViewport.resize` 时重新计算布局。
5. 当布局切换到移动端时，关闭遗留的“桌面态已打开抽屉”状态。
6. 为 `calcFrameLayout` 增加或更新测试，覆盖 root 节点缺失与移动端 WebView 容器宽度异常偏大的场景。
7. 若仅调整移动端命中条件，优先把改动限制在 `calcFrameLayout` 内部，不要改调用方对 `FRAME_LAYOUT_*` 的比较逻辑。
8. `calcFrameLayout` 可能在 store 初始化阶段被服务端模块求值调用，读取 `document` 前必须做 SSR guard，服务端默认回退 `FRAME_LAYOUT_PC`，避免非聊天页面或错误兜底页因 `document is not defined` 先崩溃。

## 备注

- 不要仅依赖 `react-device-detect` 进行聊天布局切换。
- 注释保持英文，且避免在多个文件重复断点逻辑。