# plugin-system 规范 ## 目的 定义 TvT.js 的插件契约:包括目录布局、路由发现规则、元数据约定、资源归属、依赖声明方式,以及跨插件复用的基本模式。 ## 职责边界 ### 本规范覆盖 - `src/plugins/` 下的插件源码结构 - `public/plugins/` 下的静态资源结构 - 基于 `src/plugins/**/pages/**/*.vue` 的路由发现机制 - 当前支持的页面嵌套层级 - `config.js` 作为插件元数据源的角色 - `preview` 与 `child[].preview` 的使用约定 - `require` 依赖声明的语义 - 通过 `index.js` 暴露共享能力 - 基于 `PLS` 别名的跨插件导入模式 - 开源仓库插件条目与插件市场源码交付的边界 ### 本规范不覆盖 - 预览中心的分类展示逻辑与计数逻辑 - 运行模式切换细节 - 宿主应用或外部容器的集成行为 - 单个案例页面的内部实现细节 ## 主要代码依据 - `src/app.jsx` - `src/common/utils.js` - `src/common/copySelectedPublicDirsPlugin.js` - `pluginMaker/index.cjs` - `src/components/forPreview/cardList.vue` - `src/components/forPreview/oneImageQr.vue` - `src/components/forPreview/suspenseLayout.vue` - `src/plugins/basic/config.js` - `src/plugins/goView/config.js` - `src/plugins/qiankunTvt/config.js` - `src/plugins/uniAppView/config.js` ## 要求 ### Requirement: 插件命名空间一致性 TvT.js 插件 SHALL 使用单一插件标识作为主命名空间,并在源码目录、公共资源目录、路由前缀和配置元数据中保持一致。默认情况下,该插件标识应与 `src/plugins/` 的目录名一致;`config.js` 中的 `name` 也 SHALL 与该插件标识保持一致。 #### Scenario: 标准插件命名空间一致 - GIVEN 一个目录为 `src/plugins/water` 的插件 - WHEN 系统发现其页面和配置 - THEN 该插件的公共资源命名空间应位于 `public/plugins/water` - AND 该插件的页面路由前缀应位于 `/plugins/water/...` - AND `src/plugins/water/config.js` 中的 `name` 应为 `water` #### Scenario: 维护者新增插件 - GIVEN 维护者通过脚手架或手工方式新建一个插件 - WHEN 该插件被纳入 TvT.js 插件系统 - THEN 维护者 SHALL 先确定唯一插件标识 - AND 后续目录、配置、资源、路由 SHALL 统一使用该标识 ### Requirement: 插件页面发现与路由层级 可被 TvT.js 自动发现并注册路由的插件页面 SHALL 放在 `src/plugins//pages/` 下,且仅允许两种受支持的页面层级:`pages/.vue` 与 `pages//.vue`。维护者 SHALL 不依赖更深层级的页面目录作为正式路由契约。 #### Scenario: 一级页面路由 - GIVEN 存在页面文件 `src/plugins/foo/pages/bar.vue` - WHEN 预览类模式启用插件路由发现 - THEN 系统 SHALL 为其注册路由 `/plugins/foo/bar` #### Scenario: 二级页面路由 - GIVEN 存在页面文件 `src/plugins/basic/pages/base/theBasic.vue` - WHEN 预览类模式启用插件路由发现 - THEN 系统 SHALL 为其注册路由 `/plugins/basic/base/theBasic` #### Scenario: 不受支持的更深层级 - GIVEN 维护者尝试使用 `src/plugins/foo/pages/a/b/c.vue` - WHEN 该页面被纳入插件设计 - THEN 该页面层级 SHALL 视为超出当前正式插件路由契约 - AND 维护者 SHALL 不将其作为受支持能力写入规范或技能 ### Requirement: config.js 最小强制字段 每个正式插件的 `config.js` SHALL 至少包含以下强制字段:`name`、`title`、`intro`、`version`、`author`、`website`、`state`、`require`,以及一个展示入口字段:标准插件使用 `preview`,分组插件使用 `child`。当前仓库中的正式插件配置均满足这组最小字段约束,后续插件也 SHALL 遵循这组下限。 #### Scenario: 标准插件的最小字段集合 - GIVEN 一个普通插件采用平铺展示 - WHEN 维护者编写其 `config.js` - THEN 该配置 SHALL 包含 `name`、`title`、`intro`、`version`、`author`、`website`、`state`、`require`、`preview` #### Scenario: basic 分组插件的最小字段集合 - GIVEN 当前唯一正式分组插件 `basic` - WHEN 维护者维护其 `config.js` - THEN 该配置 SHALL 包含 `name`、`title`、`intro`、`version`、`author`、`website`、`state`、`require`、`child` - AND 不要求同时再声明顶层 `preview` ### Requirement: config.js 推荐与条件字段 除最小强制字段外,`creatTime`、`updateTime` 应作为推荐字段保留;`tvtstore` 仅在插件需要被归入插件市场或区域场景编辑器分类时才作为条件字段出现。未进入这两类分类的插件 MAY 不声明 `tvtstore`。 #### Scenario: 常规案例插件 - GIVEN 一个普通案例型插件 - WHEN 其不需要进入插件市场或区域场景编辑器分类 - THEN 该插件 MAY 不声明 `tvtstore` #### Scenario: 插件市场或区域类插件 - GIVEN 一个插件需要在预览中心按插件市场或区域场景编辑器类别展示 - WHEN 维护者定义其展示分类 - THEN 该插件 SHALL 通过 `tvtstore` 等分类相关字段进入对应类别 ### Requirement: 分组插件支持范围 当前正式受支持的分组型插件 SHALL 仅有 `basic`。其他插件 SHALL 默认采用标准平铺插件模式,不应自行扩展为新的分组型插件规范;若未来确需新增分组型插件,应先更新规范再落地实现。 #### Scenario: 现有分组支持范围 - GIVEN 当前仓库中的插件集合 - WHEN 维护者定义分组型插件支持范围 - THEN 仅 `basic` SHALL 被视为正式分组型插件 #### Scenario: 新插件默认形态 - GIVEN 维护者新增一个非 `basic` 插件 - WHEN 未经过额外规范扩展 - THEN 该插件 SHALL 默认使用标准插件形态 - AND 不应直接引入新的 `child` 分组契约 ### Requirement: 插件元数据源 每个被插件系统识别的插件 SHALL 在 `src/plugins//config.js` 中定义元数据。面向预览中心展示的标准插件 SHALL 提供 `preview` 数组;面向分组展示的插件 SHALL 提供 `child[].preview`。插件元数据至少 SHALL 明确插件身份与展示入口,不得将展示入口仅散落在页面文件中而缺失 `config.js`。 #### Scenario: 标准插件使用 preview - GIVEN 一个普通插件采用平铺展示 - WHEN 预览中心读取该插件配置 - THEN 该插件的 `config.js` SHALL 提供 `preview` - AND 对于指向本地页面的条目,`preview[].name` 应与对应页面文件名保持一致 #### Scenario: 分组插件使用 child - GIVEN 一个类似 `basic` 的分组型插件 - WHEN 预览中心读取该插件配置 - THEN 该插件的 `config.js` SHALL 提供 `child` - AND 每个子分组的展示入口 SHALL 位于对应的 `child[].preview` #### Scenario: 外链或远程预览条目 - GIVEN 某个 `preview` 条目通过 `url` 直接跳转到外链或远程页面 - WHEN 维护者配置该条目 - THEN 该条目 MAY 不对应本地 `pages/*.vue` 文件 - AND 该条目仍 SHALL 保持稳定的 `name` 以供菜单、哈希和二维码等预览行为使用 ### Requirement: preview 条目最小字段与运行时扩展 每个 `preview` 或 `child[].preview` 条目 SHALL 至少包含 `src`、`type`、`name`、`title`。当前预览渲染层正式支持 `img`、`text`、`video` 三类 `type`;`url`、`disableFPSGraph`、`disableSrcBtn`、`referenceSource` 作为可选运行时扩展字段 MAY 出现,并分别影响跳转目标、调试面板显示与参考来源展示。 #### Scenario: 本地页面驱动的预览条目 - GIVEN 一个普通案例页面需要进入预览中心 - WHEN 维护者编写对应 `preview` 条目 - THEN 该条目 SHALL 至少声明 `src`、`type`、`name`、`title` - AND 若未声明 `url`,该条目 SHOULD 对应本地受支持的插件页面路由 #### Scenario: 带运行时扩展字段的预览条目 - GIVEN 某个预览条目需要跳转外链、隐藏调试按钮或展示参考出处 - WHEN 维护者编写该条目 - THEN 该条目 MAY 使用 `url`、`disableFPSGraph`、`disableSrcBtn`、`referenceSource` - AND 这些字段 SHALL 被视为正式预览契约的一部分,而不是临时展示参数 ### Requirement: 插件资源归属 插件的公共静态资源 SHALL 归属在 `public/plugins/` 名下,包括但不限于预览图、模型、纹理、配置文件、音视频和运行时加载资源。插件实现可以按周边代码选择 `plugins/...`、`./plugins/...`、`/plugins/...` 或完整 `https://...` 地址的访问形式,但 SHALL 不将插件公共资源无序散落到其他插件命名空间中。 #### Scenario: 预览图归属到插件命名空间 - GIVEN 一个插件需要在预览中心显示缩略图 - WHEN 维护者新增预览图片 - THEN 该图片 SHALL 放在 `public/plugins//preview/` 或其下级目录 #### Scenario: 场景资源与模型归属 - GIVEN 一个插件需要加载模型、贴图或配置 JSON - WHEN 维护者准备公共资源 - THEN 这些资源 SHALL 优先放在 `public/plugins//...` - AND 不应默认放到其他插件的公共目录中复用 #### Scenario: 远程托管资源或外链预览 - GIVEN 某个预览图或跳转目标由外部站点托管 - WHEN 维护者配置该资源或预览条目 - THEN 该条目 MAY 使用完整 `https://...` 地址 - AND 这不改变该插件本地源码与公共资源仍以 `` 命名空间归属的约定 ### Requirement: 插件依赖声明 当一个插件在运行期、预览期或单插件构建期依赖其他插件资源或共享能力时,该插件 SHALL 在 `config.require` 中显式声明依赖项。非单插件模式下,系统 SHALL 对声明依赖进行存在性检查;单插件构建时,系统 SHALL 基于 `config.require` 保留目标插件及其依赖插件的公共资源目录。 #### Scenario: 本地缺失依赖插件 - GIVEN 某插件在 `config.require` 中声明依赖 `floor` - WHEN 系统在非单插件模式下加载插件配置 - THEN 系统 SHALL 检查本地是否存在 `floor` 插件配置 - AND 当依赖不存在时,系统 SHALL 给出缺失提示并指向插件市场安装入口 #### Scenario: 单插件构建保留依赖资源 - GIVEN 当前单插件构建目标为 `qiankunTvt` - AND `qiankunTvt` 在 `config.require` 中声明了 `floor` 与 `medical` - WHEN 运行单插件构建流程 - THEN 构建输出 SHALL 保留 `qiankunTvt`、`floor`、`medical` 对应的公共资源目录 ### Requirement: 共享导出与跨插件复用 当插件需要向其他插件暴露可复用组件、工具或组合能力时,该插件 SHALL 通过 `src/plugins//index.js` 作为公共导出面,并通过 `PLS/` 被其他插件引用。维护者 SHALL 避免把私有实现细节作为默认跨插件导入路径。 #### Scenario: 导出公共能力 - GIVEN 插件 `floor` 需要暴露可被其他插件复用的能力 - WHEN 维护者设计该插件的公共接口 - THEN 这些能力 SHALL 从 `src/plugins/floor/index.js` 暴露 - AND 使用方插件 SHALL 优先通过 `PLS/floor` 导入 ### Requirement: 插件市场与开源仓库边界 TvT.js 的开源仓库插件清单 SHALL 与插件市场中的源码交付能力解耦。开源仓库 MAY 仅保留某些市场插件的配置、预览资源或接入点,而不直接包含其完整源码实现;此类插件应被视为“可预览、可登记、可安装”的插件条目,而不是“源码已随仓库分发”的插件。此类条目 SHALL 被视为可扩展集合,而不是单一特例。 #### Scenario: 市场插件的授权安装 - GIVEN 某插件源码通过插件市场授权交付 - WHEN 维护者将插件 ZIP 放入 `pluginMaker/install/` 并执行安装命令 - THEN 该插件 SHALL 通过既有插件安装流程接入本地仓库 - AND 其源码是否进入仓库,应以授权交付与安装结果为准,而不是以预览清单是否存在为准