本次把「一个报表项目」从单画布升级为多页面容器。项目仍然只有一个 projectId、一个发布地址、一个后端 componentData 字段;页面是项目 JSON 内部的逻辑单位。
ReportProject
└── componentData
├── homePageId
├── activePageId
├── pages[]
│ ├── 首页
│ │ ├── editCanvasConfig
│ │ ├── requestGlobalConfig
│ │ └── componentList
│ └── 区域详情
│ ├── editCanvasConfig
│ ├── requestGlobalConfig
│ └── componentList
└── sharedRequestGlobalConfig
export type ReportPageTransition = 'none' | 'fade' | 'slide-left' | 'slide-right' | 'zoom'
export interface ReportCanvasPage {
id: string
name: string
sort: number
editCanvasConfig: EditCanvasConfigType
requestGlobalConfig: RequestGlobalConfigType
componentList: Array<CreateComponentType | CreateComponentGroupType>
}
export interface ReportMultiPageStorage {
version: 2
homePageId: string
activePageId: string
pageTransition?: ReportPageTransition
pages: ReportCanvasPage[]
sharedRequestGlobalConfig?: Partial<RequestGlobalConfigType>
}
export type ReportProjectStorage = ChartEditStorage | ReportMultiPageStorage
集中新增协议工具,避免各入口散落判断:
forge-report-ui/src/utils/reportPages.ts
关键函数:
export function isMultiPageStorage(storage: unknown): storage is ReportMultiPageStorage
export function normalizeProjectStorage(storage: unknown, fallbackName?: string): ReportMultiPageStorage
export function createDefaultPage(name?: string): ReportCanvasPage
export function extractPageStorage(project: ReportMultiPageStorage, pageId?: string): ChartEditStorage
export function updatePageStorage(project: ReportMultiPageStorage, pageId: string, storage: ChartEditStorage): ReportMultiPageStorage
export function removeInvalidPageActions(project: ReportMultiPageStorage, removedPageId: string): ReportMultiPageStorage
保留 chartEditStore 作为当前画布编辑 store,新增多页面管理字段和动作。
state: {
projectPages: [],
activePageId: '',
homePageId: '',
pageTransition: 'fade',
runtimePageContext: {}
}
关键动作:
loadProjectStorage(storage: unknown): Promise<void>
getProjectStorageInfo(): ReportMultiPageStorage
flushCurrentPage(): void
switchPage(pageId: string): Promise<void>
createPage(copyFromPageId?: string): Promise<string>
renamePage(pageId: string, name: string): void
deletePage(pageId: string): void
duplicatePage(pageId: string): Promise<string>
setHomePage(pageId: string): void
setRuntimePageContext(context: Record<string, any>): void
原则:
editCanvasConfig + requestGlobalConfig + componentList。pages。getStorageInfo() 可保留给单页兼容,但保存项目必须使用 getProjectStorageInfo()。首期建议新增一个轻量页面管理面板,不做 Figma 连线原型。
位置建议:
能力:
预览入口:
/chart/preview/:projectId
/chart/preview/:projectId?pageId=page-region
运行时状态:
activePageId
runtimePageContext
pageTransition
预览流程:
读取 componentData
↓
normalizeProjectStorage()
↓
选择 query.pageId 或 homePageId
↓
extractPageStorage()
↓
回填 chartEditStore
↓
渲染 PreviewRenderList
页面跳转流程:
组件触发 click
↓
读取 component.events.actions
↓
resolveDrillParams()
↓
flush/更新 runtimePageContext
↓
switchPreviewPage(targetPageId)
↓
过渡动画 + 重新初始化数据池
新增结构化动作配置,与现有 JS 基础事件并存。
export interface ComponentAction {
id: string
trigger: 'click' | 'dblclick'
type: 'goPage'
targetPageId: string
transition?: ReportPageTransition
params?: DrillParamBinding[]
}
export interface DrillParamBinding {
id: string
targetKey: string
source: 'static' | 'componentField' | 'pageContext' | 'userContext'
sourceKey?: string
value?: string | number | boolean | null
}
第一版重点支持:
新增页面上下文来源,并接入现有动态参数机制。
示例:
{
"regionCode": "150100",
"regionName": "呼和浩特市",
"sourcePageId": "page-home"
}
动态请求参数可选择:
source = pageContext
sourceKey = regionCode
target = Params
targetKey = regionCode
这样详情页组件不需要写代码,只要把请求参数绑定到页面上下文即可。
events.baseEvent 中的 JS。