后台迁移指南
这页只放执行清单。目标很直接:把后台项目里分散在页面层的浮层、通知和表格样式,尽量收回到组件实例 token 和组件库默认基线。
如果你这轮主要在收弹窗、抽屉、提示和操作菜单,建议先配合 浮层收口指南 一起看。如果你这轮主要在收筛选条和输入浮层,再看 筛选面板收口指南。后两页会把实例级入口、可保留模式和应继续回收的历史覆盖分别串起来。
当前已经吸收进组件库的范围
这条迁移线不是抽象建议,下面这些组件的默认视觉基线已经做过组件库层收口,业务项目应该优先尝试删除旧的页面级覆盖:
- 浮层与覆盖层:
dialog / drawer / tooltip / popconfirm / popover / dropdown / menu - 表格:
table的 header / border / hover / stripe / fixed shadow 已 token 化,且已补overview - 反馈与通知:
alert / message / notification / result / statistic - 基础交互:
button / badge / input / select / link / checkbox / radio / switch / slider / input-number / rate - 基础展示与布局:
card / pagination / tag / avatar / image / skeleton / breadcrumb / divider / backtop / tabs / splitter / upload / descriptions - 筛选区高频组件:
auto-complete / cascader / tree-select / date-picker / time-picker / time-select
如果业务项目里这些组件仍然大量依赖 :deep(.xy-*) 改背景、边框、阴影、padding、hover 或 selected 态,默认先判断为“历史覆盖未回收”,而不是继续在页面层补更多样式。
本轮联调结论
这轮不是只看组件库自己的文档页,而是把本地组件库构建产物接到后台项目里做了真实页面联调。当前结论如下:
popconfirm的旧触发 contract 兼容已经在业务页真实生效:- 用户管理、角色管理、文件管理这些列表页里的“删除”按钮都能真实显示。
- 点击后会弹出真实可见的确认浮层,而不是只剩 DOM 或占位节点。
table的主题 token 收口已经在暗色主题下真实生效:- 表格正文、表头和 hover 区不再回退成整片白底。
- 表格背景、表头背景、边框和 fixed surface 会优先跟随 table token。
dialog / drawer / tooltip / popconfirm的背景、边框、阴影主基线已经来自组件库:- 如果联调里看到底色和阴影已经对了,但 header/body/footer padding 还是旧节奏,优先判断为“业务项目历史覆盖仍在”,不要直接回退成“组件库默认态没生效”。
一句话总结:这轮之后,最常见的问题不再是“组件库没能力”,而是“业务页还留着上一轮 deep 补丁没删”。
后台项目里已经验证过的保留项
这次只读联调里,也确认了几类“看起来像覆盖、但实际上是合理迁移结果”的模式。它们不应该和旧的内部类名补丁一起被误删:
table-shell这类页面 wrapper token:- 例如后台项目全局
src/style/index.scss里的.table-shell { --xy-table-* } - 这类属于推荐模式,因为它是在页面壳层接 table token,而不是 deep 到 cell / row / header 内部结构。
- 例如后台项目全局
- 页面局部的 table token 微调:
- 例如
system/user、system/role页里的--xy-table-body-cell-padding-* - 这类属于“页面密度接轨”,不是旧式内部类补丁。
- 例如
body-class搭配自定义类名的局部样式:- 例如
body-class="table-card__body",再在 scoped 样式里写:deep(.table-card__body) - 这类命中的是业务自定义 class,不是组件内部私有类名,属于可接受的 contract 用法。
- 例如
App.vue里针对 Vditor 富文本表格的注入修复:- 这类修的是第三方内容把表格条纹重新刷白的问题
- 它不是组件库默认态缺失,当前应视为保留项,而不是迁移脏补丁
一句话判断:
- 命中
--xy-*token、body-class / panel-class / popper-class这类公开入口的,默认先归为“保留项”。 - 直接命中
.xy-xxx__cell / __option / __panel / __header / __body这类内部结构类名的,默认再归为“继续收口项”。
后台项目里下一批应优先继续收口的残留
这次联调里真正还值得继续清理的,是“全局根类直改组件外观”的旧模式,而不是页面 wrapper token。浮层类的细化判断和替代入口,已经另外整理到 浮层收口指南:
- 全局
.xy-dialog覆盖:- 后台项目
src/style/index.scss里仍有移动端和中屏设备下的.xy-dialog { ... } - 这类会把所有弹窗一起绑死在同一套 max-width、radius、overflow 规则上,优先级应该低于实例
width、panel-class、body-class。
- 后台项目
- 全局
.xy-table根类覆盖:- 例如移动端下直接写
.xy-table { display: block; overflow-x: auto; ... } - 这类不是 cell 级 deep 覆盖,但仍然属于“全局改组件根节点表现”,后续应优先评估是否能迁到 wrapper 或更明确的页面容器 class。
- 例如移动端下直接写
这两类模式当前还不能简单算作“已经迁到组件库层”,它们更像是下一批应该继续压缩的全局历史覆盖。
下一批可直接按文件推进的任务簇
这条迁移线已经不适合再用“全局搜到什么就改什么”的方式推进。按当前后台项目真实页面分型,更适合拆成下面几批:
批次 A:标准表单型 Dialog
这批页面的共同点是:
- 都在用
XyDialog - 主要承载表单录入、编辑、发布、上传、配置
- 优先入口是实例
width,必要时再补panel-class / body-class / footer-class
当前可直接归到这批的页面有:
src/views/system/user/index.vuesrc/views/system/role/index.vuesrc/views/system/announcement/index.vuesrc/views/system/task/index.vuesrc/views/system/file/index.vuesrc/views/content/article/index.vuesrc/views/content/category/index.vuesrc/views/business/product/index.vuesrc/views/system/menu/index.vue
这批的迁移目标很明确:
- 先保留每个页面已经声明的
width - 把全局
.xy-dialog的响应式规则迁到页面实例panel-class - 不要再继续把移动端 radius、max-height、overflow 写在全局
.xy-dialog
继续往下拆,当前这批 Dialog 已经能按宽度和用途再分成几类公共壳层:
| 壳层类型 | 建议 panel-class | 典型宽度 | 适用页面 |
|---|---|---|---|
| 窄表单型 | dialog-shell--narrow | 默认宽度或 500px 左右 | system/task、system/file、content/category、system/menu、system/user |
| 标准表单型 | dialog-shell--form | 560px - 600px | system/role、system/announcement、business/product |
| 中宽配置型 | dialog-shell--config | 680px 左右 | system/role 的权限配置 |
| 宽内容型 | dialog-shell--wide | 800px 左右 | content/article |
当前可直接参考的页面归类:
dialog-shell--narrowsrc/views/system/task/index.vuesrc/views/system/file/index.vuesrc/views/content/category/index.vuesrc/views/system/menu/index.vuesrc/views/system/user/index.vue
dialog-shell--formsrc/views/system/role/index.vuesrc/views/system/announcement/index.vuesrc/views/business/product/index.vue
dialog-shell--configsrc/views/system/role/index.vue的权限配置弹窗
dialog-shell--widesrc/views/content/article/index.vue
这层分型的意义不是先把 class 写死到组件库里,而是给后续业务项目迁移一个稳定命名面:
- 同一类
Dialog先共用一套panel-class名称 - 再把中屏/移动端的 radius、max-height、overflow 规则收敛到这些壳层
- 避免每个页面单独发明一套
user-dialog-panel / role-dialog-panel / file-dialog-panel
建议的执行顺序:
- 先拿
dialog-shell--narrow做第一批验证,因为页面最多、风险最低。 - 再收
dialog-shell--form。 dialog-shell--config和dialog-shell--wide单独验收,不和表单弹窗混改。
建议的壳层样式骨架可以先统一成下面这套,再按页面细节微调:
.dialog-shell--narrow,
.dialog-shell--form,
.dialog-shell--config,
.dialog-shell--wide {
--xy-dialog-header-padding-y: 10px;
--xy-dialog-header-padding-x: 16px;
--xy-dialog-body-padding-y: 10px;
--xy-dialog-body-padding-x: 16px;
--xy-dialog-footer-padding-y: 10px;
--xy-dialog-footer-padding-x: 16px;
}
.dialog-shell--narrow {
max-width: min(520px, calc(100vw - 32px));
}
.dialog-shell--form {
max-width: min(600px, calc(100vw - 32px));
}
.dialog-shell--config {
max-width: min(680px, calc(100vw - 32px));
}
.dialog-shell--wide {
max-width: min(800px, calc(100vw - 32px));
}
@media screen and (max-width: 1024px) and (min-width: 769px) {
.dialog-shell--narrow,
.dialog-shell--form,
.dialog-shell--config,
.dialog-shell--wide {
max-width: 90vw;
margin: 20px auto;
}
}
@media screen and (max-width: 768px) {
.dialog-shell--narrow,
.dialog-shell--form,
.dialog-shell--config,
.dialog-shell--wide {
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
max-height: 85vh;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
}如果页面只是想统一节奏,优先先改这些公开变量,不要继续 deep 到内部结构:
--xy-dialog-header-padding-y/x--xy-dialog-body-padding-y/x--xy-dialog-footer-padding-y/x--xy-dialog-bg--xy-dialog-title-color
只有当某一页确实需要特殊布局时,才在这些公共壳层之上再叠业务局部 class。
批次 B:详情型 Drawer
这批当前样本很少,但边界最清楚:
src/views/business/order/index.vue
当前页面已经使用 XyDrawer :size="600"。这类页面默认先保留 size,只有确实需要响应式壳层时,再引入原生 class(custom-class 已废弃),不要误用 panel-class。
这批的迁移目标:
- 保留
size作为主尺寸语义 - 如果移动端需要特殊圆角、高度或滚动规则,优先挂到原生
class(custom-class已废弃) - 不要把
Drawer跟Dialog混成一套全局覆盖
当前这批虽然只有 business/order 一个样本,但已经可以先定义统一的壳层命名:
| 壳层类型 | 建议原生 class | 典型尺寸 | 适用页面 |
|---|---|---|---|
| 详情侧栏型 | drawer-shell--detail | 600px 左右 | business/order |
建议的壳层样式骨架可以先统一成下面这套,再按具体业务补局部 class:
.drawer-shell--detail {
--xy-drawer-header-padding-y: 10px;
--xy-drawer-header-padding-x: 16px;
--xy-drawer-body-padding-y: 10px;
--xy-drawer-body-padding-x: 16px;
--xy-drawer-footer-padding-y: 10px;
--xy-drawer-footer-padding-x: 16px;
}
@media screen and (max-width: 1024px) and (min-width: 769px) {
.drawer-shell--detail {
width: min(560px, 90vw) !important;
}
}
@media screen and (max-width: 768px) {
.drawer-shell--detail {
width: 100% !important;
max-width: 100vw;
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
}如果页面只是想统一节奏,优先先改这些公开变量,不要继续 deep 到内部结构:
--xy-drawer-header-padding-y/x--xy-drawer-body-padding-y/x--xy-drawer-footer-padding-y/x--xy-drawer-bg--xy-drawer-title-color
这批的执行顺序也很直接:
- 先保留页面现有
:size="600"语义。 - 再把中屏/移动端的壳层规则收进
drawer-shell--detail。 - 最后才看是否真的需要页面局部的内容布局样式。
首批最适合落地的覆盖替换组
这一步不是让业务项目再发明一轮页面补丁,而是把当前已经验证过的组件库 contract 和后台项目残留的全局覆盖,对齐成两组最容易安全落地的替换批次。
选择这两组作为第一批,原因很直接:
- 命中的页面少,风险边界清楚。
- 已经有稳定的实例级入口,不需要继续改组件库实现。
- 可以直接替换后台项目里最典型的全局
.xy-dialog覆盖,而不用先大面积动表格和筛选区。
替换组 1:dialog-shell--narrow
这组优先处理“窄表单型 Dialog”。它们的共同点是:
- 已经在用
XyDialog - 主要承载新增 / 编辑 / 上传 / 分类维护这类轻量表单
- 默认宽度相近,响应式约束也基本一致
当前建议先纳入这组的后台文件:
src/views/system/task/index.vuesrc/views/system/file/index.vuesrc/views/content/category/index.vuesrc/views/system/menu/index.vuesrc/views/system/user/index.vue
这组页面推荐的落地动作:
- 在对应
XyDialog实例上补统一的panel-class="dialog-shell--narrow"。 - 保留页面已经声明的
width;如果页面当前没写宽度,再按实际内容补500px左右的实例宽度。 - 把全局
.xy-dialog上的中屏 / 移动端响应式规则迁到dialog-shell--narrow。 - 确认没有继续命中
.xy-dialog__header / __body / __footer的历史 deep 覆盖。
建议的替换顺序:
- 先从
system/task、system/file开始,因为内容区最轻,最容易验证。 - 再收
content/category、system/menu。 system/user最后收,因为它通常还会同时带列表操作和表单校验。
这组对应的旧覆盖,优先从后台项目全局样式里迁走:
@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;
}
}替换后的推荐写法:
<xy-dialog
v-model="visible"
title="编辑任务"
width="500px"
panel-class="dialog-shell--narrow"
>
<!-- content -->
</xy-dialog>.dialog-shell--narrow {
--xy-dialog-header-padding-y: 10px;
--xy-dialog-header-padding-x: 16px;
--xy-dialog-body-padding-y: 10px;
--xy-dialog-body-padding-x: 16px;
--xy-dialog-footer-padding-y: 10px;
--xy-dialog-footer-padding-x: 16px;
max-width: min(520px, calc(100vw - 32px));
}
@media screen and (max-width: 1024px) and (min-width: 769px) {
.dialog-shell--narrow {
max-width: 90vw;
margin: 20px auto;
}
}
@media screen and (max-width: 768px) {
.dialog-shell--narrow {
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
max-height: 85vh;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
}这组可以删掉的旧规则类型:
- 全局
.xy-dialog的max-width / margin / border-radius / overflow-y - 页面里只为了统一 padding 而写的
.xy-dialog__header / __body / __footer
这组先别急着删的内容:
- 和具体表单结构耦合的业务排版
- 操作按钮排列、上传区布局、树节点编辑区这类业务内部结构样式
这组的最小验收步骤:
- 任选
system/task或system/file先替换一个页面。 - 验证桌面、中屏、移动端下弹窗宽度和滚动行为是否正常。
- 确认弹窗 header / body / footer 的背景、边框、阴影仍然跟随组件库默认基线。
- 再删除对应的全局
.xy-dialog规则,回归一次同组其它页面。
替换组 2:drawer-shell--detail
这组优先处理“详情型 Drawer”。当前样本虽然少,但 contract 最清楚,也最适合拿来做 Drawer 的标准迁移模板。
当前建议先纳入这组的后台文件:
src/views/business/order/index.vue
这组页面推荐的落地动作:
- 保留实例现有的
:size="600"作为主尺寸语义。 - 在
XyDrawer上补统一的class="drawer-shell--detail"(custom-class已废弃,改用原生class)。 - 把中屏 / 移动端下的宽度、圆角和边界规则迁到
drawer-shell--detail。 - 不要误用
panel-class;Drawer当前公开的是原生class+header-class / body-class / footer-class。
推荐写法:
<xy-drawer
v-model="visible"
:size="600"
class="drawer-shell--detail"
>
<!-- content -->
</xy-drawer>.drawer-shell--detail {
--xy-drawer-header-padding-y: 10px;
--xy-drawer-header-padding-x: 16px;
--xy-drawer-body-padding-y: 10px;
--xy-drawer-body-padding-x: 16px;
--xy-drawer-footer-padding-y: 10px;
--xy-drawer-footer-padding-x: 16px;
}
@media screen and (max-width: 1024px) and (min-width: 769px) {
.drawer-shell--detail {
width: min(560px, 90vw) !important;
}
}
@media screen and (max-width: 768px) {
.drawer-shell--detail {
width: 100% !important;
max-width: 100vw;
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
}这组可以删掉的旧规则类型:
- 为了抽屉响应式尺寸写在全局样式里的
.xy-drawer根类覆盖 - 为了统一 padding 而 deep 到
.xy-drawer__header / __body / __footer的旧规则
这组的最小验收步骤:
- 验证桌面端
size=600语义不变。 - 验证平板宽度是否正确收敛到
min(560px, 90vw)。 - 验证移动端是否铺满宽度且圆角只保留顶部。
- 确认详情区内容布局没有因为抽屉壳层迁移而被误伤。
首批替换组的执行原则
这两组落地时,建议统一遵守下面这套顺序,不要边删全局覆盖边同时乱改业务结构:
- 先给实例补
panel-class或原生class。 - 再把原来写在全局
.xy-dialog或.xy-drawer上的响应式规则迁过去。 - 页面稳定后,再删掉原全局覆盖。
- 最后才判断是否还需要少量业务局部 class。
一句话原则:
- 先挂实例壳层,再删全局根类。
- 先保留业务宽度语义,再统一响应式边界。
- 先验证 contract 生效,再删 deep 覆盖。
批次 C:普通列表页 Table Shell
这批页面的共同点是:
- 基本都已经有
table-shell - 目标不是改表格结构,而是让 header / border / spacing / mobile scroll 回到 wrapper token
- 优先参考 Table 表格 里的
list-shell
当前可直接归到这批的页面有:
src/views/system/user/index.vuesrc/views/system/role/index.vuesrc/views/system/announcement/index.vuesrc/views/system/task/index.vuesrc/views/system/file/index.vuesrc/views/system/log/index.vuesrc/views/content/article/index.vuesrc/views/business/product/index.vuesrc/views/statistics/report/index.vuesrc/views/system/monitor/index.vue
这批的迁移目标:
- 把全局
.xy-table { display: block; overflow-x: auto; }迁到 wrapper - 普通列表页统一走
table-shell + --xy-table-* - 继续删除
.xy-table__cell / __header-cell / __append-wrapper这类内部结构覆盖
批次 D:Dashboard / 概览型 Table
这批页面已经不是普通列表页,应单独看待:
src/views/dashboard/index.vue
当前这个页面已经在使用:
overview- wrapper token
- overview token,如
--xy-table-overview-cell-padding-*
这批页面不应该再和普通列表页共用一套“全局缩小 padding”的思路。后续如果要迁移,优先把它当成概览参考页,而不是列表页模板。
一句话分型:
dashboard/index.vue是概览参考页。- 其余大部分
table-shell页面,先按普通列表页批量迁移。
Table 首批最适合落地的替换组
table 这一批不要一上来就全局删样式。现在更适合先把后台项目里的表格迁成两组,分别处理“普通列表页”和“概览表”。
这样分组的原因很明确:
- 两组的目标完全不同,不能共用一套“缩小 padding”的思路。
- 普通列表页更适合迁到
table-shell + --xy-table-*。 - 概览表已经有
overview能力,应该优先用组件库 contract,而不是继续写 cell 级 deep 覆盖。
替换组 3:table-shell--list
这组优先处理“普通列表页 Table”。它们的共同点是:
- 已经有或很容易补
table-shellwrapper - 主要问题是 header / border / hover / stripe / mobile scroll 还残留页面层覆盖
- 不需要引入
overview
当前建议先纳入这组的后台文件:
src/views/system/user/index.vuesrc/views/system/role/index.vuesrc/views/system/announcement/index.vuesrc/views/system/task/index.vuesrc/views/system/file/index.vuesrc/views/system/log/index.vuesrc/views/content/article/index.vuesrc/views/business/product/index.vuesrc/views/statistics/report/index.vuesrc/views/system/monitor/index.vue
这组页面推荐的落地动作:
- 保留默认
size="md"合同,不要为了“轻一点”直接全局缩小 table。 - 给页面表格统一包一层
table-shell table-shell--list。 - 把 header / border / hover / stripe / spacing 优先迁到 wrapper token。
- 把小屏横向滚动从全局
.xy-table根类迁到 wrapper。 - 清理
.xy-table__cell / __header-cell / __append-wrapper / __empty-block这类历史 deep 覆盖。
建议先从下面几页起步:
system/usersystem/rolesystem/task
这几页的代表性最强,也最容易验证“普通列表页 contract 是否足够”。
推荐写法:
<template>
<div class="table-shell table-shell--list table-shell--mobile-scroll">
<xy-table :data="rows" row-key="id">
<!-- columns -->
</xy-table>
</div>
</template>.table-shell--list {
--xy-table-header-background: var(--bg-elevated);
--xy-table-header-text-color: var(--text-secondary);
--xy-table-border-color: var(--border-default);
--xy-table-row-hover-background: color-mix(in srgb, var(--bg-elevated) 88%, var(--brand-500) 12%);
--xy-table-striped-row-background: color-mix(in srgb, var(--bg-surface) 90%, var(--brand-500) 10%);
--xy-table-body-cell-padding-y: 10px;
--xy-table-body-cell-padding-x: 12px;
--xy-table-header-cell-padding-y: 10px;
--xy-table-header-cell-padding-x: 12px;
}
@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;
}
}这组对应的旧覆盖,优先从后台项目全局样式或页面 scoped 样式里迁走:
@media screen and (max-width: 480px) {
.xy-table {
display: block;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
}
:deep(.xy-table__cell) {
padding: 8px 12px;
}
:deep(.xy-table__header-cell) {
background: #fafafa;
}这组可以删掉的旧规则类型:
- 全局
.xy-table { display: block; overflow-x: auto; } - 只为了压密度而写的
.xy-table__cell / __header-cellpadding 覆盖 - 只为了接主题而写的
.xy-table__row:hover > .xy-table__cell、header 背景、边框颜色覆盖
这组先别急着删的内容:
- 操作列按钮排列
- 展开行里明显依赖业务结构的内容样式
- 和第三方内容渲染耦合的表格样式
这组的最小验收步骤:
- 先替换
system/user或system/role一个页面。 - 验证亮色 / 暗色主题下 header、body、border、hover、stripe 是否跟随 token。
- 验证小屏时横向滚动是否只发生在 wrapper,而不是继续命中全局
.xy-table。 - 再回归同组另外 1 到 2 个列表页,确认普通列表页不需要
overview也能保持干净基线。
替换组 4:table-shell--overview
这组优先处理“Dashboard / 概览型 Table”。这类页面不能再沿用普通列表页的迁移心智。
当前建议先纳入这组的后台文件:
src/views/dashboard/index.vue
这组页面推荐的落地动作:
- 显式开启
overview。 - 保留 wrapper,但把节奏微调优先放到
--xy-table-overview-*token。 - 不要再靠
.xy-table__cell、.xy-table__expanded-content之类内部类名手工压缩。
推荐写法:
<template>
<div class="table-shell table-shell--overview">
<xy-table
overview
:data="rows"
row-key="id"
>
<!-- columns -->
</xy-table>
</div>
</template>.table-shell--overview {
--xy-table-overview-cell-padding-y: 8px;
--xy-table-overview-cell-padding-x: 12px;
--xy-table-header-cell-padding-y: 8px;
--xy-table-header-cell-padding-x: 12px;
--xy-table-header-color: var(--text-tertiary);
--xy-table-row-hover-background: color-mix(in srgb, var(--bg-elevated) 90%, var(--brand-500) 10%);
}这组可以删掉的旧规则类型:
- 为了“看起来像 dashboard 卡片表”而手工压缩的
.xy-table__cellpadding - 为了弱化 header 而单独写的
.xy-table__header-cell字色 / 背景覆盖 - 为了收轻 hover 而 deep 到 row / cell 的 hover 规则
这组的最小验收步骤:
- 验证开启
overview后,首屏密度是否明显轻于普通列表页。 - 验证 header 节奏、cell padding 和 hover 不再依赖页面 deep 覆盖。
- 验证同页其它普通表格没有被误切成
overview语义。
Table 首批替换组的执行原则
table 这条线建议按下面的顺序推进,不要把列表页和概览页混改:
- 先判断当前页面是普通列表页还是概览表。
- 普通列表页先挂
table-shell--list或table-shell--mobile-scroll,优先用--xy-table-*。 - 概览表先显式开启
overview,再用--xy-table-overview-*微调。 - 页面稳定后,再删除旧的
.xy-table根类和__cell / __header-celldeep 覆盖。
一句话原则:
- 列表页优先 wrapper token。
- 概览页优先
overview。 - 不要再用一套全局 cell padding 去同时解决两类页面。
优先顺序
- 先处理
dialog / drawer / tooltip / popconfirm / popover / select / dropdown / date-picker / time-select / time-picker / cascader / tree-select / auto-complete。 - 再处理
message / notification / loading。 - 最后处理
table,普通列表页用 wrapper token,dashboard / 摘要页用overview。
迁移 checklist
- 删除页面层对浮层内部面板类名的
background / border / shadow / padding覆盖。 - 优先改成组件实例上的
popper-class、panel-class、body-class,或者直接覆盖对应--xy-*变量。 message / notification / loading只保留真正的业务强度差异,不要把它们当普通卡片或遮罩去写页面样式;其中loading的 directive 层优先改成xy-loading-*,loading service 再用customClass / background / text。table普通列表页优先用 wrapper token,不要继续 deep 到.xy-table__cell、.xy-table__header-cell、.xy-table__append-wrapper。table用于 dashboard 首屏、经营看板或摘要区时,优先开启overview。- 对筛选区组件,优先删掉 trigger / dropdown / option / cell 这些内部类名覆盖,先观察组件库默认基线是否已满足页面。
- 如果页面里的卡片标题或浮层触发器根本没渲染出来,先回头核对组件公开 contract,而不是先补页面样式。
额外判断规则:
- 如果
Popconfirm的按钮已经真实可见,但视觉还是偏重,先删页面层对tooltip / popconfirm内部面板类名的覆盖,再决定是否需要业务局部 token。 - 如果
Dialog的底色、边框、阴影已经跟上主题,但 body/header padding 还是旧值,优先搜业务页或全局样式里是否还在覆盖.xy-dialog__header / .xy-dialog__body / .xy-dialog__footer。 - 如果表格暗色主题已经不再发白,但 dashboard 仍然像列表页一样偏重,优先切到
overview,不要先去全局缩小.xy-table th / td。
推荐迁移顺序
建议按“最容易回收页面覆盖”的顺序删,不要一上来全删:
- 先删浮层和通知类覆盖:
dialog / drawer / tooltip / popconfirm / popover / dropdown / menu / message / notification / loading- 这批现在应优先使用
popper-class / panel-class / body-class / 原生 class(Drawer) / custom-class(message、notification) / xy-loading-*(loading directive) / customClass(loading service)和实例级 token
- 再删筛选区覆盖:
select / auto-complete / cascader / tree-select / date-picker / time-picker / time-select- 重点回收 trigger、dropdown、option、cell、快捷项这类内部类名覆盖
- 最后删表格覆盖:
- 列表页优先迁到 wrapper token
- dashboard / 摘要区优先迁到
overview
业务项目删除覆盖时的判断标准
可以删:
- 纯视觉覆盖:
background / border / shadow / border-radius / padding / color / hover / selected - 为了主题切换临时写在页面层的亮暗色修补
- 为了压视觉层级写在页面层的“更轻一点 / 更干净一点”覆盖
先别删:
- 真正和页面结构耦合的布局样式,例如操作列按钮排列、业务区块间距、复合卡片内部排版
- 直接依赖业务类名、业务状态类或异步加载链路的结构样式
- 明显属于业务品牌差异,而不是组件默认基线的问题
一句话判断:如果页面覆盖只是在“修组件默认态太重、太亮、太乱”,现在应优先回到组件库层能力。
补充一条联调后的判断规则:
- 如果页面样式命中的是业务 wrapper、自定义
body-class或--xy-*token,先不要把它和旧 deep 补丁混为一类。 - 如果页面样式直接命中
.xy-dialog、.xy-table或更深的__body / __cell / __option,再优先判断是否属于应继续收口的历史覆盖。
常见替代
| 旧写法 | 推荐替代 |
|---|---|
.xy-dialog__header { padding: ... } | panel-class / body-class / footer-class + --xy-dialog-* 变量 |
.xy-drawer__body { padding: ... } | body-class / header-class / footer-class + --xy-drawer-* 变量 |
.xy-popover__panel / .xy-tooltip__content / .xy-popconfirm__panel | popper-class + 对应 --xy-* 变量 |
.xy-select__dropdown / .xy-dropdown__panel | popper-class + 对应 --xy-* 变量 |
.xy-message / .xy-notification | 组件级 type、plain、custom-class(service 对应 customClass) |
.xy-loading(directive) | xy-loading-custom-class / xy-loading-background / xy-loading-text |
loading service / options | customClass / background / text |
.xy-table__cell { padding: ... } | --xy-table-body-cell-padding-y/x |
.xy-table__header-cell { background: ... } | --xy-table-header-background |
.xy-table__row:hover > .xy-table__cell { background: ... } | --xy-table-row-hover-background |
.xy-table__expanded-cell / __append-wrapper / __empty-block | overview 或 overview token |
高优先级 contract 提醒
这条迁移线里,最容易被误判成“样式没生效”的,其实有两类 contract 问题。它们都应先回到组件公开入口修正,不要继续在页面层打补丁。
Popconfirm 的旧触发写法兼容边界
- 当前组件已经兼容一类旧写法:
- 未提供
reference插槽 - 且没有传
content - 此时
default插槽会被视为 trigger
- 未提供
- 这主要用于兼容历史页面里直接把按钮写在默认插槽的场景,避免“删除 / 清空按钮直接消失”。
- 但如果页面同时把
default当 trigger,又想把正文也塞进默认插槽,这仍然是歧义写法;应显式改成:#reference负责触发器content或默认插槽负责正文
推荐写法:
<xy-popconfirm title="确认删除">
<template #reference>
<xy-button text type="danger">删除</xy-button>
</template>
删除后将无法恢复
</xy-popconfirm>XyCard 的公开 contract 不是 title / #header-extra
XyCard当前真实公开 contract 是:headerextraheader-class / body-class / footer-class
- 不是:
title#header-extra
- 如果页面仍然写
<XyCard title=\"...\">或<template #header-extra>,结果通常不是“header 样式失效”,而是xy-card__header根本不会渲染。
推荐写法:
<xy-card
header="经营分析"
header-class="dashboard-card__header"
body-class="dashboard-card__body"
>
<template #extra>
<xy-button text>查看全部</xy-button>
</template>
<div>卡片内容</div>
</xy-card>判断顺序:
- 先看 header / trigger 是否真实渲染。
- 再看
header-class / body-class / popper-class这类公开入口是否已经挂上。 - 最后才判断是不是还需要业务局部 token。
筛选区组件的替代策略
后台项目最容易留下历史 deep 覆盖的其实不是按钮,而是筛选区。现在这批组件优先按下面的方式回收:
| 旧覆盖写法 | 推荐替代 |
|---|---|
.xy-select__trigger / .xy-cascader__trigger / .xy-tree-select__trigger | 优先删除;仍需轻度调节时,只在业务 wrapper 上覆写对应 --xy-*trigger* 或实例级变量 |
.xy-select__dropdown / .xy-cascader__dropdown / .xy-tree-select__dropdown | popper-class + 对应 --xy-*dropdown* 变量 |
.xy-auto-complete__option / .xy-time-select__option | 先删除页面覆盖,保留组件库默认 option hover / selected 态 |
.xy-date-picker__cell / .xy-time-picker__option / __action / __shortcut | 先回到组件库默认态;只在业务确有品牌差异时,再做实例级轻覆写 |
补充说明:
date-picker / time-picker / time-select / select / auto-complete / cascader / tree-select这一组现在默认已经按同一套后台输入浮层基线收过一轮,主题切换优先依赖组件库默认态,不建议再在页面层分别压阴影和分区背景。- 如果业务页面只是想“让筛选条更克制一点”,默认先删页面级
:deep(.xy-*),只保留 wrapper 上的少量全局 token 接轨;不要继续把每个 trigger / dropdown / option 当单独组件修。
推荐的筛选条 wrapper 写法示例:
<template>
<div class="filter-shell">
<xy-select />
<xy-cascader />
<xy-date-picker />
<xy-time-select />
</div>
</template>
<style scoped>
.filter-shell {
--xy-bg-elevated: var(--bg-elevated);
--xy-border-strong: var(--border-strong);
}
</style>- 这类 wrapper 级变量,只应该做页面主题接轨。
- 不建议继续 deep 到
__trigger / __dropdown / __option / __cell改内部类名。
筛选区首批最适合落地的替换组
筛选区这条线不要按单个组件散着修。后台项目更常见的真实问题,是一整条筛选条同时命中了 trigger、dropdown、option、cell 的历史 deep 覆盖。
所以更稳的方式,是按“筛选条场景”而不是按单个组件拆组。
替换组 5:filter-shell--toolbar
这组优先处理“普通列表页筛选条”。它们的共同点是:
- 组件种类多,但本质都属于后台工具栏筛选区
- 想解决的是整体克制感,而不是单个下拉面板的品牌化视觉
- 最适合优先迁到 wrapper token,再逐步删内部类名覆盖
当前建议优先纳入这组的组件:
xy-selectxy-auto-completexy-cascaderxy-tree-selectxy-date-pickerxy-time-pickerxy-time-select
这组推荐的落地动作:
- 先给页面筛选条统一包一层
filter-shell filter-shell--toolbar。 - 先把背景、边框、elevated surface 这类主题接轨迁到 wrapper token。
- 再删 trigger / dropdown / option / cell 相关 deep 覆盖。
- 只有某个实例确实需要特殊面板视觉时,再补
popper-class。
推荐写法:
<template>
<div class="filter-shell filter-shell--toolbar">
<xy-select />
<xy-cascader />
<xy-tree-select />
<xy-date-picker />
<xy-time-select />
</div>
</template>.filter-shell--toolbar {
--xy-bg-elevated: var(--bg-elevated);
--xy-border-strong: var(--border-strong);
--xy-fill-light: color-mix(in srgb, var(--bg-elevated) 92%, var(--brand-500) 8%);
--xy-text-secondary: var(--text-secondary);
}这组可以优先删掉的旧规则类型:
.xy-select__trigger / .xy-cascader__trigger / .xy-tree-select__trigger.xy-select__dropdown / .xy-cascader__dropdown / .xy-tree-select__dropdown.xy-auto-complete__option / .xy-time-select__option.xy-date-picker__cell / .xy-time-picker__option / __action / __shortcut
这组先别急着删的内容:
- 只命中业务 wrapper 的间距规则
- 搜索表单栅格布局
- 明显依赖业务状态类的标签或按钮排列
这组的最小验收步骤:
- 先验证 trigger、placeholder、清空按钮在亮色主题下是否正常。
- 再验证 dropdown / option / cell 在暗色主题下是否还存在局部发白。
- 验证 hover、selected、快捷项、日期面板单元格是否已经回到组件库默认基线。
- 最后再决定是否还有少量实例需要
popper-class。
替换组 6:filter-shell--range
这组优先处理“时间区间 / 组合筛选”这类较重的筛选面板。它们的共同点是:
- 更容易留下
.xy-date-picker__cell、.xy-time-picker__option、.xy-time-select__option这类深层覆盖 - 经常伴随快捷项、区间输入和复杂 dropdown
- 不适合只靠 trigger 级微调解决
当前建议优先纳入这组的组件:
xy-date-pickerxy-time-pickerxy-time-select- 以及与其并排出现的
xy-select / xy-auto-complete
这组推荐的落地动作:
- 先保留原页面的业务筛选流程,不先动联动逻辑。
- 给外层筛选区统一包一层
filter-shell filter-shell--range。 - 优先删日期 / 时间面板里的 cell、option、shortcut、action 纯视觉覆盖。
- 如果确实还需要个别 dropdown 样式差异,再落到实例
popper-class,不要重新回到全局 deep 覆盖。
推荐写法:
<template>
<div class="filter-shell filter-shell--range">
<xy-date-picker type="daterange" />
<xy-time-select />
<xy-select />
</div>
</template>.filter-shell--range {
--xy-bg-elevated: var(--bg-elevated);
--xy-border-strong: var(--border-strong);
--xy-fill-light: color-mix(in srgb, var(--bg-elevated) 90%, var(--brand-500) 10%);
--xy-text-secondary: var(--text-secondary);
}这组可以优先删掉的旧规则类型:
.xy-date-picker__cell.xy-time-picker__option.xy-time-select__option.xy-date-picker__action / __shortcut.xy-date-picker__panel或同类面板上的纯视觉覆盖
这组的最小验收步骤:
- 验证日期单元格、时间 option、快捷项、操作区在亮色 / 暗色主题下是否都回到统一基线。
- 验证 range 选择、hover、selected、禁用态没有被误伤。
- 验证清空、展开、确认等交互仍然正常。
筛选区替换组的执行原则
筛选区这条线建议按下面顺序推进,不要先改单个 option 或单个 dropdown:
- 先给整条筛选区挂
filter-shell。 - 先用 wrapper token 接主题,再删 deep 覆盖。
- 只有确实需要特殊面板视觉时,才给单个实例补
popper-class。 - 不要再把 trigger、dropdown、option、cell 分别当成独立组件修。
一句话原则:
- 先收整条筛选区。
- 再删内部类名覆盖。
- 最后才做实例级特化。
表格迁移策略
table 这一项不要和浮层、筛选区混着删,建议单独处理:
- 普通列表页:
- 先迁到 wrapper token
- 保留
size="md"默认合同 - 不要再全局缩小所有 cell padding
- dashboard / 摘要区:
- 优先启用
overview - 仍需微调时,再加
--xy-table-overview-*变量
- 优先启用
当前推荐组合:
- 普通列表页:
wrapper token + 默认 table - 首屏摘要表:
overview + wrapper token
联调里最常见的两类残留如下:
- 普通列表页残留:
- 还在页面层或全局样式里写
.xy-table th / td { padding: ... } - 还在 deep 到
.xy-table__row:hover > .xy-table__cell - 这类都应先迁到
.table-shell这类 wrapper token
- 还在页面层或全局样式里写
- dashboard 摘要表残留:
- 已经想要更紧凑的节奏,却仍然只靠
.xy-table__cell/.xy-table__expanded-content手工压 padding - 这类应先开启
overview,再按需补--xy-table-overview-*
- 已经想要更紧凑的节奏,却仍然只靠
如果业务项目已经像 dashboard 一样显式写了 overview,但还保留大量 cell 级 deep 覆盖,默认应继续删覆盖,而不是反过来把 overview 当成无效能力。
浮层迁移策略
浮层类这轮最容易被误判。建议按下面顺序排查:
- 先确认按钮或 trigger 是否真实可见。
- 再确认点击后是否弹出真实浮层。
- 最后才判断视觉层级是不是还要做业务局部微调。
对于已经接入这轮组件库改动的业务项目,下面这些现象通常不该再当成组件库 bug:
Popconfirm删除按钮消失:- 如果页面还在用旧写法,先升级到这轮组件库;正常情况下按钮应恢复可见。
Tooltip / Popconfirm暗色主题下仍像一块亮白卡片:- 优先检查业务页是否自己覆写了
background / border / shadow。
- 优先检查业务页是否自己覆写了
Dialog / Drawer的底色和边框已经对了,但 body/header padding 还是旧值:- 优先检查业务全局样式或 scoped deep 覆盖;组件库默认值不应继续替业务页面兜底。
迁移完成后的目标状态
当一个后台页面完成迁移后,理想状态应该是:
- 页面层不再维护大块
.xy-*内部类名覆盖 - 页面层只保留业务结构样式和少量 wrapper 级 token
- 浮层、筛选区、通知、表格的亮暗主题切换都主要依赖组件库默认基线
- 新页面默认先用组件库默认态,不再预设“要先补一轮 deep 样式”
后台项目覆盖删除顺序清单
真正回后台项目落地时,建议不要“搜到 .xy- 就直接删”。现在更稳的方式,是按规则类型和风险分层删除。
第 1 层:先删全局根类覆盖
这层优先级最高,因为它最容易把整个后台项目的视觉基线绑死在旧样式上。
优先处理:
src/style/index.scss里的全局.xy-dialog- 同文件里小屏下的全局
.xy-table
推荐删除顺序:
- 先给对应页面补上
dialog-shell--narrow、drawer-shell--detail、table-shell--mobile-scroll - 再删全局
.xy-dialog的max-width / margin / border-radius / overflow-y - 再删全局
.xy-table的display: block / overflow-x: auto
这一层删完后的回归重点:
dialog在桌面 / 平板 / 移动端是否仍能正常控制宽度和滚动table小屏横向滚动是否已经迁到 wrapper,而不是全局根类
第 2 层:再删纯视觉 deep 覆盖
这层优先删“背景、边框、阴影、padding、hover、selected”这类只是在修组件默认态的规则。
优先处理的规则类型:
.xy-dialog__header / __body / __footer.xy-drawer__header / __body / __footer.xy-tooltip__content / .xy-popconfirm__panel / .xy-popover__panel.xy-table__cell / __header-cell / __row:hover > __cell.xy-select__dropdown / .xy-date-picker__cell / .xy-time-select__option
删除判断:
- 如果命中的是组件公开入口已经能承接的内容,优先删
- 如果删掉后页面只是“变回组件库默认视觉”,通常说明这条规则本来就该删
这一层删完后的回归重点:
- 浮层背景、阴影、边框是否仍然统一
- 表格 header、border、hover、stripe 是否仍然跟随 token
- 筛选区 dropdown / option / cell 是否仍然保持克制基线
第 3 层:最后再看结构耦合样式
这一层最容易误伤业务页面,不适合和前两层混着删。
暂时先保留:
- 操作列按钮排列
- 复合卡片内部排版
- 上传区、树节点编辑区、展开行内容区布局
- 明显依赖业务状态类或业务 wrapper 的布局规则
判断标准:
- 如果规则改的是“业务内容怎么摆”,先保留
- 如果规则改的是“组件外观该不该更轻、更暗、更克制”,优先回到组件库层
按文件推进的推荐删除顺序
如果后续真的回后台项目执行迁移,建议按下面顺序推进,而不是在所有页面里同时删样式。
第一批:先收全局入口和最轻页面
建议顺序:
src/style/index.scsssrc/views/system/task/index.vuesrc/views/system/file/index.vuesrc/views/content/category/index.vue
原因:
- 这些页面最容易承接
dialog-shell--narrow - 内容区轻,回归成本低
- 最适合验证“删全局
.xy-dialog后是否还稳定”
第二批:收标准列表页
建议顺序:
src/views/system/user/index.vuesrc/views/system/role/index.vuesrc/views/system/announcement/index.vuesrc/views/system/log/index.vue
原因:
- 这批能同时验证
dialog-shell--narrow / form和table-shell--list - 也是后台项目最典型的 CRUD 列表页
- 一旦这批稳定,后续大部分普通后台页面都可以照抄迁移方式
第三批:收详情抽屉和概览表
建议顺序:
src/views/business/order/index.vuesrc/views/dashboard/index.vue
原因:
Drawer和overview table都属于单独语义,不适合和普通列表页混改- 这批页面更适合作为“专项 contract 验证页”
每一批删除覆盖时的最小回归顺序
每批落地时,不要只看 DOM 或只看一套主题。建议最少按下面顺序回归:
- 先看亮色主题桌面端
- 再看暗色主题桌面端
- 再看中屏尺寸
- 最后看移动端或窄屏
每一步至少确认:
- trigger / header / footer 是否真实渲染
- 浮层是否能正常打开
- 背景、边框、阴影、padding 是否回到组件库默认基线
- 没有出现“删了旧覆盖后整个组件发白 / 发亮 / 过重”的回退
覆盖删除时的快速决策规则
后续真正删规则时,可以直接按下面的判定走,减少来回讨论:
- 命中
--xy-*token:默认保留,除非变量本身已经重复或冲突 - 命中
panel-class / body-class / custom-class / popper-class:默认保留 - 命中
.xy-dialog、.xy-table这类全局根类:优先迁走 - 命中
__header / __body / __cell / __option / __panel这类内部结构类名:优先评估删除 - 命中业务 wrapper、自定义业务 class:默认先保留,再看是否能进一步抽象
一句话总结:
- 先删全局根类。
- 再删纯视觉 deep 覆盖。
- 结构耦合样式最后处理。