二、核心分层设计(对标阿里 Fusion / 字节 Semi / 腾讯 TDesign)
L0 — Design Token(设计令牌层)
职责:统一视觉语言,与 UI 框架解耦
@cmc/design-tokens
├── colors.css # CSS Variables
├── spacing.css
├── typography.css
├── shadows.css
├── tokens.json # Style Dictionary 源文件(可生成多端产物)
└── index.ts # JS/TS 常量导出
- 用 Style Dictionary 管理,一份源数据 → 输出 CSS Variables / SCSS / TS / Figma Plugin
- Element Plus 主题通过覆盖
--el-*变量接入,各子应用无需各自配置 - 由基座注入全局 CSS Variables,子应用继承
L1 — 基础增强组件层
职责:Element Plus 二次封装 + 原子级通用组件
@cmc/ui
├── CmcTable/ # 增强表格(列配置化、分页内聚、虚拟滚动)
├── CmcForm/ # 配置化表单(JSON Schema 驱动)
├── CmcUpload/ # 统一上传(OSS/本地/断点续传)
├── CmcDialog/ # 增强弹窗(拖拽/全屏/promise化)
├── CmcSearch/ # 搜索栏(折叠/展开/记忆)
├── CmcDescription/ # 详情描述列表
├── CmcPermission/ # 权限指令/组件
└── ...
关键设计原则:
- Props 透传:
v-bind="$attrs"全量透传 Element Plus 原生属性,不做阉割 - 插槽穿透:暴露原组件所有 slot,保证可扩展性
- 类型完备:每个组件导出
Props / Emits / Expose类型定义 - 无业务逻辑:纯 UI 层,不含接口调用
L2 — 业务组件层
职责:跨系统复用的业务功能单元
@cmc/biz-components
├── ShipmentSelector/ # 船期选择器
├── PortPicker/ # 港口选择器(含模糊搜索+常用)
├── CustomerSearch/ # 客户搜索组件
├── ApprovalFlow/ # 审批流展示
├── FilePreview/ # 统一文件预览
└── ...
- 允许内置接口调用,但通过 依赖注入 抽象 API 层(不硬编码域名/路径)
- 通过
provide/inject或 props 传入 API adapter
L3 — Pro 区块/模板层
职责:页面级可复用布局模式
@cmc/pro-components
├── ProTable/ # 搜索 + 表格 + 分页 + 工具栏 一体化
├── ProForm/ # 分步表单 / 弹窗表单 / 抽屉表单
├── ProLayout/ # 标准页面布局框架
├── ProDetail/ # 标准详情页
└── CrudTemplate/ # CRUD 页面生成器
三、微前端共享机制(核心难点)
方案:Module Federation + npm 包双轨制
┌──────────────────────────────────────────────────────┐
│ 分发策略矩阵 │
├──────────────┬──────────────┬────────────────────────┤
│ 组件层级 │ 分发方式 │ 理由 │
├──────────────┼──────────────┼────────────────────────┤
│ L0 Token │ npm 包 │ 构建时确定,极少变更 │
│ L1 基础组件 │ npm 包 │ 稳定,需要类型推导 │
│ L2 业务组件 │ MF Remote │ 变更频繁,需要热更新 │
│ L3 Pro 区块 │ npm 包 │ 需要 Tree-shaking │
├──────────────┼──────────────┼────────────────────────┤
│ 紧急热修复 │ MF Remote │ 一次发布,全部生效 │
└──────────────┴──────────────┴────────────────────────┘
Module Federation 关键架构
┌───────────────────────┐
│ Component Service │
│ (独立部署的组件服务) │
│ │
│ remoteEntry.js │
│ ├── CmcUpload │
│ ├── ApprovalFlow │
│ └── ShipmentSelector │
└───────────┬───────────┘
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐
│ 供应商门户 │ │ 运营后台 │ │ 客户门户 │
│ (Consumer) │ │ (Consumer) │ │ (Consumer) │
└────────────┘ └────────────┘ └────────────┘
Vite 集成配置(@module-federation/vite):
// Component Service(Remote 端)
// vite.config.ts
import { federation } from '@module-federation/vite'
export default defineConfig({
plugins: [
federation({
name: 'cmc_shared_ui',
filename: 'remoteEntry.js',
exposes: {
'./CmcUpload': './src/components/CmcUpload/index.vue',
'./ApprovalFlow': './src/components/ApprovalFlow/index.vue',
},
shared: {
vue: { singleton: true },
'element-plus': { singleton: true },
pinia: { singleton: true },
},
}),
],
})
// 子应用(Consumer 端)
// vite.config.ts
federation({
name: 'supplier_portal',
remotes: {
cmc_shared_ui: {
type: 'module',
name: 'cmc_shared_ui',
// 通过 manifest 实现版本管理 + 灰度
entry: 'https://static.cmclink.com/shared-ui/remoteEntry.js',
},
},
shared: {
vue: { singleton: true },
'element-plus': { singleton: true },
},
})
降级兜底策略(生产必备)
// useRemoteComponent.ts — 加载远程组件,失败回退本地
import { defineAsyncComponent, h } from 'vue'
export function useRemoteComponent(
remoteName: string,
localFallback: () => Promise<any>,
) {
return defineAsyncComponent({
loader: async () => {
try {
const module = await import(/* @vite-ignore */ `cmc_shared_ui/${remoteName}`)
return module.default || module
} catch (e) {
console.warn(`[MF] Remote ${remoteName} 加载失败,回退本地版本`, e)
const fallback = await localFallback()
return fallback.default || fallback
}
},
loadingComponent: () => h('div', { class: 'animate-pulse h-8 bg-gray-100 rounded' }),
timeout: 5000,
})
}
// 使用
const CmcUpload = useRemoteComponent(
'CmcUpload',
() => import('@cmc/ui/CmcUpload'), // npm 包兜底
)
四、版本治理与自动升级
┌───────────┐ push ┌───────────┐ publish ┌──────────┐
│ @cmc/ui │ ──────────▶ │ CI/CD │ ──────────▶ │ 私有 npm │
│ 组件仓库 │ │ changesets │ │ Registry │
└───────────┘ └─────┬─────┘ └────┬─────┘
│ │
│ trigger │ Renovate Bot
▼ ▼
┌─────────────┐ ┌──────────────┐
│ Storybook │ │ 各子应用仓库 │
│ 自动部署 │ │ 自动提 PR │
└─────────────┘ │ patch 自动合并 │
│ minor 人工审核 │
└──────────────┘
关键配置:
- changesets:语义化版本 + 自动 CHANGELOG
- Renovate Bot:每日扫描依赖更新,自动 PR + 自动跑 CI
- patch 自动合并:配置 Renovate
automerge: truefor patch - minor/major:需人工审核 PR 后合并
五、质量保障体系
| 环节 | 工具 | 说明 |
|---|---|---|
| 单元测试 | Vitest + Vue Test Utils | 每个 L1/L2 组件 ≥80% 覆盖率 |
| 视觉回归 | Chromatic / Percy | Storybook 截图对比,防止样式劣化 |
| 文档验收 | Storybook / Histoire | 每个组件必须有在线可交互 Demo |
| 类型检查 | vue-tsc --noEmit | CI 卡口,类型不通过不允许发布 |
| Bundle 分析 | rollup-plugin-visualizer | 防止包体积膨胀 |
| API 兼容性 | api-extractor | 导出 API 变更自动检测 + 审批 |
六、仓库结构建议(pnpm workspace monorepo)
cmc-platform-ui/
├── pnpm-workspace.yaml
├── turbo.json # Turborepo 任务编排
├── .changeset/ # changesets 配置
│
├── packages/
│ ├── design-tokens/ # @cmc/design-tokens (L0)
│ │ ├── tokens.json
│ │ └── package.json
│ │
│ ├── ui/ # @cmc/ui (L1)
│ │ ├── src/
│ │ │ ├── CmcTable/
│ │ │ ├── CmcForm/
│ │ │ └── index.ts
│ │ ├── package.json
│ │ └── tsup.config.ts
│ │
│ ├── biz-components/ # @cmc/biz-components (L2)
│ │ ├── src/
│ │ └── package.json
│ │
│ ├── pro-components/ # @cmc/pro-components (L3)
│ │ ├── src/
│ │ └── package.json
│ │
│ └── shared/ # @cmc/shared (工具函数/类型/常量)
│ ├── src/
│ └── package.json
│
├── apps/
│ ├── storybook/ # 组件文档站
│ └── mf-host/ # Module Federation 组件服务
│ ├── src/
│ └── vite.config.ts
│
└── configs/ # 共享配置
├── eslint-config/
├── tsconfig/
└── tailwind-config/
七、与大厂方案对标
| 维度 | 阿里(Fusion/IceWork) | 字节(Semi/Garfish) | 本方案 |
|---|---|---|---|
| 设计令牌 | Fusion Token | Semi Token | @cmc/design-tokens |
| 基础组件 | Fusion Next | Semi Design | @cmc/ui |
| 业务组件 | 金融云物料 | 内部 Biz | @cmc/biz-components |
| 区块模板 | IceWork 物料 | Semi Pro | @cmc/pro-components |
| 微前端 | qiankun | Garfish | Module Federation |
| 共享策略 | npm + CDN | npm + MF | npm + MF 双轨 |
| 自动升级 | 内部机器人 | 内部机器人 | Renovate Bot |
| 文档 | Fusion Site | Semi Site | Storybook/Histoire |
八、落地路径(推荐 3 个阶段)
Phase 1(1~2 周):基座搭建
- 建 monorepo、配置 pnpm workspace + Turborepo
- 迁移 5~10 个最高频 L1 组件
- 接通 changesets + 私有 npm 发布
Phase 2(3~4 周):生态完善
- Storybook 文档站上线
- 接入 Renovate Bot 自动升级
- 各子应用替换本地 copy → npm 依赖
Phase 3(5~8 周):高阶能力
- L2 业务组件接入 Module Federation
- 视觉回归测试
- ProTable/ProForm 等 L3 组件建设