Files
TrueGrowth/.specify/memory/constitution.md

9.3 KiB
Raw Blame History

Opentu 项目宪章

核心原则

I. 插件优先架构

每个功能都应该实现为遵循 withXxx 模式的可组合插件。插件必须满足:

  • 自包含: 每个插件都有清晰的边界和职责
  • 可独立测试: 可以独立进行测试
  • 可组合: 可以与其他插件组合而不产生冲突
  • 框架无关: 核心逻辑应该能在不同的UI框架中工作React、Angular等

示例: withFreehandwithMindwithDrawwithHotkey - 每个都在不耦合的情况下扩展编辑器能力

II. 文件大小约束(不可协商)

单个文件不得超过 500 行(包括空行和注释)

这是一个硬性约束,以确保:

  • 代码可读性和可维护性
  • 合理的关注点分离
  • 易于代码审查和理解
  • 防止出现单体组件

执行规则

  • PR 审查必须拒绝超过 500 行的文件
  • 例外情况需要架构审查和文档化的理由
  • 重构为多个文件或抽象为可重用模块

III. 类型安全优先

TypeScript 严格模式是强制性的。所有代码必须:

  • 使用 interface 定义对象类型,type 定义联合类型/交叉类型
  • 为所有组件 Props 定义显式类型
  • 避免使用 any - 使用具体类型或泛型
  • 提交前通过严格的 TypeScript 检查

示例

// ✅ 好的做法
interface UserProfileProps {
  userId: string;
  onUpdate: (user: User) => void;
}

// ❌ 不好的做法
const UserProfile = (props: any) => {}

IV. 设计系统一致性

所有 UI 组件必须使用 TDesign React 并采用 light 主题。一致性规则:

  • 所有 UI 元素使用 TDesign 组件
  • 遵循品牌色彩系统(橙金色、蓝紫色、创作强调色)
  • 使用设计系统的 CSS 变量
  • Tooltip 主题必须使用 'light'
  • 自定义样式遵循 BEM 命名约定

V. 性能与优化

为用户体验进行优化:

  • 对昂贵的组件使用 React.memo
  • 对传递给子组件的事件处理器使用 useCallback
  • 对昂贵的计算使用 useMemo
  • 对大型组件使用 React.lazy 实现代码分割
  • 图片懒加载并实现预加载策略
  • 对长列表考虑使用虚拟化

VI. 安全与验证

安全性是不可协商的:

  • 验证和清理所有用户输入
  • 永远不要硬编码敏感信息API 密钥、密码)
  • API 调用使用安全的错误处理
  • 从日志中过滤敏感数据
  • 验证文件上传(类型、大小、内容)

VII. Monorepo 结构

在 Nx monorepo 中保持清晰的分离:

  • apps/web/ - 主 Web 应用程序
  • packages/drawnix/ - 核心白板库
  • packages/react-board/ - Plait 的 React 包装器
  • packages/react-text/ - 文本渲染组件

每个包应该有清晰的依赖关系和最小的耦合。

开发标准

命名约定

