PVQ-UI 组件库开发方案
状态:草案(待评审定稿) 作者:溟远 适用仓库:
pvq-ui(独立组件库) 关联插件:pvq-wolai-sync、pvq-threads-sync(后续迁移);参考pvq-wp的 FontAwesome 统一管理模式
1. 背景与目标
1.1 真实需求(一句话)
写一次组件库,以后写插件直接调用它,不再单独写组件;存量插件逐步替换成它,实现全站样式统一。
1.2 当前痛点(已核实代码)
pvq-wolai-sync后台已实现一套完整的.pvq-*通用组件 + 全套--pvq-*设计令牌(assets/css/admin-settings.css:11-62)。pvq-threads-sync另起一套.pvq-ts-*命名空间,并*复制了同一套 `--pvq-令牌**(assets/css/admin.css:8-43),连 FontAwesome 都硬编码了自己的 handle(includes/class-threads-sync.php:234的threads-sync-fa`)。- 结果:同一套设计语言被重复实现、各自演进,风格必然漂移,且每次新插件都要重写一遍通用组件。
1.3 目标
pvq-ui成为所有 PVQ 插件的「界面样式唯一真源」。- 新插件从第一天起直接调用
pvq-ui,零通用组件副本。 - 存量插件(wolai → threads)分阶段替换,统一视觉语言。
- 设计令牌(颜色 / 圆角 / 阴影 / 动画)全站一致。
2. 设计原则(精简版,已修正草案矛盾)
- 单一真源:通用组件只存在于
pvq-ui,插件不再自带副本。 - CDN 单一源:构建产物上传固定 URL,所有插件引用同一 URL(零本地副本、零 build 同步)。
- 自给自足:不依赖
pvq-wp,也不强制安装任何基座插件。收敛逻辑随库自带(见 §3.3),而非各插件重写。 - BEM 命名:
pvq-{block}/pvq-{block}__{element}/pvq-{block}--{modifier}。 - 渐进完善:先落地最高频的后台设置页 + 通用组件,前端 / 编辑器组件随后补充。
修正说明:原草案 §2.3「纯自给自足」与 §3.3「每个消费插件挂载 override 收敛」自相矛盾——若每个插件各自重写收敛逻辑,既不单一真源又易出 bug。本方案改为:收敛逻辑内置于库自带的
pvq-ui-loader.php单一文件,由各插件复制引用,而非重写(见 §3.3)。
3. 架构与运行机制
3.1 产物(CDN 固定路径)
构建后上传到 https://<CDN_BASE>/pvq-ui/<版本>/ 下的固定文件名:
| 文件 | 场景 | WordPress handle | 依赖 |
|---|---|---|---|
pvq-ui.css |
全场景 base(令牌 + 通用组件) | pvq-ui |
无 |
pvq-ui-admin.css |
后台 | pvq-ui-admin |
pvq-ui, font-awesome |
pvq-ui-editor.css |
块编辑器 | pvq-ui-editor |
pvq-ui |
pvq-ui-frontend.css |
前端 | pvq-ui-frontend |
pvq-ui, font-awesome |
pvq-ui.js |
全场景交互(原生 JS) | pvq-ui |
无 |
组件视觉大量使用 FontAwesome 图标(按钮 / 卡片图标 / 连接状态等),故
pvq-ui-admin与pvq-ui-frontend均须声明对font-awesome句柄的依赖;loader 会一并保证 FA 已注册(见 §3.3)。frontend 层依赖 FA 后,DataGrid 工具栏的搜索 / 排序 / 筛选 / 重置等 FA 图标在前端页面(如 wolai 前台)也能正常渲染,不必再像官网那样手动硬链 FA。
v1.2.10 新增 frontend 组件「权重输入框 Weight」(随 1.2.11 固化发布):多维权重配置(功能/性能/美观…),数字输入框与滑块双向联动微调,底部「重置/归一化」按钮使总和归 100,实时显示总和。结构契约见
doc/模块文档/设计令牌与组件清单.md「权重输入框 Weight」条目;JS 由initWeights()(已并入initAll,幂等)自动接管。设计原则为「形状归库、颜色归令牌」:组件仅定义--pvq-weight-accent(默认--pvq-primary绿),聚焦/滑块/徽章全部走该令牌,零硬编码主色,保证与全库森林绿一致。
新增 base 组件「浮层通知 Toast」+「可关闭横幅 Banner
__close」(回流自 pvq-weixinyuedu 通知与反馈需求):既有的三个反馈组件分工各不相同——.pvq-alert内联于页面流、.pvq-banner常驻于区块顶部、.pvq-status仅作状态点,缺一个「一次操作的即时结论」承载位。Toast 补上这一档:右上角固定堆叠、短暂停留后自动消失,同屏最多 4 条,悬停暂停倒计时。极为关键的三个设计约定:① 容器.pvq-toast-layer由库 JS 惰性创建(挂<body>、幂等),故 JS 未加载时页面无任何 DOM 残留;②z-index:100002刻意在.pvq-modal遮罩(100001)之上——否则「弹窗确认 → 删除成功」这条最高频链路在遮罩关闭前看不到结果;③ 布局令牌--pvq-toast-offset-y/-x默认取中性值20px,WP 后台让开 admin bar 的44px由消费方覆写,避免 base 层组件默认假设后台环境。颜色照例只走--pvq-toast-accent,零硬编码。横幅侧新增__close由initBanners()接管并派发pvq-banner:close,关闭记忆由插件持久化,库不碰 storage。结构契约见doc/模块文档/设计令牌与组件清单.md「浮层通知 Toast」条目;JS API 为PVQUI.toast(options)与声明式[data-pvq-toast],initToasts()/initBanners()已并入initAll。注意initAll同时绑DOMContentLoaded与resize:两个 init 必须做到「只确保存在 / 只绑一次」,绝不能在初始化中清理正在显示的 toast(否则窗口一缩放通知就消失)。
v1.2.10 新增 base 组件「二次确认弹窗 Confirm Modal」:破坏性操作的弹窗式二次确认,与既有
data-pvq-confirm(按钮就地二次确认,1.2.0)互为补充——就地确认轻量、适合表格行内删除;弹窗重量级、适合需说明后果/列出影响对象/异步执行的场景。颜色由--pvq-modal-accent驱动(默认--pvq-danger红,与--armed语义一致;变体--warning/--primary只换令牌),确认按钮为实色 accent + 白字以便一眼识别动作性质。JS 由initConfirms()(已并入initAll,幂等)接管开合、焦点陷阱、Esc、焦点归还、body 滚动锁,并派发pvq-modal:confirm供插件执行业务(库只管 UI)。注意:组件按钮复用.pvq-btn基类时,改背景需 ≥(0,4,1) 特度才能压过库button.pvq-btn.pvq-btn。详见调用手册 §4.5。
v1.3.1 新增 base 组件「锚点浮层 Popover」(
experimental,回流自 pvq-weixinyuedu):以某元素为锚、脱离文档流、按需显隐的浮层(术语解释 / 作者卡 / 预览 / 迷你详情),补上库中缺失的「浮层气泡类」——card是常驻容器(无定位与开合)、collapse是原地展开会撑高文档流造成布局位移、confirm-modal是模态阻断交互、toast固定角落不锚定触发元素,四者都不能替代。类.pvq-popover+__body/__foot/__arrow,修饰符--open(打开态,JS 加)、--above(JS 判定的上方位置);开关契约只有hidden(彻底不显示)与--open(淡入)两态,库不碰业务。三个关键约定:① 定位用position:fixed+getBoundingClientRect()实时算并写内联top/left,刻意不用 absolute——absolute 必须假定业务容器是定位上下文,而那是业务的自由,库不该假定,故本组件不依赖任何祖先position;② 形状归库、颜色归令牌,只暴露布局令牌--pvq-popover-width/--pvq-popover-z,并显式声明font-size/line-height(防.entry-content等主题放大正文),内容区用.pvq-popover .pvq-popover__body(0,2,0)压过主题.entry-content p(0,1,1)且不引用主题类;③ 库默认即浮层态、不设.pvq-js渐进分支,故 JS 缺席时浮层不可见(信息兜底归调用方),这也使调用方无需再写 head 同步脚本消 FOUC。JS 双入口PVQUI.popover(anchor, opts)与声明式[data-pvq-popover="<浮层 id>"],initPopovers()已并入initAll且幂等(同一浮层只初始化一次、document/window 级监听只绑一次——initAll也绑在 resize 上,这是 1.3.0initConfirms()幂等教训的直接落实)。事件pvq-popover:open/pvq-popover:close。落库决策与完整契约见doc/开发文档/PVQ-UI回流落库-Popover锚点浮层.md,用法见调用手册 §4.7。
3.2 常量 + 句柄守卫(平移 FontAwesome 模式)
先定义者生效、同句柄不重复注册:
if ( ! defined( 'PVQ_UI_URL' ) ) define( 'PVQ_UI_URL', 'https://<CDN_BASE>/pvq-ui/<ver>/pvq-ui.css' );
if ( ! defined( 'PVQ_UI_ADMIN_URL' ) )define( 'PVQ_UI_ADMIN_URL','https://<CDN_BASE>/pvq-ui/<ver>/pvq-ui-admin.css' );
if ( ! defined( 'PVQ_UI_EDITOR_URL' ) )define('PVQ_UI_EDITOR_URL','https://<CDN_BASE>/pvq-ui/<ver>/pvq-ui-editor.css' );
if ( ! defined( 'PVQ_UI_FRONT_URL' ) )define( 'PVQ_UI_FRONT_URL','https://<CDN_BASE>/pvq-ui/<ver>/pvq-ui-frontend.css' );
if ( ! defined( 'PVQ_UI_VERSION' ) ) define( 'PVQ_UI_VERSION', '1.0.0' );
foreach ( array( 'pvq-ui' => PVQ_UI_URL, 'pvq-ui-admin' => PVQ_UI_ADMIN_URL, 'pvq-ui-editor' => PVQ_UI_EDITOR_URL, 'pvq-ui-frontend' => PVQ_UI_FRONT_URL ) as $h => $url ) {
if ( ! wp_style_is( $h, 'registered' ) ) {
$deps = ( 'pvq-ui' === $h ) ? array() : array( 'pvq-ui' );
if ( 'pvq-ui-admin' === $h ) $deps[] = 'font-awesome';
wp_register_style( $h, $url, $deps, PVQ_UI_VERSION );
}
}
3.3 pvq-ui-loader.php(单一收敛点,随库分发)
库随附一个自包含的 pvq-ui-loader.php(约 60 行)。消费方复制到自身 includes/ 后 require_once 并调用助手函数即可:
require_once __DIR__ . '/pvq-ui-loader.php';
PVQ_UI_Loader::enqueue( array( 'admin' ) ); // 后台场景;'editor' / 'frontend' 同理
该文件集中负责:
- 定义 §3.2 的 4 个常量(均
defined()守卫); - 注册 4 个句柄(
wp_style_is守卫); - 提供
PVQ_UI_Loader::enqueue( $scenes )助手; - 版本收敛(override)内置于此,挂载
wp_print_styles(999),把所有pvq-ui*句柄的src/ver收敛到对应常量 URL,防止某插件硬编码旧版。
收敛逻辑用 did_action('pvq_ui_override_registered') 守卫,多副本只实际挂载一次、幂等;默认开启,可被常量 PVQ_UI_NO_CONVERGE 关闭。
这样「自给自足」与「统一收敛」不再矛盾:单一真源是库文件,不是各插件重写;且不依赖
pvq-wp。
3.4 句柄 / 常量集中
全部常量在 pvq-ui-loader.php 顶部集中定义;消费方只通过 defined() 保护做覆盖(便于内网站点把 URL 指向本地副本)。
3.5 组件清单 JSON 唯一真源 + 官网画廊数据驱动
组件清单长期存在两份漂移隐患:①doc/模块文档/设计令牌与组件清单.md(人类可读);②site/inc/gallery.php(官网画廊手抄 HTML)。本方案收敛为单一机器可读真源 site/inc/components.json:
- 结构:
{ "version", "groups":[ { "title", "items":[ { "id","name","icon","stability","layer","desc","note","demos":[ { "title","html" } ] } ] } ] }。demos[].html即画廊"预览"与"代码示例"共用的同一份 HTML——只写一次,预览和代码块都从它来。 - 字段语义(v1.4.0 规范):
stability:严格二值stable/experimental(《库演进治理方案》§5),机器可读、可直接断言;不再往里塞层级或版本文字。layer:组件真实归属层base/admin/editor/frontend(须与 CSS 实际所在文件一致)。note(可选):来源/版本等附加信息,如"1.2.9 并入"、"v1.2.10 新增(随 1.2.11 固化发布)"、"回流自 pvq-weixinyuedu"。给人看,不参与断言。desc:含内联 HTML 的说明,由画廊原样输出(仅受信内容)。- 画廊的稳定性标签由
layer+stability(+note)拼接渲染,故二值化不丢展示信息。
- 官网画廊数据驱动:
gallery.php遍历 JSON 自动生成侧边栏导航、每个组件的<section>预览区与代码块。新增组件只需在 JSON 的items加一条,画廊侧边栏 + 预览 + 代码全部自动出现,杜绝手抄三遍。 - 双轨部署(本地即时 + 线上跟版本):
- 本地:
gallery.php直接读仓库内site/inc/components.json,改 JSON 刷新即见(无需部署)。 - 线上:
deploy.sh把components.json一并同步到 COSpvq-ui/v{ver}/components.json,gallery.php运行时读该同版本 JSON(与库 CSS 同目录同版本,天然一致)。
- 本地:
- 与
.md的关系:.md降级为"人类可读 API 说明",引用 JSON 条目、不再手抄示例;令牌表(:root全集)仍留.md(令牌不进 JSON)。凡"有无某组件"以 JSON 为准。
该 JSON 随库版本一起发布到 COS,库一升级,线上画廊自动跟随多组件、变稳定性标签。
4. 文件结构与组件清单
标注 [提取] = 直接来自现有
pvq-wolai-sync/assets/css/admin-settings.css;[新增] = 库首次提供。
4.1 pvq-ui.css(base,全场景 enqueue)
- 设计令牌:
:root全套--pvq-*(以 wolaiadmin-settings.css:11-62的:root为基线,原样保留命名)。 - 按钮 [提取]:
.pvq-btn.pvq-btn--primary.pvq-btn--secondary.pvq-btn--danger.pvq-btn--warning.pvq-btn-group - 卡片 [提取]:
.pvq-card.pvq-card__header.pvq-card__icon.pvq-card__icon--{primary,success,warning,info,danger}.pvq-card__title.pvq-card__desc.pvq-card__action - 表单 [提取]:
.pvq-field.pvq-field__label.pvq-field__help.pvq-input.pvq-input__wrap.pvq-input__wrap--has-icon.pvq-input__icon.pvq-input__toggle - 开关 [提取]:
.pvq-switch.pvq-switch--active.pvq-switch-row.pvq-switch-row__label.pvq-switch-row__desc - 状态/徽标 [提取+新增]:
.pvq-status.pvq-status--{success,warning,error}.pvq-status__dot.pvq-badge[新增] - 其它 [提取]:
.pvq-divider.pvq-spinner.pvq-help.pvq-help__icon.pvq-help__title.pvq-help__text.pvq-banner.pvq-banner--{success,danger,warning,info}.pvq-alert.pvq-alert--{success,error,loading}.pvq-stat-grid.pvq-stat.pvq-stat__value.pvq-stat__label.pvq-meta-list.pvq-meta-list__row.pvq-meta-list__key.pvq-meta-list__value.pvq-meta-list__value--{ok,bad}[新增 meta-list] - 动画:全部
@keyframes保留pvq-前缀(含.pvq-spin/.pvq-pulse/.pvq-shimmer等现有动画)。 - 浮层 Popover [新增](v1.3.1,
experimental,回流自 pvq-weixinyuedu):.pvq-popover.pvq-popover__body.pvq-popover__foot.pvq-popover__arrow,修饰符--open(打开态,JS 加)--above(JS 判定的上方位置)。position:fixed+getBoundingClientRect()实时定位(不依赖祖先position)、视口边缘自动翻转与双向夹取;布局令牌--pvq-popover-width/--pvq-popover-z。落库决策与契约见《PVQ-UI回流落库-Popover锚点浮层.md》。
4.2 pvq-ui-admin.css(后台 enqueue)
- 设置页骨架 [提取]:
.pvq-settings.pvq-settings__{header,logo,title-group,title,subtitle,version-badge,footer,footer-info,footer-links,footer-link,footer-link--disabled} - 选项卡 + 磁吸滑块 [提取]:
.pvq-tabs.pvq-tabs__slider.pvq-tab.pvq-tab--active.pvq-tab__icon.pvq-tab-content.pvq-tab-content--active - 滑块 + 数字 [提取]:
.pvq-range.pvq-range__group.pvq-range__value.pvq-range__labels - 系统信息 [提取]:
.pvq-meta-list(见 4.1)
4.3 pvq-ui-editor.css(块编辑器 enqueue)
- 通用块骨架 [提取自 wolai 专有抽象]:
.pvq-block-placeholder.pvq-block-loading.pvq-block-empty.pvq-block-preview.pvq-block-frame
4.4 pvq-ui-frontend.css(前端 enqueue)
- 通用内容组件 [提取自 wolai 专有抽象]:
.pvq-callout.pvq-callout__{icon,content}.pvq-quote.pvq-prose
不进库、留在 wolai-sync 的强绑定笔记数据模型的样式:
.pvq-wolai-text/-heading/-code-block/-todo/-toggle/-image/-video/-bookmark/-table等,但改用--pvq-*令牌保证风格一致。.pvq-token-info、.pvq-detect-bar、.pvq-status-available/-unavailable等 wolai 专有类也留在 wolai。
5. 设计令牌(节选,命名保持不变)
主色 --pvq-primary 系列、语义色 --pvq-{success,danger,warning,info} 及 -light、中性色 --pvq-{bg,surface,border,text,text-secondary,text-muted}、圆角 --pvq-radius{,-sm,-lg}、阴影 --pvq-shadow{,-sm,-md,-lg,-primary}、缓动 --pvq-ease*、--pvq-transition*。完整清单以 wolai admin-settings.css:11-62 为基线,由库统一维护。
6. BEM 命名规范与旧→新映射(修正版)
重要:旧类多为双类组合(如
pvq-btn pvq-btn-primary),并非单类,迁移时勿当单类搜索替换。完整映射表写入本文档附录,供迁移对照。
| 旧(真实代码) | 新(pvq-ui BEM) | 备注 |
|---|---|---|
pvq-btn + pvq-btn-primary |
pvq-btn + pvq-btn--primary |
双类 |
pvq-btn-secondary / pvq-btn-danger / pvq-btn-warning |
pvq-btn--secondary / pvq-btn--danger / pvq-btn--warning |
|
pvq-card-icon + primary 等 |
pvq-card__icon + pvq-card__icon--primary |
双类 |
pvq-label |
pvq-field__label |
|
pvq-field-help |
pvq-field__help |
草案误写为 .pvq-label-hint |
pvq-input-wrap + has-icon |
pvq-input__wrap + pvq-input__wrap--has-icon |
双类 |
pvq-switch + active |
pvq-switch + pvq-switch--active |
双类 |
pvq-switch-label / pvq-switch-desc |
pvq-switch-row__label / pvq-switch-row__desc |
|
pvq-status-indicator + success/warning/error |
pvq-status + pvq-status--success/warning/error |
|
pvq-connection-status + connected/disconnected/unconfigured |
pvq-banner + pvq-banner--success/danger/warning |
修饰符值需变更 |
pvq-test-result + .show + .success/.error/.loading |
pvq-alert + 显隐类 + pvq-alert--success/error/loading |
需新增显隐类 |
pvq-cache-stats / pvq-cache-stat / pvq-cache-stat-value / pvq-cache-stat-label |
pvq-stat-grid / pvq-stat / pvq-stat__value / pvq-stat__label |
中间层 pvq-cache-stat 勿漏 |
pvq-help-card (+ -inner / -icon / -title / -text) |
pvq-help (+ __icon / __title / __text) |
|
pvq-settings-app / pvq-settings-header / pvq-settings-logo / pvq-settings-title / pvq-settings-subtitle / pvq-settings-footer / pvq-footer-link / pvq-footer-link--disabled |
pvq-settings / pvq-settings__header / __logo / __title / __subtitle / __footer / __footer-link / __footer-link--disabled |
|
pvq-tab-slider / pvq-tab + active / pvq-tab-content + active |
pvq-tabs__slider / pvq-tab + pvq-tab--active / pvq-tab-content + pvq-tab-content--active |
双类 |
pvq-range-group / pvq-range / pvq-range-value / pvq-range-labels |
pvq-range__group / pvq-range / pvq-range__value / pvq-range__labels |
|
pvq-system-info / pvq-system-info-row |
pvq-meta-list / pvq-meta-list__row |
|
pvq-wolai-callout (+ -icon / -content) |
pvq-callout (+ __icon / __content) |
进 frontend |
pvq-wolai-sync-placeholder |
pvq-block-placeholder |
进 editor |
7. JS 交互(pvq-ui.js,原生 JS + 事件委托)
- tab 切换 + 磁吸滑块:委托
.pvq-tab点击 → 切.pvq-tab--active+.pvq-tab-content--active+ 移动.pvq-tabs__slider。 - switch 开关:委托
.pvq-switch点击切.pvq-switch--active,并dispatchEvent自定义事件pvq-switch:change(detail 含 checked / data-target),插件监听后自行同步隐藏域与提交。 - range 拖动:同步
.pvq-range__value。 - popover 开合与定位(v1.3.1):
initPopovers()(并入initAll)接管声明式锚点[data-pvq-popover="<浮层 id>"](值空回退aria-describedby,目标须为.pvq-popover),命令式走PVQUI.popover(anchor, opts)。按getBoundingClientRect()实时算坐标(position:fixed,不依赖祖先position),含边缘自动翻转(--above)与双向夹取、桌面悬停延时关闭、触屏点按开合、Escape(焦点交还锚点)、外部点击、滚动(捕获阶段)与缩放重定位;幂等(同一浮层只初始化一次,document/window 级监听只绑一次);派发pvq-popover:open/pvq-popover:close。
迁移关键(草案低估的部分):现状 wolai 后台用 jQuery + 大量 inline
onclick="pvqWolaiSwitchTab('general')"/onkeydown=...(class-pvq-wolai-sync-settings.php:104,275,490)。迁移到pvq-ui.js必须剥离所有 inline handler,改为data-*属性 + 委托监听;switch 的「视觉 toggle」与「表单值同步」要重新划边界(库管视觉 + 派发事件,插件管隐藏域)。否则迁移后 JS 报错。
8. 消费方接入(PHP 样板 = 复制 loader + 一行调用)
// 每个插件只需:复制 pvq-ui-loader.php 到 includes/,然后:
require_once __DIR__ . '/pvq-ui-loader.php';
PVQ_UI_Loader::enqueue( array( 'admin' ) ); // 后台场景
// 插件自身 CSS:声明依赖 pvq-ui / pvq-ui-<场景>
wp_enqueue_style( 'my-plugin-admin', ..., array( 'pvq-ui', 'pvq-ui-admin' ), $ver );
相比原草案 §8:不再要求每个插件内联重复注册与 override 逻辑,全部收敛进 pvq-ui-loader.php。
9. 迁移步骤(以 wolai-sync 先行)
pvq-ui仓库完成 base / admin / editor / frontend +pvq-ui.js+pvq-ui-loader.php,构建上传 CDN 固定路径。- wolai 三个 enqueue 点(settings admin / frontend / editor)改为复制
pvq-ui-loader.php并调用PVQ_UI_Loader::enqueue();自身 CSS 加pvq-ui/pvq-ui-admin依赖。 - 删除
admin-settings.css中已进库的通用组件 +:root令牌;保留 wolai 专有类(.pvq-token-info、.pvq-wolai-*等)。 - 设置页 HTML/PHP 旧 class 全量改新 BEM 名(对照 §6 映射表);并剥离所有 inline
onclick/onkeydown(§7)。 frontend.css/editor.css中 wolai 专有.pvq-wolai-*保留,硬编码颜色改为--pvq-*令牌;callout / 块骨架等抽象部分移交pvq-ui。- 迁移完整性校验:grep 确认已进库的类(如
.pvq-card、.pvq-btn--primary)在 wolai 自有 CSS/HTML 中零残留,避免与库双定义冲突。 - 同步 docs / readme.md / CHANGELOG(按《PVQ-UI项目规则.md》§1.3 版本七处同步)。
- threads-sync 后续按同流程迁移(注意其
.pvq-ts-*命名空间需整体重命名为.pvq-*)。
10. 新插件接入清单
- 复制
pvq-ui-loader.php到插件includes/。 - 调用
PVQ_UI_Loader::enqueue( array( 'admin' / 'editor' / 'frontend' ) )。 - 自身 CSS
wp_enqueue_style(..., ['pvq-ui','pvq-ui-<场景>'])。 - 只写插件专有样式,通用组件直接用
.pvq-*BEM 类。 - 不自带任何通用组件副本(纯 CDN 引用;内网站点可常量覆盖为本地副本)。
11. 风险与权衡
- CDN 单点:UI(含 JS 交互)CDN 挂 → 设置页布局/交互崩。缓解:复用已在用域名
cdn-buke.pvq.ink;JS 交互保留 CSS 兜底(无 JS 也能看);内网站点用PVQ_UI_URL常量覆盖为本地副本。 - 版本冲突:靠 §3.3 loader 内置 override 收敛(幂等),确保全站同一版本。
- FA 依赖:组件视觉依赖 FontAwesome,loader 一并保证
font-awesome句柄已注册。 - 重命名成本:BEM 重命名需批量改所有插件 DOM 引用 + 文档/演示 HTML 硬编码类;一次性工程,靠 §6 映射表 + §9 第 6 步 grep 校验降低出错率。
- 命名空间残留:wolai 后台通用类现用
.pvq-*前缀,迁移须确保彻底删除,否则与库双定义。
12. 文档同步(铁律)
本方案定稿后写入 doc/开发文档/PVQ-UI组件库开发方案.md(即本文件,作为唯一真源)。
后续:
pvq-ui仓库内维护doc/模块文档/设计令牌与组件清单.md(令牌 + 组件 API)。- 更新现有文档(如
数据库块编辑器工具栏和FontAwesome方案.md、各插件readme.md/CHANGELOG)。 - 迁移盲区提醒:
docs/演示/*.html中大量硬编码旧 handle / CDN / 设置项,须随迁移一并更新。 - 遵循项目铁律:先文档 → 再代码 → 最后同步 CHANGELOG 与 readme(除非用户要求不更新版本号)。
13. 关联文档(单一真源拆分)
本方案为总纲,下列文档与之互为引用、共同构成唯一真源:
组件提取对照表.md:三套现有组件(wolai / pvq-wp / threads)→ 库单一实现的逐组件映射与择优;迁移实施直接对照。库演进治理方案.md:库如何随插件开发持续演进——版本化 CDN、文档驱动增量贡献、组件分级(stable/experimental)、分层文件、防回潮。PVQ-UI项目规则.md:最高优先级权威规则,收敛散落各处的铁律(文档/单一真源/命名/版本化/分级/分层/接入/纪律);凡与本文冲突以它为准。PVQ-UI组件库调用手册.md:插件开发者实操指南——复制 loader、一行 enqueue、直接写.pvq-*类、场景对照、常用组件速查、内网覆盖、迁移步骤、自检清单。
版本化细化:§3.1 的 CDN 路径已含
<版本>,各插件通过PVQ_UI_Loader::enqueue( $scenes, $version )锁定版本;§11 的 override 收敛默认只解决"同版本冲突",不强制跨版本降级——从而支持"存量不动、新插件用最新"的渐进统一,匹配"随开发慢慢完善"的诉求。