蓝湖 → Jetpack Compose(image_id 直连 + annotations 主路径 + skill 归一)
Skill 执行优先级(硬门禁)
当用户消息显式包含 $lanhu-compose-plan(或明确点名本 skill)时,必须执行以下规则:
- 本 skill 规则最高优先级:
- 禁止回退到通用 UI 转换文档作为主流程。
- 禁止输出 XML、Flutter、React Native、SwiftUI。
- 禁止输出“按视觉估算实现”这类脱离本 skill 数据链路的结论。
- 先协议、后改文件:
- 在完整输出“阶段 1 + 阶段 2(A/B/C/D)”之前,禁止修改项目代码文件。
- 未满足契约即失败:
- 未按约定输出 A) 审计区,视为未执行本 skill。
- 触发时必须输出:
FAIL_FAST: SKILL_CONTRACT_VIOLATION 并停止。
输入格式(从用户消息解析)
支持任意一种:
- 只给一行蓝湖 URL
- 或 key=value 多行:
LANHU_URL=...
HOST_ACTIVITY=...(可选)
HOST_FRAGMENT=...(可选)
PRESENTATION=auto|inline|fragment|dialog|bottom_sheet|popup|activity
输入硬要求
LANHU_URL 必须是设计图详情链接并包含 image_id(detailDetach?...&image_id=...)。
- 若缺少
LANHU_URL:仅提示补充后停止。
- 若缺少
image_id:FAIL_FAST: IMAGE_ID_MISSING_IN_URL。
必须使用的 MCP 工具(主路径)
必须调用(禁止无工具猜测):
lanhu_get_ai_analyze_design_result(url, image_ids)
lanhu_get_design_annotations(url, image_id)
lanhu_get_design_slices(url, image_id)
必要时(仅当链接为 PRD/原型文档且包含 docId):
lanhu_get_pages
lanhu_get_ai_analyze_page_result
lanhu_resolve_invite_link
若 lanhu MCP 不可用:提示用户先启动 lanhu-mcp 并确保 Codex 可见,然后停止。
URL 与工具路由(强制)
- 设计稿 URL(
/detailDetach 且含 image_id,不含 docId):
- 仅走 image_id 精确链路:
lanhu_get_ai_analyze_design_result(image_ids) -> lanhu_get_design_annotations(image_id) -> lanhu_get_design_slices(image_id)
- 禁止通过
design_name/design_names 选择画板。
- 禁止为“筛选画板”调用
lanhu_get_designs。
- PRD/原型 URL(含
docId,通常为 /product):
- 才允许调用:
lanhu_get_pages / lanhu_get_ai_analyze_page_result
- 邀请链接(
/link/#/invite?sid=...):
- 先调用
lanhu_resolve_invite_link,再按上面规则选择工具链。
数据源策略(强制)
主路径数据源(默认)
- 第一优先:
lanhu_get_design_annotations
- 第二优先:
lanhu_get_design_slices(..., image_id) 的 metadata(仅补充样式、资源、导出格式)
lanhu_get_ai_analyze_design_result(..., image_ids) 仅用于视觉核对与阶段 1 简述,不参与尺寸计算
几何与测量来源(主路径)
- 元素坐标与尺寸:
annotations.layers
- 自动测量优先使用:
annotations.measurements
text_container_paddings
icon_text_distances
nearest_neighbors
- 当 measurements 缺项时,才回退到图层几何关系推导间距
单位与圆角归一规则(主路径)
annotations.style.border_radius 是优先可消费圆角值:
- 单值圆角输出:
RoundedCornerShape(...)
- 分角圆角输出:
RoundedCornerShape(topStart=..., topEnd=..., bottomEnd=..., bottomStart=...)
- 仅当
annotations.style.border_radius 缺失时,才允许从图层样式补推
- 所有
*_raw 字段都视为原始源数据:
- 禁止直接输出到 Compose 代码
- 必须先由 skill 完成单位归一、结构归一,再写入
Modifier / Shape
annotations.unit = dp 时:
- 位置、宽高、边框、阴影、间距、圆角直接输出为 Compose
dp
- 字体与行高直接输出为 Compose
sp
- 禁止再次执行
411/750 缩放
- 文本规则:
font_size -> sp
line_height -> sp
letter_spacing 只能输出归一后的值
禁止项
- 禁止使用 OCR
- 禁止无来源猜测文本字号、间距、圆角或阴影
- 禁止在主路径中再次执行
px -> dp 缩放
- 禁止把
*_raw、px、未归一的 schema 原值直接塞进 Compose 代码
网页 schema 兜底链路(仅失败时启用)
仅当以下任一条件成立时触发兜底:
lanhu_get_design_annotations 调用失败
- annotations 缺关键字段(
unit/layers/measurements)
lanhu_get_design_slices 调用失败且无法获取关键资源信息
lanhu_get_ai_analyze_design_result 调用失败(仅影响阶段 1 语义描述时可降级为 EMPTY)
触发兜底后:
- 启用旧 schema 链路(优先复用当前 Lanhu MCP 运行环境中的
LANHU_COOKIE,再按 project/image + store_schema_revise 执行)
- 仅在此链路使用换算:
round(px * 411 / 750)
- 所有 schema 原值先落入
*_raw,再完成归一后才能输出到 Compose 代码
- A) 审计区必须标注:
source_mode=web_schema_fallback 与 fallback_reason
兜底 cookie 约束
- 第一优先:复用当前 Lanhu MCP 进程已有的
LANHU_COOKIE
- 若当前任务必须从文件读取 cookie,必须先检查当前 MCP 启动脚本或由用户显式提供路径,禁止写死历史路径
- 仅当环境变量缺失且已确认文件路径时,才允许读取该文件作为
Cookie 请求头
- 日志与输出中禁止回显 cookie 内容
硬门禁(强制)
- URL 缺少
image_id:
FAIL_FAST: IMAGE_ID_MISSING_IN_URL
- 主路径 annotations 缺关键结构且兜底失败:
FAIL_FAST: PRIMARY_AND_FALLBACK_BOTH_FAILED
- 进入兜底后未获取到可用 cookie(
LANHU_COOKIE 缺失,且未提供可读的 cookie 文件路径):
FAIL_FAST: COOKIE_SOURCE_UNAVAILABLE
- 进入兜底后预检失败或返回非成功 code:
FAIL_FAST: COOKIE_INVALID_OR_EXPIRED
- 进入兜底后 schema 拉取失败:
FAIL_FAST: SCHEMA_FETCH_FAILED
- 进入兜底后 schema 解析失败:
FAIL_FAST: SCHEMA_PARSE_FAILED
默认一律硬失败,禁止静默降级为估算模式。
Compose 硬约束(必须严格执行)
- 仅 Compose UI:
- 阶段 2 的代码产出只能是
@Composable 文件内容。
- 禁止输出 XML、ViewBinding、Flutter、RN。
- 布局组件优先级:
- 优先
Box / Column / Row / LazyColumn
- 仅在常规组合无法覆盖结构时才允许使用
ConstraintLayout
- 无必要禁止
Canvas
- 圆角输出规则:
- 统一圆角:
RoundedCornerShape(...)
- 分角圆角:
RoundedCornerShape(...)
- 禁止输出未归一的圆角数组或
*_raw
- 资源落盘规则:
- 所有栅格切图统一放到:
res/drawable-nodpi/
- 仅明显纯色基础几何形(无渐变/阴影/描边/纹理/多层叠加)才允许直接使用
Modifier.background(color, shape)
- 切图格式约束:
- 切图默认输出
webp(透明或质量异常可回退 png,并在规格表标注原因)
- 所有栅格切图(
webp/png)统一落盘到:res/drawable-nodpi/
- 资源命名规则:
- 使用语义化名称,例如:
ic_close、img_banner、bg_card(禁止 image_123)
- icon / 切图来源约束(强制):
- 除"明显纯色填充的基础几何形(无渐变/阴影/描边/纹理)"外,icon 不得手动用 Compose 绘制
- 常规 icon 必须直接使用
lanhu_get_design_slices(url, image_id) 返回的资源
- 当 slices 提供了某个区域的完整合成切图(如
bg、编组、layer-group 类型的切图,且面积覆盖该区域 >= 80%),必须优先使用切图 Image(painterResource(...)) 作为背景,禁止用 annotations 的纯色/渐变去模拟多层叠加效果
- 字体/颜色(可读性优先):
- 禁止为单个控件创建额外的 TextStyle 常量
- 字体属性完全相同在同一界面出现
>=2 次才允许抽成 val XxxTextStyle = TextStyle(...),否则一律 inline
- 颜色默认使用
private val 常量;同色 >=3 次或全局语义色才建议归并到 theme/token
Compose UI 适配优化(必须执行)
- 根布局适配:
- 整屏页面默认使用
Modifier.fillMaxSize()
- 主内容区默认使用
fillMaxWidth(),并结合 widthIn(max = ...) + wrapContentHeight() 控制设计稿基线宽度
- 当大屏宽度明显大于设计稿时,优先“内容限宽 + 居中”,禁止整体
scale
- 安全区与系统栏(沉浸式适配):
- 滚动与溢出:
- 只要垂直内容有超出风险,优先使用
LazyColumn 或 Column + verticalScroll
- 禁止把底部按钮写死到屏幕外;只有设计明确要求吸底操作区时,才允许固定到底部
- 大屏与横屏策略:
>=600dp 宽度默认视为大屏,优先使用“居中主栏 + 保留最大宽度”
- 横屏优先重排容器,不做整树缩放
- 文本与图片适配:
- 文本容器优先通过
weight、widthIn、defaultMinSize 控制伸缩
- 长文本必须给出
maxLines / overflow
- 图片必须显式声明
contentScale,比例敏感资源优先补 aspectRatio
- 绝对定位收敛:
- 仅重叠装饰、浮层锚点、精确覆盖场景允许
offset/absoluteOffset
- 主信息流禁止用绝对定位拼页面
- 图层透明度(强制):
- 必须读取
annotations.layers[].style.opacity
- 当
style.opacity 不为 null(即 < 1.0)时,必须在对应 Compose 组件上应用 .alpha(opacity) 或 Color.copy(alpha = opacity)
style.opacity 影响整个图层,如果是容器背景色,用 color.copy(alpha = style.opacity)
间距计算规则(强制)
- 必须使用 annotations 绝对坐标差值计算间距:
- 垂直间距 =
next_element.position.y - (current_element.position.y + current_element.size.height)
- 水平间距 =
next_element.position.x - (current_element.position.x + current_element.size.width)
- 禁止使用"大约"、"看起来像"等估算方式
- Header 内第一个元素:当使用
statusBarsPadding() + 动态 Header 高度方案时,第一个元素的间距直接用 annotations 坐标差值(不需要手动减去状态栏高度,因为 statusBarsPadding() 已处理)
- 优先使用
measurements.sibling_spacings(如果可用):
- 直接读取
gap_to_next 作为 Spacer(modifier = Modifier.height/width(gap.dp))
- 当
layout_direction = horizontal → 使用 Row
- 当
layout_direction = vertical → 使用 Column
- 当
layout_direction = stack → 使用 Box
- 禁止用通用系统适配方案替代设计稿间距:
- 禁止用
statusBarsPadding() 替代设计稿中状态栏区域的具体高度
- 禁止用
navigationBarsPadding() 替代设计稿中底部栏的具体高度
- 禁止用固定值(如
8.dp、16.dp)替代 annotations 中的精确间距
层级树消费规则(强制)
- 当
layout_tree 可用且有层级时,必须按树结构组织组件:
- 树的每个 group 节点对应一个容器 Composable
- 子节点按
children 数组顺序排列
- 禁止忽略树结构而自行猜测层级
- 当
layout_tree 不可用或扁平时,从 layer_path 和 parent_name 重建:
- 相同
parent_name 的图层是兄弟关系
layer_path 的 / 分隔表示嵌套深度
- 当以上均不可用时,从绝对坐标推断:
- 完全包含关系 → 父子(外层是容器)
- 同一水平线 → Row 兄弟
- 同一垂直线 → Column 兄弟
边框与阴影消费规则(强制)
- 边框:读取
style.borders_parsed[]
color → 边框颜色
width → 边框宽度(已转 dp)
alignment → inner / center / outer
- 输出:
Modifier.border(width.dp, Color(0xFF...), shape)
- 当
alignment = inner 时,边框在 padding 内侧
- 阴影:读取
style.shadows[]
- 当存在 shadow 数据时,必须应用
- 输出:
Modifier.shadow(elevation.dp, shape)
- 圆角:
border_radius 和 border_radius_detail_raw 已转为 dp
- 禁止对圆角值再次执行缩放
- 单值:
RoundedCornerShape(value.dp)
- 多值列表
[tl, tr, br, bl]:RoundedCornerShape(topStart=tl.dp, topEnd=tr.dp, bottomEnd=br.dp, bottomStart=bl.dp)
输出契约(严格)
- 阶段 1:只输出“选中画板 + 默认承载方式 + 预期产出文件清单”。
- 不输出 Compose 代码
- 不输出 slices 列表
- 不输出接入说明
- 阶段 2:只输出「A) 审计区 + B) 规格表 + C) Compose 文件内容 + D) 资源清单」。
- A 必须先于 B/C/D 输出,且字段完整
- 不输出接入指引、验收说明、状态总结
A) 审计区强制字段(缺一即失败)
必须包含以下字段,缺任意一项时立即:
FAIL_FAST: SKILL_CONTRACT_VIOLATION
tool_route=design_chain|prd_chain
mcp_calls
selection_key=image_id
selected_image_id
source_mode=mcp_annotations_primary|web_schema_fallback
unit=dp|px
conversion_applied=true|false
dimen_baseline=not_applicable|android_resources
text_source_priority
data_source=text/icon/spacing=annotations|dds_schema
fallback_reason(仅兜底时必填)
阶段 1(定位/选中/默认承载)
- 解析
LANHU_URL,提取 image_id
- 不调用
lanhu_get_designs 进行筛选;直接以该 image_id 作为唯一目标
- 调用
lanhu_get_ai_analyze_design_result(url, image_ids=[image_id]) 获取视觉核对信息(失败可记 EMPTY)
- 默认
PRESENTATION 规则:
bottom_sheet:含“底部弹窗/底部弹出/bottom sheet”
dialog:含“弹窗/对话框/提示/确认/dialog”
popup:含“气泡/悬浮/tooltip/pop”
activity:明确“独立整屏页面/导航入口/深链页”
- 否则
fragment
- 阶段 1 输出:
SELECTED: image_id=... name=... size_dp=...
PRESENTATION: <value>(一句理由)
FILES: <Screen>.kt, res/drawable-nodpi/...
阶段 2(审计 + 规格 + Compose + 资源)
前置:selected_image_id 已确定。
- 调用
lanhu_get_design_annotations(url, image_id) 获取结构化标注(主路径)
- 校验
unit 与关键字段(layers/measurements)
- 调用
lanhu_get_design_slices(url, image_id) 获取切图与资源信息
- 主路径生成规则:
- 几何值按已归一的 Compose
dp 输出
- 文本值按已归一的
sp 输出
- 间距优先使用 measurements,缺项时回退几何关系
- 圆角优先读取
annotations.style.border_radius
- 若步骤 1~3 任一失败或缺关键字段,触发
web_schema_fallback
- 输出 A) 审计区(必须完整)
- 输出 B) 规格表(<=3 层组件树)
- 输出 C) Compose 文件内容(仅
@Composable)
- 输出 D) 资源清单(仅列表)
B) 规格表字段(主路径)
component | composable | parent | strategy
position(x,y) | size(w,h) | normalized_value
font_size | line_height | letter_spacing
text_padding(measurements) | icon_text_distance | nearest_neighbor
width_strategy | height_strategy | safe_area | scroll_strategy | large_screen_strategy
border_radius_source | border_radius_output
asset_format(webp/png) | asset_output_dir(res/drawable-nodpi/) | asset
C) Compose 文件内容约束
- 只允许输出 Kotlin Compose 文件内容
- 优先使用
Stateless 风格的纯 UI 组合
- 需要根据页面风险显式体现
fillMaxWidth/widthIn、WindowInsets、滚动容器、键盘避让策略
- 资源引用使用:
painterResource(...)
- 禁止输出未归一的
*_raw、schema 原值、XML 属性名
D) 资源清单最少字段
asset_root=res/drawable-nodpi/
asset_format(webp/png) | asset_output_dir(res/drawable-nodpi/) | asset
兜底路径补充字段(仅 fallback)
scale_formula=411/750
conversion_rule=round(px * 411 / 750)
schema_version_id
schema_source_url
除 A/B/C/D 外不要输出任何内容。
1---2name: lanhu-compose-plan3description: 输入蓝湖设计图详情 URL(含 image_id),使用 lanhu MCP image_id 精确链路输出 Jetpack Compose 页面规划与代码草稿;annotations 为主路径,单位与圆角归一在 skill 内完成,schema 仅失败兜底,栅格资源统一落盘到 Android drawable-nodpi。4---56# 蓝湖 → Jetpack Compose(image_id 直连 + annotations 主路径 + skill 归一)78## Skill 执行优先级(硬门禁)910当用户消息显式包含 `$lanhu-compose-plan`(或明确点名本 skill)时,必须执行以下规则:11121. **本 skill 规则最高优先级**:13 - 禁止回退到通用 UI 转换文档作为主流程。14 - 禁止输出 XML、Flutter、React Native、SwiftUI。15 - 禁止输出“按视觉估算实现”这类脱离本 skill 数据链路的结论。162. **先协议、后改文件**:17 - 在完整输出“阶段 1 + 阶段 2(A/B/C/D)”之前,禁止修改项目代码文件。183. **未满足契约即失败**:19 - 未按约定输出 A) 审计区,视为未执行本 skill。20 - 触发时必须输出:`FAIL_FAST: SKILL_CONTRACT_VIOLATION` 并停止。2122## 输入格式(从用户消息解析)2324支持任意一种:2526- 只给一行蓝湖 URL27- 或 key=value 多行:28 - `LANHU_URL=...`29 - `HOST_ACTIVITY=...`(可选)30 - `HOST_FRAGMENT=...`(可选)31 - `PRESENTATION=auto|inline|fragment|dialog|bottom_sheet|popup|activity`3233### 输入硬要求3435- `LANHU_URL` 必须是设计图详情链接并包含 `image_id`(`detailDetach?...&image_id=...`)。36- 若缺少 `LANHU_URL`:仅提示补充后停止。37- 若缺少 `image_id`:`FAIL_FAST: IMAGE_ID_MISSING_IN_URL`。3839## 必须使用的 MCP 工具(主路径)4041必须调用(禁止无工具猜测):4243- `lanhu_get_ai_analyze_design_result(url, image_ids)`44- `lanhu_get_design_annotations(url, image_id)`45- `lanhu_get_design_slices(url, image_id)`4647必要时(仅当链接为 PRD/原型文档且包含 `docId`):4849- `lanhu_get_pages`50- `lanhu_get_ai_analyze_page_result`51- `lanhu_resolve_invite_link`5253若 lanhu MCP 不可用:提示用户先启动 lanhu-mcp 并确保 Codex 可见,然后停止。5455## URL 与工具路由(强制)56571. 设计稿 URL(`/detailDetach` 且含 `image_id`,不含 `docId`):58 - 仅走 image_id 精确链路:59 `lanhu_get_ai_analyze_design_result(image_ids)` -> `lanhu_get_design_annotations(image_id)` -> `lanhu_get_design_slices(image_id)`60 - 禁止通过 `design_name/design_names` 选择画板。61 - 禁止为“筛选画板”调用 `lanhu_get_designs`。622. PRD/原型 URL(含 `docId`,通常为 `/product`):63 - 才允许调用:`lanhu_get_pages` / `lanhu_get_ai_analyze_page_result`643. 邀请链接(`/link/#/invite?sid=...`):65 - 先调用 `lanhu_resolve_invite_link`,再按上面规则选择工具链。6667## 数据源策略(强制)6869### 主路径数据源(默认)7071- 第一优先:`lanhu_get_design_annotations`72- 第二优先:`lanhu_get_design_slices(..., image_id)` 的 metadata(仅补充样式、资源、导出格式)73- `lanhu_get_ai_analyze_design_result(..., image_ids)` 仅用于视觉核对与阶段 1 简述,不参与尺寸计算7475### 几何与测量来源(主路径)7677- 元素坐标与尺寸:`annotations.layers`78- 自动测量优先使用:`annotations.measurements`79 - `text_container_paddings`80 - `icon_text_distances`81 - `nearest_neighbors`82- 当 measurements 缺项时,才回退到图层几何关系推导间距8384### 单位与圆角归一规则(主路径)8586- `annotations.style.border_radius` 是优先可消费圆角值:87 - 单值圆角输出:`RoundedCornerShape(...)`88 - 分角圆角输出:`RoundedCornerShape(topStart=..., topEnd=..., bottomEnd=..., bottomStart=...)`89 - 仅当 `annotations.style.border_radius` 缺失时,才允许从图层样式补推90- 所有 `*_raw` 字段都视为原始源数据:91 - 禁止直接输出到 Compose 代码92 - 必须先由 skill 完成单位归一、结构归一,再写入 `Modifier` / `Shape`93- `annotations.unit = dp` 时:94 - 位置、宽高、边框、阴影、间距、圆角直接输出为 Compose `dp`95 - 字体与行高直接输出为 Compose `sp`96 - 禁止再次执行 `411/750` 缩放97- 文本规则:98 - `font_size` -> `sp`99 - `line_height` -> `sp`100 - `letter_spacing` 只能输出归一后的值101102### 禁止项103104- 禁止使用 OCR105- 禁止无来源猜测文本字号、间距、圆角或阴影106- 禁止在主路径中再次执行 `px -> dp` 缩放107- 禁止把 `*_raw`、`px`、未归一的 schema 原值直接塞进 Compose 代码108109## 网页 schema 兜底链路(仅失败时启用)110111仅当以下任一条件成立时触发兜底:112113- `lanhu_get_design_annotations` 调用失败114- annotations 缺关键字段(`unit/layers/measurements`)115- `lanhu_get_design_slices` 调用失败且无法获取关键资源信息116- `lanhu_get_ai_analyze_design_result` 调用失败(仅影响阶段 1 语义描述时可降级为 `EMPTY`)117118触发兜底后:119120- 启用旧 schema 链路(优先复用当前 Lanhu MCP 运行环境中的 `LANHU_COOKIE`,再按 `project/image` + `store_schema_revise` 执行)121- 仅在此链路使用换算:`round(px * 411 / 750)`122- 所有 schema 原值先落入 `*_raw`,再完成归一后才能输出到 Compose 代码123- A) 审计区必须标注:`source_mode=web_schema_fallback` 与 `fallback_reason`124125### 兜底 cookie 约束126127- 第一优先:复用当前 Lanhu MCP 进程已有的 `LANHU_COOKIE`128- 若当前任务必须从文件读取 cookie,必须先检查当前 MCP 启动脚本或由用户显式提供路径,禁止写死历史路径129- 仅当环境变量缺失且已确认文件路径时,才允许读取该文件作为 `Cookie` 请求头130- 日志与输出中禁止回显 cookie 内容131132## 硬门禁(强制)1331341. URL 缺少 `image_id`:135 - `FAIL_FAST: IMAGE_ID_MISSING_IN_URL`1362. 主路径 annotations 缺关键结构且兜底失败:137 - `FAIL_FAST: PRIMARY_AND_FALLBACK_BOTH_FAILED`1383. 进入兜底后未获取到可用 cookie(`LANHU_COOKIE` 缺失,且未提供可读的 cookie 文件路径):139 - `FAIL_FAST: COOKIE_SOURCE_UNAVAILABLE`1404. 进入兜底后预检失败或返回非成功 code:141 - `FAIL_FAST: COOKIE_INVALID_OR_EXPIRED`1425. 进入兜底后 schema 拉取失败:143 - `FAIL_FAST: SCHEMA_FETCH_FAILED`1446. 进入兜底后 schema 解析失败:145 - `FAIL_FAST: SCHEMA_PARSE_FAILED`146147默认一律硬失败,禁止静默降级为估算模式。148149## Compose 硬约束(必须严格执行)1501511. **仅 Compose UI**:152 - 阶段 2 的代码产出只能是 `@Composable` 文件内容。153 - 禁止输出 XML、ViewBinding、Flutter、RN。1542. **布局组件优先级**:155 - 优先 `Box` / `Column` / `Row` / `LazyColumn`156 - 仅在常规组合无法覆盖结构时才允许使用 `ConstraintLayout`157 - 无必要禁止 `Canvas`1583. **圆角输出规则**:159 - 统一圆角:`RoundedCornerShape(...)`160 - 分角圆角:`RoundedCornerShape(...)`161 - 禁止输出未归一的圆角数组或 `*_raw`1624. **资源落盘规则**:163 - 所有栅格切图统一放到:`res/drawable-nodpi/`164 - 仅明显纯色基础几何形(无渐变/阴影/描边/纹理/多层叠加)才允许直接使用 `Modifier.background(color, shape)`1655. **切图格式约束**:166 - 切图默认输出 `webp`(透明或质量异常可回退 `png`,并在规格表标注原因)167 - 所有栅格切图(`webp/png`)统一落盘到:`res/drawable-nodpi/`1686. **资源命名规则**:169 - 使用语义化名称,例如:`ic_close`、`img_banner`、`bg_card`(禁止 `image_123`)1707. **icon / 切图来源约束(强制)**:171 - 除"明显纯色填充的基础几何形(无渐变/阴影/描边/纹理)"外,icon 不得手动用 Compose 绘制172 - 常规 icon 必须直接使用 `lanhu_get_design_slices(url, image_id)` 返回的资源173 - 当 slices 提供了某个区域的完整合成切图(如 `bg`、`编组`、`layer-group` 类型的切图,且面积覆盖该区域 >= 80%),必须优先使用切图 `Image(painterResource(...))` 作为背景,禁止用 annotations 的纯色/渐变去模拟多层叠加效果1748. **字体/颜色(可读性优先)**:175 - 禁止为单个控件创建额外的 TextStyle 常量176 - 字体属性完全相同在同一界面出现 `>=2` 次才允许抽成 `val XxxTextStyle = TextStyle(...)`,否则一律 inline177 - 颜色默认使用 `private val` 常量;同色 `>=3` 次或全局语义色才建议归并到 theme/token178179## Compose UI 适配优化(必须执行)1801811. **根布局适配**:182 - 整屏页面默认使用 `Modifier.fillMaxSize()`183 - 主内容区默认使用 `fillMaxWidth()`,并结合 `widthIn(max = ...)` + `wrapContentHeight()` 控制设计稿基线宽度184 - 当大屏宽度明显大于设计稿时,优先“内容限宽 + 居中”,禁止整体 `scale`1852. **安全区与系统栏(沉浸式适配)**:186 - 设计稿坐标系从 y=0 开始,包含状态栏区域(通常 25dp)187 - 当页面顶部有背景容器(Header)覆盖状态栏区域时,必须使用动态高度适配:188 ```189 val statusBarHeight = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()190 Box(modifier = Modifier.height(设计稿高度.dp + statusBarHeight)) {191 // 背景图 fillMaxSize192 Column(modifier = Modifier.fillMaxSize().statusBarsPadding()) {193 // 内容间距直接用坐标差值,不需要手动减去状态栏高度194 }195 }196 ```197 - 这样 Preview(statusBarHeight=0)和真机(statusBarHeight≈25dp)都能正确显示198 - 禁止用固定值(如 25dp)硬编码状态栏高度199 - 输入页、登录页、搜索页等受键盘影响场景必须考虑 `imePadding()`2003. **滚动与溢出**:201 - 只要垂直内容有超出风险,优先使用 `LazyColumn` 或 `Column + verticalScroll`202 - 禁止把底部按钮写死到屏幕外;只有设计明确要求吸底操作区时,才允许固定到底部2034. **大屏与横屏策略**:204 - `>=600dp` 宽度默认视为大屏,优先使用“居中主栏 + 保留最大宽度”205 - 横屏优先重排容器,不做整树缩放2065. **文本与图片适配**:207 - 文本容器优先通过 `weight`、`widthIn`、`defaultMinSize` 控制伸缩208 - 长文本必须给出 `maxLines` / `overflow`209 - 图片必须显式声明 `contentScale`,比例敏感资源优先补 `aspectRatio`2106. **绝对定位收敛**:211 - 仅重叠装饰、浮层锚点、精确覆盖场景允许 `offset/absoluteOffset`212 - 主信息流禁止用绝对定位拼页面2137. **图层透明度(强制)**:214 - 必须读取 `annotations.layers[].style.opacity`215 - 当 `style.opacity` 不为 null(即 < 1.0)时,必须在对应 Compose 组件上应用 `.alpha(opacity)` 或 `Color.copy(alpha = opacity)`216 - `style.opacity` 影响整个图层,如果是容器背景色,用 `color.copy(alpha = style.opacity)`217218## 间距计算规则(强制)2192201. **必须使用 annotations 绝对坐标差值计算间距**:221 - 垂直间距 = `next_element.position.y - (current_element.position.y + current_element.size.height)`222 - 水平间距 = `next_element.position.x - (current_element.position.x + current_element.size.width)`223 - 禁止使用"大约"、"看起来像"等估算方式224 - **Header 内第一个元素**:当使用 `statusBarsPadding()` + 动态 Header 高度方案时,第一个元素的间距直接用 annotations 坐标差值(不需要手动减去状态栏高度,因为 `statusBarsPadding()` 已处理)2252. **优先使用 `measurements.sibling_spacings`**(如果可用):226 - 直接读取 `gap_to_next` 作为 `Spacer(modifier = Modifier.height/width(gap.dp))`227 - 当 `layout_direction = horizontal` → 使用 `Row`228 - 当 `layout_direction = vertical` → 使用 `Column`229 - 当 `layout_direction = stack` → 使用 `Box`2303. **禁止用通用系统适配方案替代设计稿间距**:231 - 禁止用 `statusBarsPadding()` 替代设计稿中状态栏区域的具体高度232 - 禁止用 `navigationBarsPadding()` 替代设计稿中底部栏的具体高度233 - 禁止用固定值(如 `8.dp`、`16.dp`)替代 annotations 中的精确间距234235## 层级树消费规则(强制)2362371. **当 `layout_tree` 可用且有层级时,必须按树结构组织组件**:238 - 树的每个 group 节点对应一个容器 Composable239 - 子节点按 `children` 数组顺序排列240 - 禁止忽略树结构而自行猜测层级2412. **当 `layout_tree` 不可用或扁平时**,从 `layer_path` 和 `parent_name` 重建:242 - 相同 `parent_name` 的图层是兄弟关系243 - `layer_path` 的 `/` 分隔表示嵌套深度2443. **当以上均不可用时**,从绝对坐标推断:245 - 完全包含关系 → 父子(外层是容器)246 - 同一水平线 → Row 兄弟247 - 同一垂直线 → Column 兄弟248249## 边框与阴影消费规则(强制)2502511. **边框**:读取 `style.borders_parsed[]`252 - `color` → 边框颜色253 - `width` → 边框宽度(已转 dp)254 - `alignment` → `inner` / `center` / `outer`255 - 输出:`Modifier.border(width.dp, Color(0xFF...), shape)`256 - 当 `alignment = inner` 时,边框在 padding 内侧2572. **阴影**:读取 `style.shadows[]`258 - 当存在 shadow 数据时,必须应用259 - 输出:`Modifier.shadow(elevation.dp, shape)`2603. **圆角**:`border_radius` 和 `border_radius_detail_raw` 已转为 dp261 - 禁止对圆角值再次执行缩放262 - 单值:`RoundedCornerShape(value.dp)`263 - 多值列表 `[tl, tr, br, bl]`:`RoundedCornerShape(topStart=tl.dp, topEnd=tr.dp, bottomEnd=br.dp, bottomStart=bl.dp)`264265## 输出契约(严格)266267- **阶段 1**:只输出“选中画板 + 默认承载方式 + 预期产出文件清单”。268 - 不输出 Compose 代码269 - 不输出 slices 列表270 - 不输出接入说明271- **阶段 2**:只输出「A) 审计区 + B) 规格表 + C) Compose 文件内容 + D) 资源清单」。272 - A 必须先于 B/C/D 输出,且字段完整273 - 不输出接入指引、验收说明、状态总结274275### A) 审计区强制字段(缺一即失败)276277必须包含以下字段,缺任意一项时立即:278`FAIL_FAST: SKILL_CONTRACT_VIOLATION`279280- `tool_route=design_chain|prd_chain`281- `mcp_calls`282- `selection_key=image_id`283- `selected_image_id`284- `source_mode=mcp_annotations_primary|web_schema_fallback`285- `unit=dp|px`286- `conversion_applied=true|false`287- `dimen_baseline=not_applicable|android_resources`288- `text_source_priority`289- `data_source=text/icon/spacing=annotations|dds_schema`290- `fallback_reason`(仅兜底时必填)291292## 阶段 1(定位/选中/默认承载)2932941. 解析 `LANHU_URL`,提取 `image_id`2952. 不调用 `lanhu_get_designs` 进行筛选;直接以该 `image_id` 作为唯一目标2963. 调用 `lanhu_get_ai_analyze_design_result(url, image_ids=[image_id])` 获取视觉核对信息(失败可记 `EMPTY`)2974. 默认 `PRESENTATION` 规则:298 - `bottom_sheet`:含“底部弹窗/底部弹出/bottom sheet”299 - `dialog`:含“弹窗/对话框/提示/确认/dialog”300 - `popup`:含“气泡/悬浮/tooltip/pop”301 - `activity`:明确“独立整屏页面/导航入口/深链页”302 - 否则 `fragment`3035. 阶段 1 输出:304 - `SELECTED: image_id=... name=... size_dp=...`305 - `PRESENTATION: <value>(一句理由)`306 - `FILES: <Screen>.kt, res/drawable-nodpi/...`307308## 阶段 2(审计 + 规格 + Compose + 资源)309310前置:`selected_image_id` 已确定。3113121. 调用 `lanhu_get_design_annotations(url, image_id)` 获取结构化标注(主路径)3132. 校验 `unit` 与关键字段(`layers/measurements`)3143. 调用 `lanhu_get_design_slices(url, image_id)` 获取切图与资源信息3154. 主路径生成规则:316 - 几何值按已归一的 Compose `dp` 输出317 - 文本值按已归一的 `sp` 输出318 - 间距优先使用 measurements,缺项时回退几何关系319 - 圆角优先读取 `annotations.style.border_radius`3205. 若步骤 1~3 任一失败或缺关键字段,触发 `web_schema_fallback`3216. 输出 A) 审计区(必须完整)3227. 输出 B) 规格表(<=3 层组件树)3238. 输出 C) Compose 文件内容(仅 `@Composable`)3249. 输出 D) 资源清单(仅列表)325326### B) 规格表字段(主路径)327328- `component | composable | parent | strategy`329- `position(x,y) | size(w,h) | normalized_value`330- `font_size | line_height | letter_spacing`331- `text_padding(measurements) | icon_text_distance | nearest_neighbor`332- `width_strategy | height_strategy | safe_area | scroll_strategy | large_screen_strategy`333- `border_radius_source | border_radius_output`334- `asset_format(webp/png) | asset_output_dir(res/drawable-nodpi/) | asset`335336### C) Compose 文件内容约束337338- 只允许输出 Kotlin Compose 文件内容339- 优先使用 `Stateless` 风格的纯 UI 组合340- 需要根据页面风险显式体现 `fillMaxWidth/widthIn`、`WindowInsets`、滚动容器、键盘避让策略341- 资源引用使用:`painterResource(...)`342- 禁止输出未归一的 `*_raw`、schema 原值、XML 属性名343344### D) 资源清单最少字段345346- `asset_root=res/drawable-nodpi/`347- `asset_format(webp/png) | asset_output_dir(res/drawable-nodpi/) | asset`348349### 兜底路径补充字段(仅 fallback)350351- `scale_formula=411/750`352- `conversion_rule=round(px * 411 / 750)`353- `schema_version_id`354- `schema_source_url`355356除 A/B/C/D 外不要输出任何内容。