文件命名(严格执行):

  • 组件文件:PascalCase.tsx(例如 ImageCropPopup.tsx
  • Hook 文件:camelCase.ts(例如 useImageCrop.ts
  • 工具文件:kebab-case.ts(例如 image-utils.ts
  • 类型文件:kebab-case.types.ts(例如 image-crop.types.ts
  • 常量文件:UPPER_SNAKE_CASE.ts(例如 STORAGE_KEYS.ts

代码命名

  • 变量camelCase
  • 常量UPPER_SNAKE_CASE
  • 组件PascalCase
  • 接口/类型PascalCase

组件结构

所有 React 组件必须遵循以下顺序:

  1. 导入(第三方 → 本地)
  2. 类型定义
  3. 常量
  4. 主组件函数
  5. HooksuseState、useEffect、自定义 hooks
  6. 事件处理器(使用 useCallback 包装)
  7. 渲染逻辑

示例

import React, { useState, useCallback } from 'react';
import { Button } from 'tdesign-react';
import './Component.scss';

interface ComponentProps {
  title: string;
  onAction: (data: string) => void;
}

const DEFAULT_CONFIG = { timeout: 5000 };

export const Component: React.FC<ComponentProps> = ({ title, onAction }) => {
  const [loading, setLoading] = useState(false);

  const handleClick = useCallback(() => {
    onAction(title);
  }, [title, onAction]);

  return <Button onClick={handleClick}>{title}</Button>;
};

测试要求

每个功能必须包括:

  • 单元测试 - 用于逻辑和工具函数
  • 组件测试 - 使用 React Testing Library 测试 React 组件
  • 集成测试 - 用于插件交互
  • E2E 测试 - 使用 Playwright 测试关键用户流程

测试必须:

  • 提交前通过
  • 覆盖边界情况和错误状态
  • 遵循 Arrange-Act-Assert 模式
  • 使用中文或英文的描述性测试名称

CSS/SCSS 标准

遵循 BEM 方法论:

.component-name {
  // 1. Position
  position: relative;

  // 2. Box model
  width: 100%;
  padding: 16px;

  // 3. Appearance
  background: var(--color-bg);
  border-radius: 8px;

  // 4. Typography
  font-size: 14px;

  // 5. Animation
  transition: all 0.2s ease-out;

  // 6. Nested elements
  &__header { }
  &__content { }

  // 7. Modifiers
  &--active { }

  // 8. Responsive
  @media (max-width: 768px) { }
}

Git 与版本控制

提交信息格式

遵循 Conventional Commits

<type>(<scope>): <subject>

<body>

<footer>

类型feat, fix, docs, style, refactor, test, chore, perf, ci

示例

feat(crop): 添加图片圆形和椭圆形裁剪功能

- 实现三种裁剪形状:方形、圆形、椭圆形
- 添加裁剪预览功能
- 更新相关TypeScript类型定义

Closes #123

分支策略

  • main - 生产就绪代码
  • develop - 开发集成分支
  • feature/* - 新功能
  • fix/* - Bug 修复
  • docs/* - 文档更新

预提交检查

在任何提交之前,代码必须通过:

  • TypeScript 类型检查(nx typecheck
  • ESLint 检查(nx lint
  • 单元测试(nx test
  • 文件大小验证(< 500 行)
  • 无 console.log 或调试代码
  • 无硬编码的密钥

品牌指南集成

视觉识别

  • 品牌名称Opentu开图- AI 图片与视频创作工具
  • 标语爱上图片爱上创作Love Images, Love Creation

色彩系统

// 主品牌色
--brand-primary: #F39C12;        // 橙金色
--brand-secondary: #5A4FCF;      // 蓝紫色
--brand-accent: #E91E63;         // 创作强调色

// 渐变
--gradient-brand: linear-gradient(135deg, #F39C12 0%, #E67E22 30%, #5A4FCF 70%, #E91E63 100%);
--gradient-brush: linear-gradient(135deg, #5A4FCF 0%, #7B68EE 50%, #E91E63 100%);

使用方式

  • 主要行动号召按钮:使用品牌渐变
  • 链接/强调:橙金色(#F39C12
  • AI 功能:蓝紫色(#5A4FCF
  • 创作工具:洋红色(#E91E63

排版

  • 字体栈'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif
  • 尺寸xs(12), sm(14), base(16), lg(18), xl(20), 2xl(24), 3xl(30), 4xl(36)

组件设计

  • 按钮8px 圆角渐变背景12px/24px 内边距
  • 卡片12px 圆角白色背景细微阴影24px 内边距
  • 输入框8px 圆角2px 聚焦边框使用品牌主色
  • 动画150-300ms 过渡时间,使用 ease-out 曲线

质量门槛

代码审查清单

在批准任何 PR 之前,验证:

  • TypeScript 严格模式合规
  • 所有文件 < 500 行
  • 测试已添加/更新并通过
  • UI 使用 TDesign 组件
  • 自定义样式使用 BEM 命名
  • 无硬编码的值或密钥
  • 应用了性能优化
  • 实现了安全验证
  • 符合无障碍标准
  • 文档已更新

完成定义

当满足以下条件时,功能才算完成:

  1. 代码已实现并审查
  2. 单元测试已编写并通过(>80% 覆盖率)
  3. 集成测试通过
  4. 关键流程的 E2E 测试通过
  5. 文档已更新JSDoc、README
  6. 无障碍性已验证
  7. 性能已基准测试
  8. 安全性已审查
  9. 已部署到预发布环境并验证

架构约束

依赖规则

  • 核心包(@plait/*)不得依赖 UI 框架
  • React 包可以依赖核心,但反之不行
  • 插件不得有循环依赖
  • 工具函数必须是无副作用的纯函数

存储与持久化

  • 使用 localforage 进行浏览器存储
  • 实现带防抖的自动保存
  • 支持数据格式变更的迁移
  • 导出格式PNG、JPG、JSON.drawnix

国际化

  • 所有面向用户的文本使用 useI18n hook
  • 支持中文zh-CN和英文en-US
  • 组件中不得有硬编码字符串
  • 翻译键遵循命名空间模式

治理

宪章权威

本宪章优先于所有其他编码实践和约定。任何偏离都需要:

  1. 文档化的理由
  2. 架构审查批准
  3. 更新本宪章或异常文档
  4. 如果现有代码需要更新,需要迁移计划

修订流程

修订本宪章的步骤:

  1. 通过 GitHub Issue 提出变更,标签为 constitution-amendment
  2. 与团队和利益相关者讨论
  3. 获得项目维护者批准
  4. 更新本文档并说明理由
  5. 更新版本和最后修订日期
  6. 向所有贡献者传达变更

执行

  • 所有 PR 必须包含宪章合规性验证
  • CI/CD 管道执行自动化检查
  • 手动审查检查不可自动化的标准
  • 违规将阻止合并直至解决
  • 重复违规将触发架构审查

相关文档

有关运行时开发指导,请参考:


版本1.0.0 | 批准日期2025-01-22 | 最后修订2025-01-22