文档核心
262
Project/fonrey/DATA_MODEL/DATA_MODEL文档要求.md
Normal file
@@ -0,0 +1,262 @@
|
||||
`DATA_MODEL.md` 的核心目标是:**让 AI 在触碰任何数据相关代码时,都能理解业务语义,而不只是看到一堆字段名。**
|
||||
|
||||
---
|
||||
|
||||
### 必须包含的内容
|
||||
|
||||
#### 1. 领域概览(Domain Overview)
|
||||
|
||||
用业务语言(不是技术语言)描述核心概念和它们的关系。这是 AI 理解"为什么"的基础。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Domain Overview
|
||||
|
||||
This is a **multi-tenant** project management tool.
|
||||
|
||||
Core concepts:
|
||||
- **Workspace**: The top-level container, maps to a paying customer (company)
|
||||
- **Project**: Lives inside a Workspace, has a lifecycle (draft → active → archived)
|
||||
- **Task**: The atomic unit of work, always belongs to a Project
|
||||
- **Member**: A User's role within a specific Workspace (not global)
|
||||
|
||||
Key business rules:
|
||||
- A User can belong to multiple Workspaces with different roles
|
||||
- Deleting a Project soft-deletes all its Tasks (never hard delete)
|
||||
- Only Workspace `owner` or `admin` can invite new Members
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 2. 实体关系图(Entity Relationship)
|
||||
|
||||
用文字或 ASCII 图表达清楚关系,不要依赖读者去脑补。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Entity Relationships
|
||||
|
||||
Workspace (1) ──── (N) Project
|
||||
Workspace (1) ──── (N) Member
|
||||
Member (N) ──── (1) User ← same User, different roles per Workspace
|
||||
Project (1) ──── (N) Task
|
||||
Task (N) ──── (1) Member ← assignee
|
||||
Task (1) ──── (N) Comment
|
||||
Task (N) ──── (N) Tag ← via task_tags join table
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 3. 完整 Schema 定义(Schema Definition)
|
||||
|
||||
每个表都需要:字段 + 类型 + 约束 + **业务注释**。注释是给 AI 的关键上下文。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Schema
|
||||
|
||||
### workspaces
|
||||
| Column | Type | Constraints | Notes |
|
||||
|--------------|-------------|-------------------|--------------------------------|
|
||||
| id | uuid | PK, default gen | |
|
||||
| slug | text | UNIQUE, NOT NULL | URL identifier, immutable after creation |
|
||||
| name | text | NOT NULL | |
|
||||
| plan | text | NOT NULL | enum: 'free' | 'pro' | 'enterprise' |
|
||||
| created_at | timestamptz | NOT NULL, default now() | |
|
||||
| deleted_at | timestamptz | nullable | soft delete, filter WHERE deleted_at IS NULL |
|
||||
|
||||
### members
|
||||
| Column | Type | Constraints | Notes |
|
||||
|--------------|-------------|-------------------|--------------------------------|
|
||||
| id | uuid | PK | |
|
||||
| workspace_id | uuid | FK → workspaces.id, CASCADE DELETE | |
|
||||
| user_id | uuid | FK → users.id | |
|
||||
| role | text | NOT NULL | enum: 'owner' \| 'admin' \| 'member' \| 'viewer' |
|
||||
| invited_by | uuid | FK → members.id, nullable | null = founding owner |
|
||||
| joined_at | timestamptz | nullable | null = invitation pending |
|
||||
|
||||
-- UNIQUE(workspace_id, user_id) — one membership per workspace per user
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 4. 枚举与常量(Enums & Constants)
|
||||
|
||||
把所有枚举值集中在一处,AI 就不会自己发明状态值。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Enums & Constants
|
||||
|
||||
### Task Status (ordered, represents workflow progression)
|
||||
pending → in_progress → in_review → done → cancelled
|
||||
|
||||
Rules:
|
||||
- Only forward transitions are allowed (no reopening cancelled tasks)
|
||||
- `done` and `cancelled` are terminal states
|
||||
- Changing status logs an entry in task_activity
|
||||
|
||||
### Member Role Permissions
|
||||
| Action | owner | admin | member | viewer |
|
||||
|---------------------|-------|-------|--------|--------|
|
||||
| Invite members | ✅ | ✅ | ❌ | ❌ |
|
||||
| Delete project | ✅ | ❌ | ❌ | ❌ |
|
||||
| Create tasks | ✅ | ✅ | ✅ | ❌ |
|
||||
| Comment on tasks | ✅ | ✅ | ✅ | ✅ |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 5. 索引策略(Indexes)
|
||||
|
||||
告诉 AI 哪些查询是热路径,避免它写出全表扫描的代码。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Indexes
|
||||
|
||||
-- tasks is the most queried table, optimize for these patterns:
|
||||
CREATE INDEX idx_tasks_project_status ON tasks(project_id, status) WHERE deleted_at IS NULL;
|
||||
CREATE INDEX idx_tasks_assignee ON tasks(assignee_id) WHERE deleted_at IS NULL;
|
||||
CREATE INDEX idx_members_user ON members(user_id); -- "get all workspaces for a user"
|
||||
|
||||
-- Avoid: never query tasks without a project_id filter
|
||||
-- Avoid: never do SELECT * on tasks, always select specific columns
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 6. 软删除约定(Soft Delete Convention)
|
||||
|
||||
如果使用软删除,必须明确说明规则,否则 AI 会写出漏掉过滤条件的查询。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Soft Delete Convention
|
||||
|
||||
Tables with soft delete: workspaces, projects, tasks
|
||||
|
||||
Rules:
|
||||
- ALL queries MUST include `WHERE deleted_at IS NULL` unless explicitly retrieving deleted records
|
||||
- Use `deletedAt: new Date()` to soft delete, never use DELETE SQL
|
||||
- Cascading: deleting a Project sets deleted_at on all its Tasks in the same transaction
|
||||
- Deleted records are purged by a cron job after 30 days (hard delete)
|
||||
|
||||
⚠️ AI Note: Never generate a query on these tables without the soft delete filter.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 7. 多租户隔离规则(Multi-tenancy Rules)
|
||||
|
||||
这是安全的核心,必须让 AI 理解每次查询都要带租户过滤。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Multi-tenancy & Data Isolation
|
||||
|
||||
This is a **workspace-scoped** multi-tenant system.
|
||||
|
||||
Rules:
|
||||
- EVERY query involving projects, tasks, members MUST be scoped by workspace_id
|
||||
- Never query tasks directly by id alone — always join through project → workspace
|
||||
- The workspace_id must come from the authenticated session, never from user input
|
||||
- Row Level Security (RLS) is enabled on Supabase for all tenant tables
|
||||
|
||||
Correct pattern:
|
||||
SELECT * FROM tasks
|
||||
JOIN projects ON tasks.project_id = projects.id
|
||||
WHERE projects.workspace_id = :workspaceId ← always present
|
||||
AND tasks.id = :taskId
|
||||
|
||||
Wrong pattern (security hole):
|
||||
SELECT * FROM tasks WHERE id = :taskId ← missing tenant scope
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 8. 核心查询模式(Common Query Patterns)
|
||||
|
||||
把最常用的查询写出来,AI 会直接复用,而不是重新发明。
|
||||
|
||||
md
|
||||
|
||||
````md
|
||||
## Common Query Patterns
|
||||
|
||||
### Get tasks for a project (with assignee info)
|
||||
```sql
|
||||
SELECT t.*, m.user_id, u.name as assignee_name
|
||||
FROM tasks t
|
||||
LEFT JOIN members m ON t.assignee_id = m.id
|
||||
LEFT JOIN users u ON m.user_id = u.id
|
||||
WHERE t.project_id = :projectId
|
||||
AND t.deleted_at IS NULL
|
||||
ORDER BY t.created_at DESC;
|
||||
```
|
||||
|
||||
### Check if user has permission in workspace
|
||||
```sql
|
||||
SELECT role FROM members
|
||||
WHERE workspace_id = :workspaceId
|
||||
AND user_id = :userId
|
||||
AND joined_at IS NOT NULL; -- pending invitations don't count
|
||||
```
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
#### 9. 明确禁止的操作(Forbidden Operations)
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Forbidden Operations
|
||||
|
||||
- ❌ Never hard DELETE on workspaces, projects, or tasks — use soft delete
|
||||
- ❌ Never UPDATE a task's status by skipping intermediate states
|
||||
- ❌ Never expose internal UUIDs in URLs — use slugs for workspaces/projects
|
||||
- ❌ Never store user PII (email, name) in tasks or comments — always join from users table
|
||||
- ❌ Never write a migration that drops a column without a deprecation period
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 10. 数据迁移约定(Migration Convention)
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Migration Convention
|
||||
|
||||
- Migration tool: Drizzle Kit
|
||||
- File naming: `0001_create_workspaces.ts`, sequential, never rename
|
||||
- Every migration must be reversible (include `down` function)
|
||||
- Never edit a migration that has been merged to main
|
||||
- Backfill scripts go in /scripts, not in migrations
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 内容优先级总结
|
||||
|
||||
|优先级|内容|为什么关键|
|
||||
|---|---|---|
|
||||
|🔴 必须|领域概览 + 业务规则|AI 需要理解"为什么"才能做正确取舍|
|
||||
|🔴 必须|完整 Schema + 字段注释|防止字段命名歧义和类型错误|
|
||||
|🔴 必须|软删除 + 多租户规则|安全漏洞和数据污染的高发区|
|
||||
|🟡 重要|枚举常量 + 状态机|防止 AI 自己发明状态值|
|
||||
|🟡 重要|常用查询模式|复用 > 重新发明|
|
||||
|🟢 加分|索引策略|引导 AI 写出性能友好的查询|
|
||||
|🟢 加分|迁移约定|保持 schema 演进的可控性|
|
||||
|
||||
---
|
||||
|
||||
**核心原则**:`DATA_MODEL.md` 写的不是给数据库看的 DDL,而是给 AI 看的**业务契约**。每一个"显而易见"的业务规则,在 AI 眼里都是需要被明确告知的约束。没写的,它都会自己猜。
|
||||
161
Project/fonrey/TECH_STACK/TECH_STACK 文档要求.md
Normal file
@@ -0,0 +1,161 @@
|
||||
#### 1. 项目概览(Project Overview)
|
||||
|
||||
用 2-3 句话说清楚这是什么项目、核心用途、目标用户。AI 需要这个"北极星"来判断所有技术取舍。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Project Overview
|
||||
A B2B SaaS invoice management tool. Target users are SMB accountants.
|
||||
Prioritize reliability and data integrity over flashy UI.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 2. 核心技术栈(Core Stack)
|
||||
|
||||
每一层都要写清楚,**不要只写框架名,要写版本号和选型原因**。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Core Stack
|
||||
- Runtime: Node.js 22 (not Bun, not Deno)
|
||||
- Framework: Next.js 15 (App Router only, never Pages Router)
|
||||
- Language: TypeScript 5.x, strict mode enabled
|
||||
- Database: PostgreSQL 16 via Supabase
|
||||
- ORM: Drizzle ORM (not Prisma)
|
||||
- Styling: Tailwind CSS v4 + shadcn/ui
|
||||
- Auth: Clerk
|
||||
- Deployment: Vercel
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 3. 关键约定(Key Conventions)
|
||||
|
||||
这是 vibe coding 最容易出错的地方,AI 会有自己的"默认习惯",必须显式覆盖。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Key Conventions
|
||||
- File naming: kebab-case for files, PascalCase for components
|
||||
- All server actions in /actions, never inline in components
|
||||
- Use `server components` by default; add 'use client' only when needed
|
||||
- Environment variables: never hardcode, always use process.env.NEXT_PUBLIC_*
|
||||
- Error handling: always use Result pattern, never throw in server actions
|
||||
- No `any` types. No `// @ts-ignore`.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 4. 目录结构(Directory Structure)
|
||||
|
||||
AI 需要知道把新文件放在哪里,否则它会自己"发明"结构。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Directory Structure
|
||||
src/
|
||||
├── app/ # Next.js routes only, minimal logic
|
||||
├── components/ # Reusable UI components
|
||||
│ └── ui/ # shadcn primitives, DO NOT edit
|
||||
├── actions/ # Server actions
|
||||
├── lib/ # Utilities and helpers
|
||||
├── db/ # Drizzle schema and migrations
|
||||
└── types/ # Global TypeScript types
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 5. 明确禁止的东西(Explicitly Forbidden)
|
||||
|
||||
这是最被忽视但最重要的部分。告诉 AI **不要用什么**,比告诉它用什么更有效。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Do NOT Use
|
||||
- ❌ `axios` — use native `fetch`
|
||||
- ❌ `moment.js` — use `date-fns`
|
||||
- ❌ `useEffect` for data fetching — use server components or React Query
|
||||
- ❌ `pages/` directory — App Router only
|
||||
- ❌ `class components` — functional only
|
||||
- ❌ CSS Modules or styled-components — Tailwind only
|
||||
- ❌ `console.log` in production code
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 6. 第三方服务与集成(External Services)
|
||||
|
||||
列出已经接入的服务,避免 AI 重复造轮子或引入冲突的 SDK。
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## External Services
|
||||
- Payments: Stripe (already configured in /lib/stripe.ts)
|
||||
- Email: Resend + React Email templates
|
||||
- File storage: Supabase Storage (not S3)
|
||||
- Analytics: PostHog
|
||||
- Error tracking: Sentry
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 7. 代码风格与 Linting(Code Style)
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Code Style
|
||||
- Formatter: Prettier (config in .prettierrc)
|
||||
- Linter: ESLint with eslint-config-next
|
||||
- Imports: absolute paths via `@/` alias, no relative `../../`
|
||||
- Prefer `const` over `let`, avoid `var`
|
||||
- Async/await over `.then()` chains
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 8. 测试策略(Testing, 如果有的话)
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
## Testing
|
||||
- Unit tests: Vitest
|
||||
- E2E tests: Playwright (critical flows only)
|
||||
- No snapshot tests
|
||||
- Test files co-located: `component.test.ts` next to `component.ts`
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 一个实用的小技巧
|
||||
|
||||
在文件开头加一句 AI 专用说明:
|
||||
|
||||
md
|
||||
|
||||
```md
|
||||
> **For AI assistants**: Read this entire file before writing any code.
|
||||
> All decisions here are final. Do not suggest alternatives unless asked.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 内容优先级总结
|
||||
|
||||
|优先级|内容|原因|
|
||||
|---|---|---|
|
||||
|🔴 必须|核心技术栈 + 禁止列表|防止 AI 用错库|
|
||||
|🔴 必须|目录结构 + 文件约定|防止结构混乱|
|
||||
|🟡 重要|外部服务清单|防止重复实现|
|
||||
|🟡 重要|关键约定|保持风格一致|
|
||||
|🟢 加分|测试策略 + 代码风格|提升整体质量|
|
||||
|
||||
**核心原则**:写给 AI 看的文档要比写给人看的**更具体、更强硬、更少歧义**。任何"视情况而定"的描述,AI 都会做出你不想要的选择。
|
||||
432
Project/fonrey/UI&UX/UI_SYSTEM文档要求.md
Normal file
@@ -0,0 +1,432 @@
|
||||
`UI_SYSTEM.md` 的核心目标是:**让 AI 生成的每一个组件,都像是同一个设计师写的,而不是从五个不同的 UI 库里随机拼凑的。**
|
||||
|
||||
---
|
||||
|
||||
## 必须包含的内容
|
||||
|
||||
### 1. 设计哲学(Design Philosophy)
|
||||
|
||||
在写任何具体规则之前,先定义"感觉"。AI 在模糊情况下会回到这里做判断。
|
||||
|
||||
```md
|
||||
## Design Philosophy
|
||||
|
||||
**Core aesthetic**: Clean, functional, low-friction.
|
||||
We build tools, not experiences. Every UI element must earn its place.
|
||||
|
||||
**Principles** (in priority order):
|
||||
1. **Clarity over cleverness** — if you have to explain the UI, it failed
|
||||
2. **Density over whitespace** — our users are power users, don't waste screen space
|
||||
3. **Consistency over novelty** — use existing patterns before inventing new ones
|
||||
4. **Motion is functional** — animate only to communicate state change, never for decoration
|
||||
|
||||
**Anti-patterns we actively avoid**:
|
||||
- Skeleton loaders for data that loads in < 300ms (just show a spinner)
|
||||
- Modal dialogs for destructive actions that are easily reversible
|
||||
- Infinite scroll (we use pagination, users need to share URLs to specific pages)
|
||||
- Tooltips on mobile
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. 设计 Token(Design Tokens)
|
||||
|
||||
这是整个系统的基础。所有颜色、间距、字体都必须来自这里,AI 不能自己发明数值。
|
||||
|
||||
````md
|
||||
## Design Tokens
|
||||
|
||||
### Color System
|
||||
We use CSS variables. NEVER use raw hex values in components.
|
||||
|
||||
**Semantic colors** (use these, not primitives):
|
||||
```css
|
||||
--color-bg-base /* page background */
|
||||
--color-bg-subtle /* card, sidebar backgrounds */
|
||||
--color-bg-muted /* disabled states, placeholders */
|
||||
|
||||
--color-text-primary /* body text */
|
||||
--color-text-secondary /* labels, captions */
|
||||
--color-text-disabled /* disabled text */
|
||||
--color-text-inverse /* text on dark backgrounds */
|
||||
|
||||
--color-border /* default borders */
|
||||
--color-border-strong /* focused, emphasized borders */
|
||||
|
||||
--color-accent /* primary actions, links */
|
||||
--color-accent-hover /* hover state of accent */
|
||||
|
||||
--color-success /* confirmations, completed states */
|
||||
--color-warning /* non-blocking alerts */
|
||||
--color-danger /* destructive actions, errors */
|
||||
--color-info /* informational, neutral alerts */
|
||||
````
|
||||
|
||||
**Rule**: If you find yourself writing `text-gray-500`, stop. Map it to a semantic token.
|
||||
|
||||
### Spacing Scale
|
||||
|
||||
We use an 4px base grid. Only use these values: `4px / 8px / 12px / 16px / 24px / 32px / 48px / 64px / 96px`
|
||||
|
||||
In Tailwind: `p-1 / p-2 / p-3 / p-4 / p-6 / p-8 / p-12 / p-16 / p-24`
|
||||
|
||||
Never: `p-5`, `p-7`, `p-9`, `p-10`, `p-11` — these break the grid.
|
||||
|
||||
### Border Radius
|
||||
|
||||
```
|
||||
--radius-sm: 4px → rounded-sm (inputs, badges)
|
||||
--radius-md: 8px → rounded (cards, buttons) ← default
|
||||
--radius-lg: 12px → rounded-xl (modals, panels)
|
||||
--radius-full: 9999px → rounded-full (avatars, pills)
|
||||
```
|
||||
|
||||
Never mix radius sizes within the same component.
|
||||
|
||||
### Elevation / Shadow
|
||||
|
||||
```
|
||||
--shadow-sm → subtle card lift
|
||||
--shadow-md → dropdowns, popovers
|
||||
--shadow-lg → modals, dialogs
|
||||
```
|
||||
|
||||
Never use `drop-shadow` filter — use `box-shadow` only.
|
||||
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
### 3. 字体系统(Typography System)
|
||||
|
||||
```md
|
||||
## Typography
|
||||
|
||||
**Font stack**:
|
||||
- UI: `Inter` (loaded via next/font, variable weight)
|
||||
- Code: `JetBrains Mono` (code blocks, inline code only)
|
||||
- Never import fonts from Google Fonts directly
|
||||
|
||||
**Type scale** (use only these, no arbitrary sizes):
|
||||
|
||||
| Token | Size | Weight | Line-height | Usage |
|
||||
|----------------|-------|--------|-------------|--------------------------|
|
||||
| `text-xs` | 12px | 400 | 1.5 | Labels, badges, metadata |
|
||||
| `text-sm` | 14px | 400 | 1.5 | Body, secondary content |
|
||||
| `text-base` | 16px | 400 | 1.6 | Primary body text |
|
||||
| `text-lg` | 18px | 500 | 1.4 | Section headings |
|
||||
| `text-xl` | 20px | 600 | 1.3 | Page sub-headings |
|
||||
| `text-2xl` | 24px | 700 | 1.2 | Page titles |
|
||||
| `text-3xl` | 30px | 700 | 1.1 | Hero headings only |
|
||||
|
||||
**Rules**:
|
||||
- Max 2 font sizes per component
|
||||
- `font-weight: 500` is the minimum for anything interactive (buttons, links)
|
||||
- Never use `text-3xl` outside of marketing pages
|
||||
- Line length: max 72 characters for body text (`max-w-prose`)
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
### 4. 核心组件规范(Core Component Specs)
|
||||
|
||||
为每个高频组件定义变体、状态和使用规则。这是 AI 最需要的部分。
|
||||
|
||||
````md
|
||||
## Core Component Specs
|
||||
|
||||
### Button
|
||||
|
||||
**Variants**:
|
||||
| Variant | Use case | Never use for |
|
||||
|-------------|---------------------------------------|----------------------------|
|
||||
| `primary` | Single main CTA per view | Destructive actions |
|
||||
| `secondary` | Secondary actions | Main CTA |
|
||||
| `ghost` | Toolbar actions, low-priority | Standalone CTAs |
|
||||
| `danger` | Irreversible destructive actions only | Anything reversible |
|
||||
| `link` | Navigation only | Form submissions |
|
||||
|
||||
**Sizes**: `sm` (28px h) / `md` (36px h, default) / `lg` (44px h)
|
||||
|
||||
**States** (all must be handled):
|
||||
- `default` / `hover` / `active` / `focus-visible` / `disabled` / `loading`
|
||||
|
||||
**Loading state rule**:
|
||||
Show spinner + disable button immediately on click.
|
||||
Never let the button be clicked twice.
|
||||
```tsx
|
||||
// Correct
|
||||
<Button onClick={handleSubmit} loading={isSubmitting}>
|
||||
Save Changes
|
||||
</Button>
|
||||
|
||||
// Wrong — no loading state
|
||||
<Button onClick={handleSubmit} disabled={isSubmitting}>
|
||||
{isSubmitting ? 'Saving...' : 'Save Changes'}
|
||||
</Button>
|
||||
````
|
||||
|
||||
**Icon buttons**: Always include `aria-label`. Never use icon-only buttons for primary actions.
|
||||
|
||||
---
|
||||
|
||||
### Form Inputs
|
||||
|
||||
**Anatomy** (always in this order, no exceptions):
|
||||
|
||||
```
|
||||
[Label] ← always visible, never placeholder-only
|
||||
[Input field]
|
||||
[Helper text] ← optional, describes expected format
|
||||
[Error message] ← replaces helper text on error
|
||||
```
|
||||
|
||||
**States**: `default` / `focus` / `error` / `disabled` / `readonly`
|
||||
|
||||
**Rules**:
|
||||
|
||||
- Label always above input, never to the side (except checkbox/radio)
|
||||
- Placeholder text is NOT a label — both must exist
|
||||
- Error messages: specific and actionable ("Enter a valid email" not "Invalid input")
|
||||
- Required fields: mark with asterisk (*) next to label, explain at top of form
|
||||
- Never disable a submit button to prevent submission — show errors inline instead
|
||||
|
||||
---
|
||||
|
||||
### Data Table
|
||||
|
||||
```md
|
||||
### Table
|
||||
|
||||
**Default behavior**:
|
||||
- Sticky header on scroll
|
||||
- Row hover highlight
|
||||
- Checkbox column for bulk actions (leftmost)
|
||||
- Actions column (rightmost, visible on row hover only)
|
||||
- Empty state: illustration + message + CTA (never just "No data")
|
||||
|
||||
**Pagination**:
|
||||
- Default page size: 25 rows
|
||||
- Options: 10 / 25 / 50 / 100
|
||||
- Always show total count ("Showing 1–25 of 143 results")
|
||||
- Preserve page position on filter change
|
||||
|
||||
**Column rules**:
|
||||
- Numbers: right-aligned, monospace font
|
||||
- Dates: relative time for < 7 days ("2 hours ago"), absolute for older
|
||||
- Status: always a colored badge, never plain text
|
||||
- Long text: truncate with tooltip showing full value
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Modal / Dialog
|
||||
|
||||
```md
|
||||
### Modal
|
||||
|
||||
**Size variants**:
|
||||
| Size | Max-width | Use case |
|
||||
|-------|-----------|---------------------------|
|
||||
| `sm` | 400px | Confirmation dialogs |
|
||||
| `md` | 560px | Forms with < 5 fields |
|
||||
| `lg` | 720px | Complex forms, previews |
|
||||
| `xl` | 960px | Multi-step flows |
|
||||
|
||||
**Rules**:
|
||||
- Always trap focus inside modal
|
||||
- ESC key always closes (unless unsaved changes → show confirmation)
|
||||
- Click outside closes (unless form with unsaved changes)
|
||||
- Never nest modals — use a multi-step flow instead
|
||||
- Destructive confirm dialogs: danger button on RIGHT, cancel on LEFT
|
||||
- Never auto-close a modal after async action — wait for user to dismiss
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. 状态与反馈模式(State & Feedback Patterns)
|
||||
|
||||
````md
|
||||
## State & Feedback Patterns
|
||||
|
||||
### Loading States
|
||||
| Duration | Pattern |
|
||||
|---------------|--------------------------------|
|
||||
| < 300ms | Nothing (avoid flash of spinner)|
|
||||
| 300ms – 1s | Inline spinner |
|
||||
| 1s – 3s | Spinner + "Loading..." |
|
||||
| > 3s | Progress bar + estimated time |
|
||||
| Background | Subtle pulsing indicator in nav|
|
||||
|
||||
### Empty States
|
||||
Every list/table must handle empty state:
|
||||
```tsx
|
||||
// Required elements:
|
||||
// 1. Relevant icon (not a generic "no data" icon)
|
||||
// 2. Friendly headline ("No tasks yet")
|
||||
// 3. Explanation of why ("Projects with tasks will appear here")
|
||||
// 4. CTA if user can fix it ("Create your first task →")
|
||||
````
|
||||
|
||||
### Toast Notifications
|
||||
|
||||
|Type|When to use|Duration|
|
||||
|---|---|---|
|
||||
|`success`|Async action completed|3s|
|
||||
|`error`|Action failed, user must retry|persistent|
|
||||
|`warning`|Completed with caveats|5s|
|
||||
|`info`|Background process started|3s|
|
||||
|
||||
**Rules**:
|
||||
|
||||
- Max 3 toasts visible at once (queue the rest)
|
||||
- Never show success toast for page navigations
|
||||
- Error toasts must include a retry action when possible
|
||||
- Never use toast for validation errors — show inline instead
|
||||
|
||||
### Skeleton vs Spinner
|
||||
|
||||
- Skeleton: only for content with known layout (profile cards, feed items)
|
||||
- Spinner: for unknown-shape content, buttons, inline actions
|
||||
- Never both at the same time in the same view
|
||||
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
### 6. 响应式断点(Responsive Breakpoints)
|
||||
|
||||
```md
|
||||
## Responsive Breakpoints
|
||||
|
||||
**Strategy**: Desktop-first (our users are 85% desktop)
|
||||
|
||||
| Breakpoint | Token | Value | Target |
|
||||
|------------|--------|--------|--------------------------|
|
||||
| Desktop | (base) | > 1280px | Primary design target |
|
||||
| Laptop | `lg` | 1024px | Minor adjustments |
|
||||
| Tablet | `md` | 768px | Collapsed sidebar |
|
||||
| Mobile | `sm` | 640px | Single column, no tables |
|
||||
|
||||
**Component-specific rules**:
|
||||
- Data tables → horizontal scroll on `md` and below
|
||||
- Sidebar → collapses to bottom nav on `sm`
|
||||
- Modals → full-screen on `sm`
|
||||
- Multi-column forms → single column on `md` and below
|
||||
|
||||
**Never**:
|
||||
- Hide critical functionality on mobile (adapt it, don't remove it)
|
||||
- Use fixed px widths for layout containers
|
||||
- Assume touch input on desktop or mouse on mobile
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
### 7. 动效规范(Motion & Animation)
|
||||
|
||||
```md
|
||||
## Motion & Animation
|
||||
|
||||
**Principle**: Motion communicates state, it doesn't decorate.
|
||||
|
||||
**Duration scale**:
|
||||
```
|
||||
|
||||
--duration-fast: 100ms → micro-interactions (checkbox, toggle) --duration-normal: 200ms → most transitions (hover, focus) --duration-slow: 350ms → larger elements (modal, drawer enter) --duration-crawl: 500ms → only for page-level transitions
|
||||
|
||||
```
|
||||
|
||||
**Easing**:
|
||||
```
|
||||
|
||||
--ease-default: cubic-bezier(0.2, 0, 0, 1) → most UI transitions --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1) → playful elements only --ease-linear: linear → progress bars only
|
||||
|
||||
```
|
||||
|
||||
**What to animate**:
|
||||
- ✅ Opacity (enter/exit)
|
||||
- ✅ Transform: translateY (panel slide-in)
|
||||
- ✅ Max-height (accordion expand)
|
||||
|
||||
**Never animate**:
|
||||
- ❌ `width` or `height` directly (use `max-height` or `transform`)
|
||||
- ❌ `top/left/right/bottom` (use `transform: translate`)
|
||||
- ❌ `box-shadow` on hover (use opacity trick instead)
|
||||
- ❌ Anything if `prefers-reduced-motion: reduce`
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 8. 可访问性基线(Accessibility Baseline)
|
||||
|
||||
```md
|
||||
## Accessibility (Non-negotiable)
|
||||
|
||||
**Every component must**:
|
||||
- Meet WCAG 2.1 AA contrast ratios (4.5:1 body, 3:1 large text)
|
||||
- Be fully keyboard navigable
|
||||
- Have visible focus indicators (never `outline: none` without replacement)
|
||||
- Work with screen readers (proper ARIA roles and labels)
|
||||
|
||||
**Required patterns**:
|
||||
- Icon-only buttons: always `aria-label`
|
||||
- Form inputs: always `htmlFor` ↔ `id` pairing
|
||||
- Images: `alt` text always (empty string `""` for decorative images)
|
||||
- Modals: `role="dialog"`, `aria-modal="true"`, focus trap
|
||||
- Loading states: `aria-busy="true"` on the loading container
|
||||
- Error messages: `aria-describedby` linking input to error text
|
||||
|
||||
**Color alone is never enough**:
|
||||
- Status badges: color + icon + text
|
||||
- Form errors: color + icon + message below field
|
||||
- Graphs: color + pattern or label
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 9. 禁止模式(Anti-patterns)
|
||||
|
||||
```md
|
||||
## UI Anti-patterns — Never Do These
|
||||
|
||||
**Layout**:
|
||||
- ❌ Centering body text wider than 72 characters
|
||||
- ❌ Full-width buttons on desktop (max-width: 320px)
|
||||
- ❌ Mixing card and table layouts in the same list view
|
||||
|
||||
**Interaction**:
|
||||
- ❌ Double-click to perform actions (single click only)
|
||||
- ❌ Drag-and-drop as the *only* way to reorder
|
||||
- ❌ Hover-only affordances (invisible until you hover)
|
||||
- ❌ Auto-submitting forms on change without explicit confirmation
|
||||
|
||||
**Feedback**:
|
||||
- ❌ Generic error messages ("Something went wrong")
|
||||
- ❌ Success messages that don't tell the user what happened
|
||||
- ❌ Blocking UI with a spinner for optimistic actions
|
||||
- ❌ Alert dialogs (window.alert) — use our Dialog component
|
||||
|
||||
**Content**:
|
||||
- ❌ Lorem ipsum in any committed code
|
||||
- ❌ Hardcoded user names or emails in components
|
||||
- ❌ Placeholder images (use our Avatar initials fallback)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 优先级总结
|
||||
|
||||
|优先级|内容|为什么关键|
|
||||
|---|---|---|
|
||||
|🔴 必须|设计 Token(颜色、间距、圆角)|AI 最容易乱用原始数值|
|
||||
|🔴 必须|核心组件规范(Button、Input、Table)|高频生成,最容易出现不一致|
|
||||
|🔴 必须|状态与反馈模式|最能体现产品质感的细节|
|
||||
|🟡 重要|字体系统|防止 AI 混用字号和字重|
|
||||
|🟡 重要|可访问性基线|事后补救成本极高|
|
||||
|🟡 重要|禁止模式|比"应该做什么"更有效|
|
||||
|🟢 加分|动效规范|统一产品"手感"|
|
||||
|🟢 加分|响应式断点|避免断点不一致的多设备问题|
|
||||
|
||||
---
|
||||
|
||||
**核心原则**:`UI_SYSTEM.md` 不是设计文档,是给 AI 的**决策树**。当 AI 面对"这里用什么颜色?""这个按钮多大?""错误怎么展示?"时,答案必须在这里找到,不能靠猜。
|
||||
1265
Project/fonrey/UI&UX/组件清单.md
Normal file
BIN
Project/fonrey/screenshots/页面组件/Accordion Progress Panel.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
Project/fonrey/screenshots/页面组件/Collapsible Card Grid.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
Project/fonrey/screenshots/页面组件/Data Table.png
Normal file
|
After Width: | Height: | Size: 277 KiB |
BIN
Project/fonrey/screenshots/页面组件/Date Range Picker.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
Project/fonrey/screenshots/页面组件/Drawer Slide over.png
Normal file
|
After Width: | Height: | Size: 712 KiB |
BIN
Project/fonrey/screenshots/页面组件/Dynamic Form Table.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
Project/fonrey/screenshots/页面组件/Image Lightbox View.jpg
Normal file
|
After Width: | Height: | Size: 830 KiB |
BIN
Project/fonrey/screenshots/页面组件/Inline Edit Mode.png
Normal file
|
After Width: | Height: | Size: 157 KiB |
BIN
Project/fonrey/screenshots/页面组件/Modal Dialog.png
Normal file
|
After Width: | Height: | Size: 510 KiB |
|
After Width: | Height: | Size: 174 KiB |
BIN
Project/fonrey/screenshots/页面组件/Multi-select with Tag Input.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
Project/fonrey/screenshots/页面组件/Photo Gallery Manager 1.png
Normal file
|
After Width: | Height: | Size: 404 KiB |
BIN
Project/fonrey/screenshots/页面组件/Photo Gallery Manager 2.png
Normal file
|
After Width: | Height: | Size: 250 KiB |
|
After Width: | Height: | Size: 34 KiB |
BIN
Project/fonrey/screenshots/页面组件/Tab Navigation.png
Normal file
|
After Width: | Height: | Size: 174 KiB |
BIN
Project/fonrey/screenshots/页面组件/Tree Select Search 2.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
Project/fonrey/screenshots/页面组件/Tree Select.png
Normal file
|
After Width: | Height: | Size: 142 KiB |
@@ -1,10 +1,42 @@
|
||||
|
||||
- 文档根目录是:`~/Workspace/nexus`
|
||||
- 你是一名资深的后端架构师,请你参考读取 `raw/Agent/agency-agents/engineering/engineering-backend-architect.md` 并用该文档提及的架构师方面的技能和方法论帮设计系统
|
||||
- 我希望的技术栈如下:
|
||||
- Frontend: HTMX + Alpine.js + Tailwind CSS
|
||||
- Backend: Django 4.x (ASGI mode)
|
||||
- Multi-tenant: django-tenants (Postgres schema isolation)
|
||||
- Database: PostgreSQL + PgBouncer
|
||||
- Cache: Redis
|
||||
- Tasks: Celery + Celery Beat
|
||||
- Storage: Cloudflare R2 (or AWS S3)
|
||||
- CDN: Cloudflare
|
||||
- Server: Gunicorn + Uvicorn workers + Nginx
|
||||
- Monitoring: Sentry + Grafana
|
||||
- 部署方式: Docker Compose
|
||||
- 代码管理: Git
|
||||
- 编程方式: Vibe Coding
|
||||
- 在做技术选型时,我分析了页面的组件并记录在 `Project/fonrey/UI&UX/组件清单.md`里
|
||||
- 项目概览
|
||||
- **系统名称**:Fonrey 房产经纪管理系统
|
||||
- **已有 PRD 模块**:房源管理(v2.1)、客源管理(v1.4)、楼盘管理(v1.0)、系统设置(v1.0),均为 Draft 状态
|
||||
- **房源管理**:支持住宅/别墅/商铺/商住/写字楼/其他 6 种房源类型(P0 住宅,P1 别墅,商业类低优先级);核心功能含录入、跟进、图片管理、价格解读、市场报盘、附件、业主联系人;目标 89,000+ 条数据量级
|
||||
- **客源管理**:管理购房/租房意向客户(私客为核心,公客/成交客后续版本);功能含录入私客、智能配房、跟进记录、活跃度分层、转公客/转成交/转无效、联系人管理、操作日志
|
||||
- **楼盘管理**:楼盘为房源基础数据底座;功能含楼盘列表、楼盘详情(楼盘信息/楼栋管理/结构管理/照片/价格走势/周边配套)、区域管理(城区/商圈/关联关系)、学校管理;聚焦二手房
|
||||
- **系统设置**:平台"控制中心";本期聚焦首页设置与房源设置(字段标签、必填规则、自定义字段、标签管理);其余设置(客源/交易/财务/人事OA/合同/通用/移动端/安装登录)在各自模块 PRD 中说明
|
||||
- 所有模块均为 Web 端,移动端适配为 v2 规划
|
||||
- **目标用户**:一线经纪人(高频)、店长/经理(每日)、运营/行政人员(每日)、系统管理员(不定期)
|
||||
- 具体项目PRD文档`Project/fonrey/PRD/*.md`
|
||||
- 请根据TECH_STAK文档要求 `Project/fonrey/TECH_STACK/TECH_STACK 文档要求`帮我设计TECH_STACK文档 输出到`Project/fonrey/TECH_STACK/`目录下
|
||||
|
||||
|
||||
|
||||
|
||||
## 系统提示词
|
||||
- 文档根目录是:`~/Workspace/nexus`
|
||||
- 你是一名资深的产品经理和产品需求分析师,现在我要你根据我提供的产品截图和信息帮我分析产品功能需求并写成需求文档
|
||||
- 请你参考读取 `raw/Agent/agency-agents/product/product-manager.md` 并用该文档提及的产品经理专业知识和方法论帮我进行需求分析
|
||||
- 我的项目是开发一套房产经纪管理系统(Fonrey), 主要的功能是包含房源管理,客源管理以及基本的组织管理/人员管理/权限管理等。我现在有一套成熟系统的截图,我希望你根据我提供的截图和我提供的信息来分析具体的需求并写成专业的文档。
|
||||
- 现阶段已经完成`Project/fonrey/PRD/房源管理模块PRD.md`, `Project/fonrey/PRD/客源管理模块PRD.md`和``Project/fonrey/PRD/楼盘管理模块PRD.md``,你可以参考该文档格式及目录结构并继续根据以下提供的内容撰写需求文档
|
||||
- 现阶段已经完成`Project/fonrey/PRD/房源管理模块PRD.md`, `Project/fonrey/PRD/客源管理模块PRD.md`你可以参考该文档格式及目录结构并继续根据以下提供的内容撰写需求文档
|
||||
- 现在请你继续分析楼盘管理 并写入`Project/fonrey/PRD/系统设置模块PRD.md`
|
||||
|
||||
- 我提供的截图有分不同的模块:
|
||||
@@ -179,4 +211,22 @@
|
||||
- 客源相关方设置:`Project/fonrey/screenshots/设置/客源设置-客源相关方配置.png`
|
||||
- 客源行政跨部门权限:`Project/fonrey/screenshots/设置/客源设置-客源行政跨部门权限.png`
|
||||
- 人事OA设置
|
||||
- 组织人事基本设置:`Project/fonrey/screenshots/设置/人事OA设置-组织人事设置.png`
|
||||
- 组织人事基本设置:`Project/fonrey/screenshots/设置/人事OA设置-组织人事设置.png`
|
||||
|
||||
|
||||
|
||||
## 项目概况
|
||||
请根据我的PRD 文档`Project/fonrey/PRD/*.md` 里面描述的项目功能帮我写一个项目概况用于快速介绍这个项目
|
||||
|
||||
|
||||
## 技术栈
|
||||
- Frontend: HTMX + Alpine.js + Tailwind CSS
|
||||
- Backend: Django 4.x (ASGI mode)
|
||||
- Multi-tenant: django-tenants (Postgres schema isolation)
|
||||
- Database: PostgreSQL + PgBouncer
|
||||
- Cache: Redis
|
||||
- Tasks: Celery + Celery Beat
|
||||
- Storage: Cloudflare R2 (or AWS S3)
|
||||
- CDN: Cloudflare
|
||||
- Server: Gunicorn + Uvicorn workers + Nginx
|
||||
- Monitoring: Promethues + Grafana
|
||||
77
Project/fonrey/核心文档体系.md
Normal file
@@ -0,0 +1,77 @@
|
||||
### 1. 产品愿景与 MVP 范围书 (`PRD_MVP.md`)
|
||||
|
||||
AI 需要知道“终点”在哪里,以及“当前阶段”的界限。
|
||||
|
||||
- **核心功能清单:** 明确第一阶段(MVP)必须实现的 3-5 个核心功能。
|
||||
|
||||
- **非目标 (Out of Scope):** 明确哪些功能在 MVP 阶段**绝对不做**,防止 Claude 在生成代码时过度设计。
|
||||
|
||||
- **用户故事:** 简单的 `As a [user], I want to [action], so that [value]`,这有助于 Claude 理解业务逻辑的优先级。
|
||||
|
||||
|
||||
### 2. 技术栈与规范定义 (`TECH_STACK.md`)
|
||||
|
||||
Vibe Coding 最怕 AI 随意引入不兼容的库。
|
||||
|
||||
- **固定技术栈:** 例如 Frontend (Next.js 14, Tailwind), Backend (Supabase/PostgreSQL), Auth (Clerk)。
|
||||
|
||||
- **代码风格:** 比如“使用 Functional Components”、“优先使用 TypeScript 严格模式”、“所有的 API 调用必须遵循 RESTful 规范”。
|
||||
|
||||
- **项目结构:** 预定义文件夹结构(如 `/components`, `/hooks`, `/lib`, `/types`),让 AI 生成的代码能够准确归位。
|
||||
|
||||
|
||||
### 3. 领域模型与数据库 Schema (`DATA_MODEL.md`)
|
||||
|
||||
这是项目的“骨架”。即便你使用 NoSQL,也要先定义好数据关系。
|
||||
|
||||
- **实体关系图 (ERD):** 描述 User, Project, Task 等实体的关系。
|
||||
|
||||
- **Schema 定义:** 提供 SQL DDL 或 Prisma Schema 示例。
|
||||
|
||||
- **核心业务状态机:** 如果有复杂逻辑(如订单状态、工作流状态),定义好状态转换矩阵。
|
||||
|
||||
|
||||
### 4. UI/UX 风格与组件指南 (`UI_SYSTEM.md`)
|
||||
|
||||
为了让生成的页面不至于太丑或不统一:
|
||||
|
||||
- **设计语言:** 明确使用哪个组件库(如 shadcn/ui, Ant Design)。
|
||||
|
||||
- **核心页面路由:** 定义 MVP 阶段的所有 URL 路径及对应的功能页面。
|
||||
|
||||
- **全局布局:** 描述 Header, Sidebar, Footer 的行为。
|
||||
|
||||
|
||||
### 5. AI 指令手册 (`.cursorrules` 或 `AI_INSTRUCTIONS.md`)
|
||||
|
||||
这是 Vibe Coding 的“灵魂”,专门给 Claude 看的“说明书”。
|
||||
|
||||
- **角色设定:** “你是一个资深的 Full-stack Engineer,擅长编写可维护的、高性能的 React 代码。”
|
||||
|
||||
- **禁止事项:** “禁止使用任何未在 TECH_STACK.md 中定义的第三方库。”
|
||||
|
||||
- **报错处理:** “如果遇到错误,优先检查类型定义,并输出详细的 Debug Log。”
|
||||
|
||||
## 针对 Vibe Coding 的特化建议
|
||||
|
||||
### 1. 采用“模块化文档”而非“长篇大论”
|
||||
|
||||
不要给 Claude 一个 5000 字的文档。将文档拆分为上述的 `.md` 文件。在对话时,使用 `@` 功能(在 Cursor/OpenCode 中)按需引用。例如:“基于 `@DATA_MODEL.md` 实现 `@PRD_MVP.md` 中的用户注册流程。”
|
||||
|
||||
### 2. 准备“上下文脚手架”
|
||||
|
||||
在开始第一行代码前,先让 Claude 生成一个 `README.md`,概括整个项目的架构。这会成为后续对话中最重要的上下文参考。
|
||||
|
||||
### 3. 动态更新的“决策记录” (`ADR.md`)
|
||||
|
||||
在 Vibe Coding 过程中,AI 可能会建议一些架构改动。一旦你接受了某个改动,**立即**记录在 `Architecture Decision Records (ADR)` 中。这样当你在后续对话中开启新 Session 时,可以把这个文档丢给它,避免它推翻之前的设计方案。
|
||||
|
||||
---
|
||||
|
||||
## 建议的执行流程
|
||||
|
||||
1. **初始化阶段:** 编写上述 5 份 Markdown 文档。
|
||||
|
||||
2. **环境对齐:** 将文档喂给 Claude,问它:“基于这些文档,你认为实现 MVP 的第一步是什么?请列出任务清单。”
|
||||
|
||||
3. **循环迭代:** 按照 `任务清单 -> 生成代码 -> 测试反馈 -> 更新文档` 的循环进行。
|
||||