组件的封装

这个项目封装了哪些"组件层级"

  • **基础 UI 组件层**:`src/components/ui/*`(`button`/`dialog`/`select`/`popover`...),偏"设计系统",稳定、复用广。

  • **业务通用组件层**:`src/components/shared/*`(`ConfirmDialog`、`ChatInputShell`、`StableUserAvatar`...),跨页面复用。

  • **页面/模块组件层**

  • **Dashboard**:`DashboardPage`、`DashboardTopBar`、`DashboardWorkspaceListPanel`

  • **Workspace(核心)**:`ChatPanel/*`、`CanvasPanel/*`、`FileSystem/*`、`PreviewPanel/*`、`SkillBuilder/*`


我觉得最"牛"的:**资产槽位系统(Asset Slot System)+ `AssetSlotPanel`**

它不是单纯 UI 封装。它是**配置驱动的"输入协议"**。解决一个很真实的问题:不同模型/工具对素材输入的**角色、数量、类型**都不一样。

  • **你要的"插槽"在这里是业务插槽**:首帧、尾帧、参考图、参考视频、音频等。

  • **你要的"通信"在这里是跨组件状态协作**:工具切换、素材引用、上传、交换、校验、发送。

关键点 1:把"工具差异"收敛成配置

  • **配置文件**:`src/components/Toolbox/constants/assetSlots.ts`

  • **UI 组件**:`src/components/Workspace/ChatPanel/AssetSlotPanel.tsx`(统一渲染/上传/交换/删除)

  • **状态层**:`src/components/Workspace/stores/uiStore.ts`(槽位化引用 + 扁平引用同步)

关键点 2:封装后如何保证 API 兼容性(这里是最能讲的)

这个项目用的是**双轨兼容**:

  • **新 API(槽位化)**:`slottedReferences: Record<slotId, nodeId[]>`

  • **旧 API(扁平)**:`referencedNodeIds: nodeId[]`

所有增删改都保证两者同步。旧逻辑不用改,也能继续跑;新逻辑逐步迁移即可。

最关键的一段就是 `uiStore.addReference`:在 tool 模式下优先进槽位;否则进扁平数组。

```251:302:c:\Users\派大鑫\Desktop\新建文件夹\loop\src\components\Workspace\stores\uiStore.ts

// ---------- 引用 ----------

referencedNodeIds: [],

slottedReferences: {},

addReference(refId) {

set((s) => {

const { activeToolId, interactionMode } = useToolStore.getState();

// ... 解析 refType ...

if (interactionMode === 'tool' && activeToolId && refType) {

const config = getToolAssetSlotConfig(activeToolId);

if (config) {

for (const slot of config.slots) {

if (slot.acceptType === refType) {

const current = s.slottedReferences[slot.slotId] || [];

if (current.length < slot.max && !current.includes(refId)) {

if (!s.slottedReferences[slot.slotId]) {

s.slottedReferences[slot.slotId] = [];

}

s.slottedReferences[slot.slotId].push(refId);

s.referencedNodeIds = Object.values(

s.slottedReferences

).flat();

return;

}

}

}

return;

}

}

if (!s.referencedNodeIds.includes(refId)) {

s.referencedNodeIds.push(refId);

}

});

},

```

**这就是"封装组件后 API 兼容性"的硬核答案**:

  • **不删旧接口**,而是用"兼容层"桥接。

  • **状态单一事实来源**在 store 内部维护,外部调用者感知最小。


面试官怎么讲(建议用 60 秒版本)

  • **问题**:不同 AI 工具对素材输入要求不同,原来会写很多 if/else,工具一多就爆炸;切换工具还会丢素材或校验混乱。

  • **做法**:做了"资产槽位系统"。用配置描述每个工具的输入槽位(类型/最小/最大/可交换)。UI 用一个通用组件渲染。store 负责分配、交换、迁移、校验。

  • **兼容**:保留旧的扁平引用 `referencedNodeIds`,新增槽位化 `slottedReferences`,在 store 内同步,保证旧链路不改也能跑。

  • **收益**:新增工具的素材输入适配从"改 UI + 改校验 + 改拼参"收敛为"加一份配置";减少重复代码与回归风险。


你说的"通信 + 插槽"对吗?

  • **对,但要区分两种"插槽"**:

  • **业务插槽**:上面这个资产槽位(首帧/尾帧/参考图)。这是本项目的核心亮点。

  • **React 插槽**:`children`/render props 这种组件组合方式。这里当然也用,但面试价值没"业务插槽系统"高。

  • **通信方式(你可以直接说)**:Zustand store 做"模块间总线"。

  • `toolStore` 提供当前工具与模式

  • `uiStore` 管引用与槽位

  • `AssetSlotPanel` 只做交互与展示,不自己写规则


简历可直接写的关键词与表述

  • **关键词**:React、TypeScript、Zustand、配置驱动(Config-driven UI)、Backward Compatibility、状态同步、模块解耦、可扩展输入协议、复杂表单/素材引用系统

  • **表述句式**(不编数字版):

  • "设计并落地配置驱动的资产槽位系统,将不同模型的素材输入差异抽象为统一协议(slotId/acceptType/min/max),并实现工具切换时的自动迁移与校验。"

  • "通过双轨兼容(slottedReferences + referencedNodeIds)构建兼容层,保障旧调用方无感升级,降低重构风险。"

如果你愿意,我也可以把这套"60 秒版本"再压缩成面试口播稿(更像真实对话)。

相关推荐
漂流瓶jz4 小时前
总结CSS组件化演进之路:命名规范/CSS Modules/CSS in JS/原子化CSS
前端·javascript·css
踩着两条虫4 小时前
「AI + 低代码」的可视化设计器
开发语言·前端·低代码·设计模式·架构
JoneBB5 小时前
ABAP Webservice连接
运维·开发语言·数据库·学习
Jagger_5 小时前
项目上线忙碌结束之后,为什么总想找点事做?
前端
GalenZhang8885 小时前
OpenClaw 配置多个飞书账号实战指南
前端·chrome·飞书·openclaw
即使再小的船也能远航5 小时前
【Python】安装
开发语言·python
Irissgwe5 小时前
类与对象(三)
开发语言·c++·类和对象·友元
steven~~~6 小时前
为什么mq报错
javascript
雪度娃娃6 小时前
转向现代C++——优先选用nullptr而不是0和NULL
开发语言·c++
萌新小码农‍6 小时前
python装饰器
开发语言·前端·python