模块组织
大型项目需要把框架依赖、业务页面、服务、模型和静态资源分开。框架能力统一从 ds-ui 包入口导入,业务代码只在自己的模块中组合。
推荐目录
app/
main.ts
app_context.ts
app_shell.ts
modules/
workbench/
patient-list/
record-editor/
quality-review/
services/
api_client.ts
permission_service.ts
dictionary_service.ts
audit_service.ts
state/
app_state.ts
user_state.ts
workspace_state.ts
models/
user.ts
permission.ts
record.ts
docs/
business-guides/
app/ 放启动和全局装配。modules/ 放业务页面。services/ 放接口访问和业务服务。state/ 放跨页面状态。models/ 放业务数据结构。
框架导入规则
业务模块应该从包入口导入框架能力:
import { RenderStackPanel, RenderText, RenderButton } from 'ds-ui'
不要从框架内部路径导入。内部路径可能随着实现优化而变化,包入口才是公共 API 边界。
页面文件结构
一个业务页面建议拆成:
record-editor/
record_editor_page.ts
record_editor_state.ts
record_editor_commands.ts
record_editor_service.ts
record_editor_view_model.ts
页面文件负责组件组合。状态文件负责页面数据。命令文件负责按钮和快捷键。服务文件负责业务接口。视图模型负责把业务数据整理成组件需要的结构。
示例与正式业务的边界
示例中的页面类、mock 数据和局部工具只用于演示框架能力,不属于框架 API。
业务项目不要继承示例页面类,也不要依赖示例数据。如果某段逻辑在多个业务页面都有用,应根据职责沉淀为业务公共模块、服务适配器或由公共组件组合出的页面片段。
模块通信
模块之间不要直接互相持有页面实例。推荐使用三种方式通信:
- 同一页面内部:直接组合子组件并通过回调通信。
- 同一业务范围:通过页面上下文共享服务和状态。
- 跨页面或全局:通过应用状态、事件服务或命令触发。
这种组织方式能让 tab、浮动窗口和弹窗保持独立生命周期,也便于做内存泄露排查。