ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Activepieces Web 前端工程规范实战:从技术栈、表单到数据安全的完整开发手册

Activepieces Web 前端工程规范实战:从技术栈、表单到数据安全的完整开发手册 Activepieces Web 前端工程规范实战从技术栈、表单到数据安全的完整开发手册【免费下载链接】activepiecesAI Agents MCPs AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows AI Agents • MCPs for AI Agents项目地址: https://gitcode.com/GitHub_Trending/ac/activepiecesActivepieces 的 Web 前端packages/web承载着可视化流程编排、AI Agent、表格Tables、连接器配置等核心交互界面。这份以仓库内 packages/web/CLAUDE.md 为主体的技术指南系统梳理了该前端的工程规范与实践约定——包括技术栈选型、目录组织、测试方式、Tailwind v4 样式纪律、React Hook Form 表单范式、useEffect使用边界、数据获取失败处理、功能开关守卫与 ICU 国际化语法。读完本文你将掌握一套可直接套用的企业级 React 前端开发标准并能在仓库源码中逐一找到对应的实现证据。技术栈概览一份被源码印证的依赖清单packages/web/CLAUDE.md明确给出了 Activepieces Web 前端的核心技术选型这些约定在 packages/web/package.json 的dependencies中均可找到对应条目领域选型源码佐证package.json 版本框架React React Routerreact-router-dom6.11.2构建Vitebuild: vite build、serve: viteUI 组件Shadcn/Radix UIradix-ui1.4.3、radix-ui/react-accordion1.2.4等状态管理Zustandzustand4.5.4数据获取TanStack Querytanstack/react-query5.51.1表单React Hook Form Zodreact-hook-form7.71.2、zod4.3.6样式Tailwind CSStailwindcss4.1.17v4见下文theme说明流程画布XYFlowxyflow/react12.3.5国际化i18next ICU MessageFormati18next-icu2.3.0语言TypeScript (strict)typecheck: tsc --noEmit -p tsconfig.app.json需要说明的是文档撰写时描述框架为 React 18而从当前 package.json 看react与react-dom已为19types/react19react-router-dom仍为 v6——可以推断这是文档相对代码的版本滞后阅读时以 package.json 实际版本为准但本文所述的模式规范如 key 重置、FormField结构在两种版本下均适用。项目结构按 Feature 组织的目录约定packages/web/src/下的目录划分遵循功能优先feature-based原则src/components/ui/— 共享的 Shadcn/Radix 基础 UI 原语Button、Dialog、DataTable 等src/features/— 按功能域拆分的业务模块。从 src/features 目录可以看到实际存在的模块agents、authentication、billing、chat、connections、flow-runs、flows、folders、pieces、project-releases、secret-managers、tables、templates、variables、workspace等src/lib/— 共享工具与辅助函数如cn()src/app/— 应用级路由与布局如 query-client.ts 中的全局 QueryClienttest/— 单元测试详见下一节。在src/features/内部每个功能域通常再按components / hooks / api / lib细分例如 secret-managers 模块的 hooks 位于 src/features/secret-managers/hooks/secret-managers-hooks.tsAPI 层位于api/secret-managers-api.ts。新增功能时应当遵循这些既有约定而不是自创目录形态。测试规范测试永远不进src/packages/web/CLAUDE.md对测试做了三条硬性约定测试必须放在packages/web/test/下绝不能放在src/下。测试文件与源码路径一一镜像src/features/foo/bar.ts的测试就是test/features/foo/bar.test.ts。这样做的直接收益是测试代码不会被打包进生产 bundle源码树保持干净。被测对象一律通过/别名导入例如import { x } from /features/foo/bar;禁止使用相对路径。好处是移动文件时无需同步修改测试中的 import。运行命令cd packages/web npm test底层是 Vitestnode 环境。从 package.json 的 scripts 可见test: vitest run --passWithNoTests而 devDependencies 中同时准备了jsdom26.1.0与testing-library/react说明测试环境支持组件渲染级断言。test/目录当前共 77 个文件51 个.ts与 26 个.tsx可作参考样例。样式纪律Tailwind v4 下的三条铁律1. className 组合必须用cn()文档要求永远使用cn()组合 className禁止模板字符串拼接或号连接例如禁止class-a ${someVar}。cn()的实现位于 src/lib/utils.ts本质是twMerge(clsx(inputs))——clsx负责条件与数组拼接tailwind-merge负责解决冲突类如同时出现p-2与p-4时后者生效保证组件被覆盖样式时的确定性。2. 使用预定义字号刻度杜绝任意值这是 Tailwind v4主题定义在 src/styles.css 的theme块中不是原版 Tailwind 默认刻度它额外增加了--text-xss: 0.65rem约 10.4px并把--text-3xl收窄到1.75rem、--text-4xl收窄到2rem对应 styles.css 中的定义。因此选字号要挑 token不要写text-[13px]这类任意值目标字号使用的 token典型场景10–11pxtext-xss眉毛标签eyebrow、密集徽章11.5–12.5pxtext-xs元数据Badge 默认即text-xs13–13.5pxtext-sm正文默认15–15.5pxtext-base次级正文卡片标题text-lg卡片标题区块标题text-xl分区标题页面标题text-2xl页面标题展示级text-3xl/text-4xl大屏展示配套规则组件自身已设置字号时如 Badge 自带text-xs就不要再叠加类行高与字距同样优先用leading-*、tracking-tight标题、tracking-wide/tracking-wider大写眉毛标签Tailwind v4 支持小数间距所以size-4.5优于size-[18px]。唯一的任意值例外是没有对应 token 的布局约束——例如阅读宽度max-w-[628px]、侧栏宽度lg:w-[344px]这类任意值是被允许且地道的。文档特别提醒eslint 和tsc都抓不到这些违规它们只会在 code review 中被发现。3. 禁止负 margin-mt-、-mb-、-mx-、-my-、-ml-、-mr-一律禁用。负 margin 会引入难以排查的细微布局错位使间距推理变得困难。应改用gap、padding或space-*工具类表达间距意图。组件复用先搜索再扩展不造平行组件组件规范的核心原则是先复用再新建创建新组件前先在仓库中搜索是否已有覆盖该场景的组件避免为微小差异复制出近重复组件会增加维护负担与视觉不一致如果现有组件不够完美不要另起炉灶而是向后兼容地扩展它例如增加可选 prop保证既有用法不受影响并把取舍trade-off向用户解释清楚。溢出文本必须用TextWithTooltip任何可能溢出容器的文本邮箱、ID、长名称都必须包在TextWithTooltip位于/components/custom/text-with-tooltip中TextWithTooltip tooltipMessage{text} p className...{text}/p /TextWithTooltip它会在文本真正溢出时才自动显示 tooltip。配套细节父级 flex 容器需要min-w-0truncate才能正确生效。复制按钮必须用CopyToClipboardInput需要复制到剪贴板的 UI 一律使用CopyToClipboardInput位于 src/components/custom/clipboard/copy-to-clipboard.tsx禁止手搓readonly Input 复制 Button navigator.clipboard.writeText。该组件内置了复制成功态切换、tooltip、样式与可选下载按钮useInput{true}单行值链接、密钥useInput{false}多行内容textareafileName仅当值需要支持下载时传入。React Hook Form一整套表单范式表单是 Activepieces 前端出现频率最高的交互形态连接器配置、项目设置、成员邀请等packages/web/CLAUDE.md给出了近乎逐字段级的规范校验消息用formErrors标准校验消息如必填使用activepieces/shared导出的formErrors常量自定义消息则先在packages/web/public/locales/en/translation.json中添加翻译 key再使用 key 字符串。FormMessage会自动对每条错误消息执行t()因此传入的字符串必须是合法的翻译 key。接线方式必须使用zodResolveruseForm({ resolver: zodResolver(MySchema) })把 Zod schema 直接接到表单上必须设置defaultValues防止受控/非受控切换警告保证重置干净defaultValues 应从 helper 派生而不是内联字面量使用mode: onChange用户输入时即时校验反馈。用key重置不用form.reset()当对话框或父组件重新打开时给表单组件传新的key让 React 干净地卸载重挂MyForm key{open ? open : closed} /与之配套的架构要求是从写第一版起就分离对话框状态与表单逻辑对话框组件持有open状态表单是独立的子组件。文档特别强调这是写初始代码时就该做的而不是后续重构——每个包含useForm(...)的Dialog都必须长这样// ✅ 正确——对话框包装 带 key 的表单子组件 const MyDialog: React.FCProps ({ open, onOpenChange }) ( Dialog open{open} onOpenChange{onOpenChange} DialogContent MyForm key{open ? open : closed} onOpenChange{onOpenChange} / /DialogContent /Dialog );字段结构必须使用FormField render prop每个字段都包成FormField name... render{({ field }) FormItem.../FormItem} /并在FormItem内放FormMessage /以展示校验错误条件渲染要订阅字段绝不读form.getValues()getValues()返回的是非响应式快照用它做派生 UI 会显示旧状态。规则是——在调用useForm的组件里用form.watch(fieldName)在更下层的组件里通过useFormContext触达表单的用useWatch({ control: form.control, name: fieldName })。因为在深层组件里用form.watch()会连带重渲染useForm的宿主进而重渲染表单内所有useFormContext消费者而不是只有请求了该值的组件级联更新用form.setValue()当一个字段变化需要重置/更新关联字段如选择 provider 时重置其配置在onValueChange处理器中调用form.setValue()。服务端错误与表单包装服务端错误统一放root.serverError用form.setError(root.serverError, { type: manual, message: ... })设置在handleSubmit开头用form.clearErrors(root.serverError)清理渲染在字段下方、ScrollArea之外必须用Form {...form}包装form元素并在原生form上使用form.handleSubmit(handleSubmit)。提交按钮必须在form内部且typesubmit取消按钮必须typebutton防止误触发表单提交。React 模式useEffect的边界文档把useEffect定义为与外部系统同步的逃生舱浏览器 API、WebSocket、第三方库、DOM 操作。以下场景严禁使用useEffect从 props 或 state 派生数据→ 直接在组件体内计算响应用户交互→ 用事件处理器onClick、onSubmit等prop 变化时重初始化组件状态→ 父组件改传新key让 React 卸载重挂MyComponent key{someId} /监听值变化去触发其他 state 更新→ 渲染期间直接派生或在触发变化的事件处理器里处理useEffect → setState → useEffect的链条永远是设计问题的信号为渲染转换数据→ 渲染时内联计算向上层传递数据→ 提升 state 或使用共享 storeZustand。数据获取失败处理绝不让错误路径渲染空白这是文档用词最重的一条规则每个展示用户想看数据的组件在获取失败时必须渲染内容。空表格或空白面板会被用户读成数据被删了——这个故障模式被客户多次反馈过。具体落地方式渲染DataFetchErrorState位于 src/components/custom/data-fetch-error-state.tsx。它接收entity一个已翻译的小写名词会读作 Trouble loading {entity}和可选onRetry。从源码可见其文案刻意平静Nothing has been lost — your data is safe. Try again in a moment.配以警告色图标与 Try again 重试按钮——不要升级成破坏性的红色告警样式DataTable把isError和errorStateEntity设为必需 prop编译器层面就杜绝了不决策就渲染表格有refetch时传onRetry{refetch}。若表格行来自已加载的 props 而非自身查询isError{false}才是正确答案非DataTable表面卡片网格、配置面板、Tab、图表没有内置守卫必须在空状态判断之前先分支isError否则失败会静默渲染你还没有任何内容的文案返回成形对象的 hook 必须把isError以及refetch透传出去否则调用方无法遵守上述规则辅助查询不要加错误态功能开关、piece 元数据、单项获取、筛选选项、用户详情这些应当静默失败。最后没有全局错误 toast。app/query-client.ts 中QueryCache.onError仅通过errorReporting上报 Sentry带query_hash、http_status、request_url等上下文。不要重新引入 toast在占位组件之上再加 toast 等于一次失败两种通知单独一个 toast 又会让空白界面得不到解释。查询功能守卫请求不该在没权限时发出当服务端端点被platformMustHaveFeatureEnabled门控计划缺功能时返回 HTTP 402FEATURE_DISABLED时对应的useQueryhook必须包含enabled: platform.plan.flag让请求在功能关闭时根本不发出。否则接在DataFetchErrorState上的列表查询会在本来就不该有这个功能的页面上显示误导性的 Trouble loading … 占位符。标准范式参见 secret-managers-hooks.tsconst { platform } platformHooks.useCurrentPlatform(); return useQuery({ queryKey: [...], queryFn: ..., enabled: platform.plan.someFeatureEnabled, });要点platformHooks.useCurrentPlatform()从缓存即时返回由InitialDataGuard预加载可以在任何 hook 中安全调用——这正是源码中useListSecretManagerConnections的做法其enabled绑定的是platform.plan.secretManagersEnabled若查询已有enabled条件则合并enabled: !!existing platform.plan.flag对含计划门控内容的页面再用LockedFeatureGuard包裹让用户看到升级引导而不是坏掉的空页面。F 型布局所有面向用户的界面遵循阅读模型所有用户可见布局——页面、对话框、卡片、邮件模板——都要遵循F-pattern 阅读模型内容左对齐用户从左到右扫描再沿左侧边缘下移。避免居中文本块、标题或正文CTA按钮可以全宽但不应导致周围文本居中。国际化ICU MessageFormat 语法项目通过i18next-icu使用 ICU MessageFormat配置见 src/i18n.ts其中还启用了fallbackLng: en、关闭了keySeparator与nsSeparator。所有 translation.json 中的翻译字符串必须遵循 ICU 语法而不是 i18next 默认语法变量用单花括号{variableName}严禁双花括号{{variableName}}Delete {name}: Delete {name}复数用 ICU{var, plural, ...}语法绝不使用_one/_other的 key 后缀模式invitationsSentCount: {count, plural, 1 {1 invitation sent} other {# invitations sent}}其中1精确匹配值 1other是兜底分支#在分支内会被替换为选择变量的数值。变量与复数组合复数分支内部的变量依然使用单花括号membersAddedCount: {count, plural, 1 {1 member joined {projectName}} other {# members joined {projectName}}}通用工程指南与源码对照packages/web/CLAUDE.md最后给出几条总纲与前文规范一脉相承改代码前先读现有代码理解既有模式——例如表单参照features/下已有的useForm用法错误态参照 contenteditable="false">【免费下载链接】activepiecesAI Agents MCPs AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows AI Agents • MCPs for AI Agents项目地址: https://gitcode.com/GitHub_Trending/ac/activepieces创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表