浮层收口指南
这页只解决一类问题:后台项目里的弹窗、抽屉、气泡卡片、确认浮层和操作菜单,应该优先如何回到组件库公开入口,而不是继续在页面层或全局样式里改 .xy-* 根类和内部结构类名。
如果你还没看过总迁移策略,先读 后台迁移指南。如果你这轮主要在处理筛选条、日期面板和输入浮层,再配合 筛选面板收口指南 一起看。
先判断这是不是组件库层问题
下面这些现象,默认都先判断为“组件库公开 contract 没被正确使用”或“历史全局覆盖还没回收”,而不是先回业务页补更多样式:
dialog / drawer / tooltip / popconfirm / popover / dropdown在亮暗主题下像两套风格。- 页面或全局样式里还在大量命中
.xy-dialog、.xy-drawer、.xy-tooltip、.xy-popconfirm、.xy-popover、.xy-dropdown。 - 页面继续 deep 到
__panel / __header / __body / __footer / __content / __arrow这类内部类名,只是为了改背景、边框、阴影、圆角或 padding。 - 浮层触发器不显示,或者浮层本体根本没打开,但页面第一反应是继续补样式。
一句话判断:
- 如果你改的是“背景、边框、阴影、层次、圆角、padding、宽度、位置、主题接轨”,优先回到组件库实例级入口。
- 如果你改的是“业务流程、弹窗字段布局、详情区块排版、操作按钮顺序”,那才更可能属于业务页。
后台项目这轮联调的关键结论
这轮不是只看组件库文档页,而是对后台项目做了只读审计。当前和浮层直接相关的结论如下:
- 已验证为可保留的模式:
XyDialog通过width控制不同业务弹窗宽度XyDrawer通过size控制详情抽屉宽度Popconfirm通过#reference显式声明触发器body-class、header-class这类实例级 class 入口- 页面 wrapper 上接少量
--xy-*token
- 已确认仍值得继续收口的残留:
src/style/index.scss里中屏和移动端下的全局.xy-dialog { ... }- 同文件里小屏下的全局
.xy-table { display: block; overflow-x: auto; }
补一条非常具体的当前事实:
- 这次后台项目当前代码里,
panel-class、popper-class还没有成为主流落地方式。 - 这不代表这些入口没用,而是说明下一批迁移更适合先把“全局
.xy-dialog/.xy-table根类覆盖”迁走,再按需要引入实例级面板 class。
这里最重要的判断不是“后台项目写了样式就都该删”,而是要区分:
- 命中公开入口和 token 的,是组件库允许的实例级定制。
- 直接命中组件根类或内部结构类名的,才是下一批应继续回收的历史覆盖。
推荐收口入口
| 组件 | 优先入口 | 不建议继续 deep 的位置 |
|---|---|---|
dialog | width、panel-class、header-class、body-class、footer-class | .xy-dialog、__header / __body / __footer / __panel |
drawer | size、direction、原生 class(custom-class 已废弃)、header-class、body-class、footer-class | .xy-drawer、__header / __body / __footer / __panel |
tooltip | effect、popper-class、popper-style | .xy-tooltip、__content / __arrow |
popconfirm | #reference、content、popper-class、iconColor | .xy-popconfirm、__panel / __content / __actions |
popover | popper-class、popper-style、width | .xy-popover、__panel / __header / __body |
dropdown | trigger、popper-class、popper-style | .xy-dropdown、__panel / __item / __divider |
高优先级 contract 提醒
这条迁移线里,最容易被误判成“样式没生效”的,通常不是视觉变量,而是 trigger 和 slot contract 用错了。
Popconfirm 的旧触发写法兼容边界
- 当前组件已经兼容一类历史写法:
- 没有
reference插槽 - 且没有传
content - 此时默认插槽会被视为 trigger
- 没有
- 这用于兼容旧页面里直接把按钮写在默认插槽的场景,避免“删除 / 清空按钮直接消失”。
- 但如果页面同时把默认插槽当 trigger,又想把正文也塞进默认插槽,这仍然是歧义写法,应该显式拆成
#reference和正文内容。
推荐写法:
<xy-popconfirm title="确认删除">
<template #reference>
<xy-button text type="danger">删除</xy-button>
</template>
删除后将无法恢复
</xy-popconfirm>Dialog / Drawer 优先先看实例 contract,再看样式
如果页面里看到“弹窗已经开了,但尺寸、padding、内容区节奏不对”,判断顺序应该是:
- 先看
width/size/direction是否已经实例级声明。 - 再看
panel-class / body-class / header-class / footer-class是否已经挂上。 - 最后才决定是否还需要少量局部 token。
Drawer 再补一条实现边界:
- 当前
XyDrawer没有panel-class,它公开的是原生class,再配合header-class / body-class / footer-class。 custom-class已废弃,改用组件原生class即可。- 如果有人按
Dialog的心智去给Drawer传panel-class,这不是”样式没生效”,而是 contract 用错了。
不要直接从全局 .xy-dialog 或 .xy-drawer 开始修,这会把所有弹窗和抽屉一起绑死。
后台项目里可以保留的模式
这轮只读审计里,浮层链路已经能确认下面这些用法属于可接受的实例级 contract:
XyDialog直接通过width控制不同业务弹窗宽度XyDrawer直接通过size控制详情抽屉宽度XyPopconfirm通过#reference显式提供触发器XyCard等组件上的body-class、header-class
这些都不属于“旧 deep 补丁”,因为它们没有反向依赖组件内部 DOM 结构。
当前后台项目里真实已经采用的实例方式
这轮只读审计拿到的真实样本主要是下面这些:
system/user:- 列表删除按钮已经显式使用
Popconfirm -> #reference - 用户编辑弹窗直接用
XyDialog默认基线,没有再额外挂全局内部类名
- 列表删除按钮已经显式使用
system/role:- 角色编辑弹窗和权限配置弹窗分别使用
width="560px"、width="680px"
- 角色编辑弹窗和权限配置弹窗分别使用
business/order:- 订单详情使用
XyDrawer :size="600"
- 订单详情使用
layout/Header:- 顶部用户菜单使用
XyDropdown trigger="click"
- 顶部用户菜单使用
这组证据说明,后台项目已经在使用一部分健康的实例 contract,但“实例级 panel/popper 定制”还没有成为主路径,所以当前最优先的工作仍然是收走全局根类覆盖,而不是先在业务页大面积补 panel-class。
后台项目里下一批应继续收口的残留
这轮最值得继续清理的不是页面实例,而是全局根类覆盖:
- 全局
.xy-dialog:- 当前后台项目在中屏和移动端下统一改了
max-width、margin、border-radius、overflow-y - 这类规则会让所有弹窗共享同一套设备响应策略,优先级应该低于实例
width、panel-class和页面容器 class
- 当前后台项目在中屏和移动端下统一改了
- 全局
.xy-table:- 当前后台项目在小屏下直接改成
display: block和overflow-x: auto - 这类规则虽然不是浮层,但和同一批“全局根类直改组件表现”的历史模式属于同类问题,应继续迁到 wrapper 或更明确的业务壳类
- 当前后台项目在小屏下直接改成
把这两类覆盖再往下拆一层,当前更可落地的替代方式是:
.xy-dialog { max-width: 90vw; margin: 20px auto; }- 优先迁到具体业务弹窗实例的
width - 如果是某一类弹窗共享约束,再落到页面壳类或
panel-class
- 优先迁到具体业务弹窗实例的
.xy-dialog { border-radius: ...; max-height: 85vh; overflow-y: auto; }- 优先迁到页面壳类或
panel-class Drawer则对应迁到原生class
- 优先迁到页面壳类或
.xy-table { display: block; overflow-x: auto; }- 优先迁到
table-shell这类 wrapper,而不是继续直接命中组件根类
- 优先迁到
一句话总结:
- 公开入口和 token 是保留项。
- 全局根类和内部结构类名覆盖,是下一批继续收口项。
可直接替换的迁移示例
下面这两段不是抽象建议,而是针对后台项目当前残留的全局 .xy-dialog / .xy-table 覆盖,给出的可直接落地替代方式。
把全局 .xy-dialog 迁到实例 width + 页面壳类
如果旧代码是这种全局覆盖:
@media screen and (max-width: 1024px) and (min-width: 769px) {
.xy-dialog {
max-width: 90vw;
margin: 20px auto;
}
}
@media screen and (max-width: 768px) {
.xy-dialog {
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
max-height: 85vh;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
}优先迁成页面实例约束,而不是继续命中所有 dialog:
<template>
<xy-dialog
v-model="visible"
title="编辑用户"
width="560px"
panel-class="user-dialog-panel"
>
<!-- content -->
</xy-dialog>
</template>
<style scoped>
@media screen and (max-width: 1024px) and (min-width: 769px) {
:deep(.user-dialog-panel) {
max-width: 90vw;
margin: 20px auto;
}
}
@media screen and (max-width: 768px) {
:deep(.user-dialog-panel) {
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
max-height: 85vh;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
}
</style>迁移判断规则:
width负责业务弹窗默认宽度。panel-class只命中当前这一类 dialog,不再全局绑死所有弹窗。- 如果多个同类弹窗共享同一套移动端规则,也优先抽成页面壳类或业务级公共 class,不要重新回到
.xy-dialog根类。
把全局 .xy-table 横向滚动迁到 wrapper
如果旧代码是这种全局覆盖:
@media screen and (max-width: 480px) {
.xy-table {
display: block;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
}优先迁成表格 wrapper,而不是直接改组件根类:
<template>
<div class="table-shell table-shell--mobile-scroll">
<xy-table :data="rows" row-key="id">
<!-- columns -->
</xy-table>
</div>
</template>
<style scoped>
@media screen and (max-width: 480px) {
.table-shell--mobile-scroll {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.table-shell--mobile-scroll :deep(.xy-table) {
min-width: 640px;
}
}
</style>迁移判断规则:
- 横向滚动属于页面容器策略,优先挂在 wrapper。
xy-table本身只保留 table token、overview和列配置语义。- 如果只是想压缩移动端节奏,先用 wrapper token 或
overview,不要把display: block继续写到全局.xy-table。
推荐迁移顺序
- 先删
tooltip / popconfirm / popover / dropdown的内部类名覆盖。 - 再收
dialog / drawer的全局根类覆盖。 - 如果页面确实还需要局部浮层差异,再按需引入
panel-class / popper-class。 - 最后才处理仍然和页面布局强相关的局部样式。
不建议的顺序是:
- 先保留全局
.xy-dialog - 再叠一层
panel-class - 最后分不清到底哪一层在控制弹窗外观
常见替代
| 旧写法 | 推荐替代 |
|---|---|
.xy-dialog { max-width: ... } | 组件实例 width 或页面壳类约束 |
.xy-dialog__header / __body / __footer | header-class / body-class / footer-class |
.xy-drawer { ... } | 原生 class + 页面壳类约束 |
.xy-drawer__body { padding: ... } | body-class + 局部 token |
.xy-tooltip__content / .xy-popconfirm__panel | popper-class + 对应 token |
.xy-popover__panel / .xy-dropdown__panel | popper-class + 对应 token |
继续把 trigger 和正文都塞进 Popconfirm 默认插槽 | 显式拆成 #reference 和正文内容 |
联调时怎么判断算收口成功
满足下面几点,通常说明这批浮层已经基本回到组件库层:
- 亮暗主题切换后,
dialog / drawer / tooltip / popconfirm / popover / dropdown看起来属于同一套背景、边框和阴影体系。 - 页面不再依赖全局
.xy-dialog或内部__panel / __body / __header去修浮层视觉。 - 页面仍可保留少量实例级 class 或 wrapper token,但不再反向绑定组件内部结构。
- 触发器、标题、正文和操作区都优先按公开 contract 组织,而不是先靠样式兜底。