| name | coding-standards |
| description | Creative Studio 项目的基础编码标准,覆盖 TypeScript、React、Rust 与跨层协作。 |
编码规范
说明
定义本项目在 TypeScript、React、Rust 以及跨层协作上的基础编码规范。
这个 skill 是当前仓库的通用下限规则,负责统一命名、可读性、不可变更新、错误处理与异味识别。
更具体的桌面 UI 模式请结合 tauri-react-desktop,Tauri Rust command 设计请结合 tauri-rust-commands 与 tauri-command。
适用时机
- 新增页面、组件、Hook
- 新增 Tauri command
- 调整共享类型
- 重构复杂逻辑
- 审查代码可维护性
通用规则
- 优先可读性,其次才是技巧
- 保持最小必要抽象
- 不复制粘贴多处相同流程
- 不为了未来假设提前造复杂框架
- 命名要表达业务语义,不用
data、temp、flag 这类低信息量名字
- 代码优先自解释,只有在“为什么这样做”不明显时才补简短注释
代码质量原则
可读性优先
- 代码是给人读的,不是给作者炫技巧的
- 变量、函数、类型名都要能独立表达含义
- 复杂分支优先拆函数,不堆在一个事件回调里
- 同一类结构保持一致写法,降低阅读切换成本
KISS
- 先写最简单可工作的实现
- 不为假设中的复用提前做复杂泛化
- 性能优化要基于真实瓶颈,不做习惯性过度优化
DRY
- 两处以上重复的流程,要考虑抽成函数、Hook 或共享组件
- 但不要为了去重 5 行代码,把本来简单的逻辑包装成难懂框架
YAGNI
- 当前项目处于早期阶段,先保证结构清晰、边界稳定、验证可跑
- 没有明确需求前,不预留成套平台化接口
TypeScript 规则
- 不使用
any 逃避建模
- 参数、返回值、组件 props 明确标注类型
- 优先使用字面量联合、对象类型和
interface 表达约束
- 共享类型集中放在
src/types/
- 布尔名使用语义化前缀,如
isLoading、hasError、canRetry
- 常量避免魔法值,提取为命名常量
示例:
type StrategyCardProps = {
strategyId: string;
titleCount: number;
onSelect: (strategyId: string) => void;
};
const MAX_RETRY_COUNT = 3;
const SEARCH_DEBOUNCE_MS = 500;
不可变更新
- React 状态默认使用不可变更新
- 数组、对象变更优先使用展开语法或派生新值
- 只有在性能原因非常明确时,才允许局部受控可变写法,并说明原因
示例:
setFormState((prev) => ({
...prev,
browserProfileId: nextProfileId,
}));
React 规则
- 组件保持单一职责
- 页面负责布局和区域组合,复杂逻辑下沉到 Hook
- 状态更新优先函数式写法,避免闭包读到旧值
- 明确处理
loading、empty、error、success
- 避免三元表达式嵌套地狱
- 复杂页面不要把业务编排、弹窗逻辑、请求状态都塞进同一个组件
组件与 Hook 约束
- 可复用交互逻辑优先抽到 Hook
- 纯展示组件不要知道 Tauri
invoke 细节
- 跨页面共享前,先确认是否真的是共享状态,而不是局部状态被错误上提
- 事件处理函数应体现业务语义,如
handleSubmitTask,不要写成 onClickButton
条件渲染
- 优先显式分支或提取局部变量
- 避免一行里混杂多层条件和 JSX
示例:
if (isLoading) return <TaskSkeleton />;
if (errorMessage) return <InlineError message={errorMessage} />;
if (items.length === 0) return <EmptyState />;
return <TaskList items={items} />;
Rust 规则
- command 命名面向能力,不面向某个按钮
- 返回
Result<_, String> 或更清晰的错误模型
- 文件、端口、进程、路径处理都必须考虑失败分支
- 尽量把路径解析、配置读取等共性逻辑收敛到复用函数
- 不把底层异常原样暴露给 UI,返回对用户可理解的错误文本
Tauri command 约束
- command 入参和出参结构要稳定,不随 UI 临时状态命名漂移
- 与前端交互的字段名保持一致
- 对路径、端口、配置等外部输入先做校验,再执行副作用
跨层规则
- 前端与 Rust 间的结构体字段名保持一致
- 前端调用 Tauri 时优先封装统一入口
- 同一个能力不要在多个组件里散写
invoke
- 涉及 engine 协议时,字段变更必须同步修改上下游
- UI 负责展示与轻量交互,不承载长流程业务编排
- 长流程、采集、模型调用优先放在
engine/
错误处理规则
- 所有外部调用都要考虑失败分支
- 错误提示优先告诉用户下一步怎么做,而不是只显示“失败”
- 日志保留调试价值,但不打印敏感信息
- 不要默默吞错;如果选择降级,也要让调用方知道当前不是正常路径
文件组织建议
src/components/:通用或可复用组件
src/pages/:页面级组合与工作台区域
src/hooks/:复用交互逻辑与状态转换
src/types/:共享类型与跨层契约
src-tauri/src/:桌面能力、IPC 桥接、配置与进程管理
engine/:长流程、采集、模型和数据处理
注释规则
- 解释“为什么”而不是“代码正在做什么”
- 对路径绕过、兼容旧数据、失败重试等不明显决策,可以补一行短注释
- 明显语句不要加解释性废话注释
审查清单
- 命名是否表达真实业务含义
- 是否存在可以明显下沉到 Hook 或工具函数的重复逻辑
- 是否有未处理的失败分支
- 是否把跨层调用散落在多个组件中
- 是否引入了没有当前需求支撑的抽象
- 是否出现魔法值、长函数、深层嵌套
异味模式
- 巨型页面组件
- 复制粘贴多个 modal / page 的状态逻辑
- 把业务流程直接写在按钮点击回调里
- 用字符串魔法值驱动步骤流
- Rust command 只返回
"ok" / "fail" 这类低信息量结果
- 多层
if/else 嵌套却没有提早返回
- 把临时调试输出、假数据、注释掉的旧代码留在提交中