---
category: schema
title: Parse Server 数据范式文档
subtitle: 项目管理系统数据表结构
name: 'project-schema'
label: database
---

# Parse Server 数据范式 - 项目管理系统

## 概述

本文档详细描述了 nova-project 项目管理系统中使用的 Parse Server 数据表结构，包括表结构、字段说明、关系映射和使用场景。

系统采用**多租户架构**，以 Company 为核心，支持项目管理、任务管理、产品需求管理、OKR目标管理和知识文档管理。

---

## 数据表关系图

### 整体架构（PlantUML）

```plantuml
@startuml
!define TABLE(name,desc) class name as "desc" << (T,#FFAAAA) >>
!define FIELD(name,type) name : type

skinparam classAttributeIconSize 0
skinparam class {
    BackgroundColor LightYellow
    BorderColor Black
    ArrowColor Black
}

' ============ 核心实体 ============
TABLE(Company, "Company\n企业表") {
    FIELD(objectId, String)
    FIELD(name, String)
    FIELD(project, Pointer)
    FIELD(devModule, Array)
    FIELD(isDeleted, Boolean)
    FIELD(createdAt, Date)
    FIELD(updatedAt, Date)
}

TABLE(Profile, "Profile\n用户档案表") {
    FIELD(objectId, String)
    FIELD(name, String)
    FIELD(mobile, String)
    FIELD(email, String)
    FIELD(company, Pointer→Company)
    FIELD(department, Pointer→Department)
    FIELD(user, Pointer→_User)
    FIELD(identyType, String)
    FIELD(isDeleted, Boolean)
    FIELD(createdAt, Date)
    FIELD(updatedAt, Date)
}

TABLE(Department, "Department\n部门表") {
    FIELD(objectId, String)
    FIELD(name, String)
    FIELD(type, String)
    FIELD(company, Pointer→Company)
    FIELD(parent, Pointer→Department)
    FIELD(num, Number)
    FIELD(index, Number)
    FIELD(isDeleted, Boolean)
    FIELD(createdAt, Date)
    FIELD(updatedAt, Date)
}

' ============ 项目模块 ============
TABLE(Project, "Project\n项目表") {
    FIELD(objectId, String)
    FIELD(title, String)
    FIELD(type, String)
    FIELD(company, Pointer→Company)
    FIELD(owner, Pointer→Profile)
    FIELD(defaultTab, String)
    FIELD(isClosed, Boolean)
    FIELD(isStar, Boolean)
    FIELD(isStarted, Boolean)
    FIELD(isDeleted, Boolean)
    FIELD(createdAt, Date)
    FIELD(updatedAt, Date)
}

TABLE(ProjectTask, "ProjectTask\n任务表") {
    FIELD(objectId, String)
    FIELD(title, String)
    FIELD(project, Pointer→Project)
    FIELD(company, Pointer→Company)
    FIELD(assignee, Pointer→Profile)
    FIELD(owner, Pointer→Profile)
    FIELD(parent, Pointer→ProjectTask)
    FIELD(priority, Number)
    FIELD(stateList, String)
    FIELD(stateLane, String)
    FIELD(startDate, Date)
    FIELD(endDate, Date)
    FIELD(deadline, Date)
    FIELD(duration, Number)
    FIELD(estimate, Number)
    FIELD(progress, Number)
    FIELD(tag, Array)
    FIELD(desc, String)
    FIELD(cate, String)
    FIELD(isClosed, Boolean)
    FIELD(isDeleted, Boolean)
    FIELD(createdAt, Date)
    FIELD(updatedAt, Date)
}

TABLE(ProjectTeam, "ProjectTeam\n项目团队表") {
    FIELD(objectId, String)
    FIELD(project, Pointer→Project)
    FIELD(profile, Pointer→Profile)
    FIELD(role, String)
    FIELD(isDeleted, Boolean)
    FIELD(createdAt, Date)
}

TABLE(Product, "Product\n产品表") {
    FIELD(objectId, String)
    FIELD(title, String)
    FIELD(project, Pointer→Project)
    FIELD(company, Pointer→Company)
    FIELD(isDeleted, Boolean)
    FIELD(createdAt, Date)
    FIELD(updatedAt, Date)
}

TABLE(ProductRequire, "ProductRequire\n产品需求表") {
    FIELD(objectId, String)
    FIELD(title, String)
    FIELD(type, String)
    FIELD(project, Pointer→Project)
    FIELD(company, Pointer→Company)
    FIELD(product, Pointer→Product)
    FIELD(module, Pointer→ProductRequire)
    FIELD(parent, Pointer→ProductRequire)
    FIELD(isDeleted, Boolean)
    FIELD(createdAt, Date)
    FIELD(updatedAt, Date)
}

' ============ OKR模块 ============
TABLE(OKR, "OKR\nOKR周期表") {
    FIELD(objectId, String)
    FIELD(title, String)
    FIELD(company, Pointer→Company)
    FIELD(startDate, Date)
    FIELD(endDate, Date)
    FIELD(isDeleted, Boolean)
    FIELD(createdAt, Date)
    FIELD(updatedAt, Date)
}

TABLE(OKRObject, "OKRObject\nOKR对象表") {
    FIELD(objectId, String)
    FIELD(title, String)
    FIELD(type, String)
    FIELD(okr, Pointer→OKR)
    FIELD(company, Pointer→Company)
    FIELD(department, Pointer→Department)
    FIELD(profile, Pointer→Profile)
    FIELD(tree, Pointer→OKRObject)
    FIELD(parent, Pointer→OKRObject)
    FIELD(bsc, String)
    FIELD(value, Number)
    FIELD(unit, String)
    FIELD(index, Number)
    FIELD(isDeleted, Boolean)
    FIELD(createdAt, Date)
    FIELD(updatedAt, Date)
}

' ============ 知识库模块 ============
TABLE(NoteSpace, "NoteSpace\n知识空间表") {
    FIELD(objectId, String)
    FIELD(title, String)
    FIELD(type, String)
    FIELD(company, Pointer→Company)
    FIELD(project, Pointer→Project)
    FIELD(isDeleted, Boolean)
    FIELD(createdAt, Date)
    FIELD(updatedAt, Date)
}

TABLE(NotePad, "NotePad\n文档笔记表") {
    FIELD(objectId, String)
    FIELD(title, String)
    FIELD(space, Pointer→NoteSpace)
    FIELD(profile, Pointer→Profile)
    FIELD(parent, Pointer→NotePad)
    FIELD(content, String)
    FIELD(isDeleted, Boolean)
    FIELD(createdAt, Date)
    FIELD(updatedAt, Date)
}

' ============ 关系连线 ============

' Company 一对多关系
Company "1" --> "n" Profile : 企业员工
Company "1" --> "n" Department : 企业部门
Company "1" --> "n" Project : 企业项目
Company "1" --> "n" OKR : OKR周期

' Profile 关系
Profile "n" --> "1" Department : 所属部门
Profile "1" --> "n" ProjectTask : assignee\n执行任务
Profile "1" --> "n" ProjectTask : owner\n创建任务
Profile "1" --> "n" NotePad : 创建笔记

' Department 树状结构
Department "1" --> "n" Department : parent\n上下级

' Project 相关
Project "n" --> "1" Profile : owner\n项目负责人
Project "1" --> "n" ProjectTask : 项目任务
Project "1" --> "n" Product : 项目产品
Project "1" --> "1" NoteSpace : Wiki空间
Project "n" <--> "n" Profile : ProjectTeam\n团队成员

' ProjectTask 树状结构
ProjectTask "1" --> "n" ProjectTask : parent\n父子任务

' Product 相关
Product "1" --> "n" ProductRequire : 产品需求

' ProductRequire 树状结构
ProductRequire "1" --> "n" ProductRequire : module/parent\n层级结构

' OKR 相关
OKR "1" --> "n" OKRObject : OKR对象
OKRObject "n" --> "1" Department : 部门OKR
OKRObject "n" --> "1" Profile : 个人OKR
OKRObject "1" --> "n" OKRObject : tree/parent\n指标树

' NoteSpace 相关
NoteSpace "1" --> "n" NotePad : 空间笔记

' NotePad 树状结构
NotePad "1" --> "n" NotePad : parent\n目录层级

@enduml
```

---

## 数据表详细说明

### 1. Company（企业表）

**用途**: 多租户系统的核心，所有数据通过 company 字段进行租户隔离。

**表结构**:

| 字段名 | 类型 | 必填 | 说明 | 示例值 |
|--------|------|------|------|--------|
| objectId | String | 是 | 主键ID | "1AiWpTEDH9" |
| name | String | 是 | 企业名称 | "科技有限公司" |
| project | Pointer | 否 | 关联项目 | → Project |
| devModule | Array | 否 | 开发模块配置 | ["module1", "module2"] |
| isDeleted | Boolean | 否 | 软删除标记 | false |
| createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z |
| updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z |

**关系**:
- 一对多: Company → Profile（企业员工）
- 一对多: Company → Department（企业部门）
- 一对多: Company → Project（企业项目）
- 一对多: Company → OKR（OKR周期）

**使用场景**:
```typescript
// 获取当前企业ID
const companyId = localStorage.getItem("Parse/CompanyId") || localStorage.getItem("company");

// 数据隔离查询
const query = new Parse.Query("Project");
query.equalTo("company", companyId);
```

**索引建议**:
- `objectId` (主键，自动索引)
- `name`

---

### 2. Profile（用户档案表）

**用途**: 存储用户在企业内的档案信息，关联 Parse 内置 _User 表。

**表结构**:

| 字段名 | 类型 | 必填 | 说明 | 示例值 |
|--------|------|------|------|--------|
| objectId | String | 是 | 主键ID | "abc123xyz" |
| name | String | 是 | 用户姓名 | "张三" |
| mobile | String | 否 | 手机号 | "13800138000" |
| email | String | 否 | 邮箱 | "zhangsan@example.com" |
| company | Pointer | 是 | 所属企业 | → Company |
| department | Pointer | 否 | 所属部门 | → Department |
| user | Pointer | 否 | 关联Parse用户 | → _User |
| identyType | String | 否 | 身份类型 | "admin" / "coders" |
| isDeleted | Boolean | 否 | 软删除标记 | false |
| createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z |
| updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z |

**identyType 枚举值**:
- `admin`: 管理员权限
- `coders`: 开发者权限
- 其他: 普通用户权限

**关系**:
- 多对一: Profile → Company（所属企业）
- 多对一: Profile → Department（所属部门）
- 多对一: Profile → _User（关联用户账号）
- 一对多: Profile ← ProjectTask (assignee, 执行任务)
- 一对多: Profile ← ProjectTask (owner, 创建任务)
- 多对多: Profile ←→ Project（通过 ProjectTeam）

**使用场景**:
```typescript
// 获取当前用户档案ID
const profileId = localStorage.getItem("Parse/ProfileId");

// 查询用户创建的任务
const query = new Parse.Query("ProjectTask");
query.equalTo("owner", profileId);

// 查询用户执行的任务
const query2 = new Parse.Query("ProjectTask");
query2.equalTo("assignee", profileId);

// 搜索用户（模糊查询）
const query3 = new Parse.Query("Profile");
query3.matches("name", keyword, "i"); // 不区分大小写
query3.matches("mobile", keyword, "i");
```

**索引建议**:
- `company + isDeleted`
- `name + company`
- `mobile + company`
- `user`

---

### 3. Department（部门表）

**用途**: 组织架构管理，支持树状结构（多层级部门）。

**表结构**:

| 字段名 | 类型 | 必填 | 说明 | 示例值 |
|--------|------|------|------|--------|
| objectId | String | 是 | 主键ID | "dept001" |
| name | String | 是 | 部门名称 | "技术部" |
| type | String | 是 | 类型 | "depart" |
| company | Pointer | 是 | 所属企业 | → Company |
| parent | Pointer | 否 | 父部门 | → Department |
| num | Number | 否 | 排序号 | 1 |
| index | Number | 否 | 索引 | 100 |
| isDeleted | Boolean | 否 | 软删除标记 | false |
| createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z |
| updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z |

**关系**:
- 多对一: Department → Company（所属企业）
- 树状结构: Department → Department (parent, 支持多层级)
- 一对多: Department ← Profile（部门员工）
- 一对多: Department ← OKRObject（部门OKR）

**使用场景**:
```typescript
// 查询企业所有部门
const query = new Parse.Query("Department");
query.equalTo("company", companyId);
query.notEqualTo("isDeleted", true);
query.ascending("num"); // 按排序号排序

// 查询一级部门（没有父级）
const rootQuery = new Parse.Query("Department");
rootQuery.equalTo("company", companyId);
rootQuery.doesNotExist("parent"); // parent 为空

// 查询某部门的子部门
const childQuery = new Parse.Query("Department");
childQuery.equalTo("parent", parentDeptId);
```

**索引建议**:
- `company + isDeleted`
- `parent + company`
- `num + company`

---

### 4. Project（项目表）

**用途**: 项目管理的核心表，支持多种类型项目。

**表结构**:

| 字段名 | 类型 | 必填 | 说明 | 示例值 |
|--------|------|------|------|--------|
| objectId | String | 是 | 主键ID | "proj001" |
| title | String | 是 | 项目标题 | "CRM系统开发" |
| type | String | 否 | 项目类型 | "project" / "book" / "plan" / "module" |
| company | Pointer | 是 | 所属企业 | → Company |
| owner | Pointer | 是 | 项目负责人 | → Profile |
| defaultTab | String | 否 | 默认Tab页 | "gantt" / "kanban" / "wiki" |
| isClosed | Boolean | 否 | 是否已关闭 | false |
| isStar | Boolean | 否 | 是否星标 | false |
| isStarted | Boolean | 否 | 是否已启动 | true |
| isDeleted | Boolean | 否 | 软删除标记 | false |
| createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z |
| updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z |

**type 枚举值**:
- `project`: 项目平台
- `book`: 电子书籍
- `plan`: 行动策略
- `module`: 功能模块

**关系**:
- 多对一: Project → Company（所属企业）
- 多对一: Project → Profile (owner, 项目负责人)
- 一对多: Project → ProjectTask（项目任务）
- 一对多: Project → Product（项目产品）
- 一对多: Project → ProductRequire（项目需求）
- 一对一: Project → NoteSpace（Wiki空间）
- 多对多: Project ←→ Profile（通过 ProjectTeam）

**使用场景**:
```typescript
// 查询项目
const query = new Parse.Query("Project");
await query.get(projectId);

// 查询用户创建的项目
const myQuery = new Parse.Query("Project");
myQuery.equalTo("owner", profileId);
myQuery.notEqualTo("isDeleted", true);

// 查询星标项目
const starQuery = new Parse.Query("Project");
starQuery.equalTo("isStar", true);
starQuery.equalTo("company", companyId);

// 按类型筛选
const typeQuery = new Parse.Query("Project");
typeQuery.containedIn("type", ["project", "module"]);

// 查询用户参与的项目（通过 ProjectTeam）
const teamQuery = new Parse.Query("ProjectTeam");
teamQuery.equalTo("profile", profileId);
teamQuery.include("project");
const teams = await teamQuery.find();
const projects = teams.map(team => team.get("project"));
```

**索引建议**:
- `company + isDeleted`
- `owner + company`
- `isStar + company`
- `isStarted + company`
- `type + company`
- `updatedAt` (降序)

---

### 5. ProjectTask（项目任务表）

**用途**: 存储项目任务，支持甘特图、看板等多种视图，支持父子任务。

**表结构**:

| 字段名 | 类型 | 必填 | 说明 | 示例值 |
|--------|------|------|------|--------|
| objectId | String | 是 | 主键ID | "task001" |
| title | String | 是 | 任务标题 | "实现用户登录功能" |
| desc | String | 否 | 任务描述 | "包括前端页面和后端API" |
| project | Pointer | 是 | 所属项目 | → Project |
| company | Pointer | 是 | 所属企业 | → Company |
| assignee | Pointer | 否 | 任务执行人 | → Profile |
| owner | Pointer | 是 | 任务创建人 | → Profile |
| parent | Pointer | 否 | 父任务 | → ProjectTask |
| priority | Number | 否 | 优先级 | 1 / 50 / 70 / 90 / 100 |
| stateList | String | 否 | 任务状态 | "待分配" / "进行中" / "测试中" / "已完成" / "已上线" |
| stateLane | String | 否 | 看板泳道 | "默认泳道" |
| startDate | Date | 是 | 开始时间 | 2024-01-01T00:00:00.000Z |
| endDate | Date | 否 | 结束时间 | 2024-01-10T00:00:00.000Z |
| deadline | Date | 否 | 截止时间 | 2024-01-15T00:00:00.000Z |
| duration | Number | 否 | 实际工时(小时) | 8.5 |
| estimate | Number | 否 | 预估工时(小时) | 10 |
| progress | Number | 否 | 完成进度(0-100) | 75 |
| tag | Array | 否 | 标签数组 | ["前端", "紧急"] |
| cate | String | 否 | 工作分类 | "frontend" / "backend" / "design" / "testing" |
| target | String | 否 | 排序目标ID | 用于甘特图排序 |
| remark | String | 否 | 备注 | "需要先完成设计稿" |
| approver | Pointer | 否 | 审批人 | → Profile |
| approvalDate | Date | 否 | 审批日期 | 2024-01-10T00:00:00.000Z |
| isClosed | Boolean | 否 | 是否已关闭 | false |
| isDeleted | Boolean | 否 | 软删除标记 | false |
| createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z |
| updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z |

**priority 枚举值**:
- `1`: 最低
- `50`: 普通（默认）
- `70`: 较高
- `90`: 重要
- `100`: 严重

**stateList 枚举值**:
```
待分配 → 进行中 → 测试中 → 已完成 → 已上线
```

**cate 枚举值**:
- `requirement`: 需求
- `frontend`: 前端开发
- `backend`: 后端开发
- `design`: 设计
- `testing`: 测试

**关系**:
- 多对一: ProjectTask → Project（所属项目）
- 多对一: ProjectTask → Company（所属企业）
- 多对一: ProjectTask → Profile (assignee, 执行人)
- 多对一: ProjectTask → Profile (owner, 创建人)
- 多对一: ProjectTask → Profile (approver, 审批人)
- 树状结构: ProjectTask → ProjectTask (parent, 父子任务)

**使用场景**:
```typescript
// 查询项目任务
const query = new Parse.Query("ProjectTask");
query.equalTo("project", projectId);
query.notEqualTo("isDeleted", true);
query.notEqualTo("isClosed", true);
query.descending("startDate");
query.include("assignee", "owner");

// 查询用户的任务
const myTaskQuery = new Parse.Query("ProjectTask");
myTaskQuery.equalTo("assignee", profileId);
myTaskQuery.notEqualTo("isDeleted", true);

// 按状态筛选
const stateQuery = new Parse.Query("ProjectTask");
stateQuery.containedIn("stateList", ["进行中", "测试中"]);

// 查询即将到期的任务
const today = new Date();
const endDate = new Date();
endDate.setDate(endDate.getDate() + 7); // 7天内到期
const deadlineQuery = new Parse.Query("ProjectTask");
deadlineQuery.greaterThanOrEqualTo("deadline", today);
deadlineQuery.lessThan("deadline", endDate);
deadlineQuery.notContainedIn("stateList", ["已完成", "已上线"]);

// 查询用户参与的所有项目（SQL方式）
const sql = `
SELECT DISTINCT(task."project"), pro."title" AS "name"
FROM "ProjectTask" task
LEFT JOIN "Project" pro ON pro."objectId" = task."project"
WHERE task."isDeleted" IS NOT TRUE
  AND task."isClosed" IS NOT TRUE
  AND (task."assignee" = '${profileId}' OR task."owner" = '${profileId}')
  AND task."project" IS NOT NULL
`;
```

**工时统计（SQL）**:
```sql
-- 用户工时统计
SELECT
    pt."assignee",
    SUM(pt."d") as duration,      -- 实际工时
    SUM(pt."e") as estimate        -- 预估工时
FROM (
    SELECT *,
    CASE WHEN "ProjectTask"."duration" IS NOT NULL
         THEN "ProjectTask"."duration" ELSE 0 END as d,
    CASE WHEN "ProjectTask"."estimate" IS NOT NULL
         THEN "ProjectTask"."estimate" ELSE 0 END as e
    FROM "ProjectTask"
    WHERE "company" = $1
      AND ("isDeleted" != true OR "isDeleted" IS NULL)
      AND "startDate" >= $2
      AND "startDate" < $3
) as pt
GROUP BY pt."assignee"
```

**索引建议**:
- `project + isDeleted`
- `assignee + isDeleted`
- `owner + isDeleted`
- `company + startDate`
- `priority` (降序)
- `stateList + project`
- `deadline + stateList`

---

### 6. ProjectTeam（项目团队表）

**用途**: 管理项目成员关系，实现项目与用户的多对多关联。

**表结构**:

| 字段名 | 类型 | 必填 | 说明 | 示例值 |
|--------|------|------|------|--------|
| objectId | String | 是 | 主键ID | "team001" |
| project | Pointer | 是 | 所属项目 | → Project |
| profile | Pointer | 是 | 团队成员 | → Profile |
| role | String | 否 | 成员角色 | "开发" / "测试" / "PM" |
| isDeleted | Boolean | 否 | 软删除标记 | false |
| createdAt | Date | 自动 | 加入时间 | 2024-01-01T00:00:00.000Z |

**关系**:
- 多对一: ProjectTeam → Project
- 多对一: ProjectTeam → Profile
- 实现: Project ←→ Profile 的多对多关系

**使用场景**:
```typescript
// 查询项目成员
const query = new Parse.Query("ProjectTeam");
query.equalTo("project", projectId);
query.notEqualTo("isDeleted", true);
query.include("profile");
const members = await query.find();

// 查询用户参与的项目
const myProjectQuery = new Parse.Query("ProjectTeam");
myProjectQuery.equalTo("profile", profileId);
myProjectQuery.notEqualTo("isDeleted", true);
myProjectQuery.include("project");
myProjectQuery.select("project");
const teams = await myProjectQuery.find();
const projects = teams.map(team => team.get("project"));

// 添加项目成员
const ProjectTeam = Parse.Object.extend("ProjectTeam");
const team = new ProjectTeam();
team.set("project", project.toPointer());
team.set("profile", profile.toPointer());
team.set("role", "开发");
await team.save();
```

**索引建议**:
- `project + isDeleted`
- `profile + isDeleted`
- `project + profile` (联合唯一索引)

---

### 7. Product（产品表）

**用途**: 项目下的产品管理。

**表结构**:

| 字段名 | 类型 | 必填 | 说明 | 示例值 |
|--------|------|------|------|--------|
| objectId | String | 是 | 主键ID | "prod001" |
| title | String | 是 | 产品名称 | "移动端APP" |
| project | Pointer | 是 | 所属项目 | → Project |
| company | Pointer | 是 | 所属企业 | → Company |
| isDeleted | Boolean | 否 | 软删除标记 | false |
| createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z |
| updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z |

**关系**:
- 多对一: Product → Project（所属项目）
- 多对一: Product → Company（所属企业）
- 一对多: Product → ProductRequire（产品需求/模块）

**使用场景**:
```typescript
// 查询项目的产品列表
const query = new Parse.Query("Product");
query.equalTo("project", projectId);
query.addDescending("updatedAt");
const products = await query.find();

// 创建产品
const Product = Parse.Object.extend("Product");
const product = new Product();
product.set("title", "Web管理后台");
product.set("project", project.toPointer());
product.set("company", company.toPointer());
await product.save();
```

**索引建议**:
- `project + isDeleted`
- `company + isDeleted`
- `updatedAt` (降序)

---

### 8. ProductRequire（产品需求表）

**用途**: 支持模块化的需求管理，可构建树状结构（模块→子模块→需求）。

**表结构**:

| 字段名 | 类型 | 必填 | 说明 | 示例值 |
|--------|------|------|------|--------|
| objectId | String | 是 | 主键ID | "req001" |
| title | String | 是 | 需求/模块名称 | "用户管理模块" |
| type | String | 是 | 类型 | "module" / "require" |
| project | Pointer | 是 | 所属项目 | → Project |
| company | Pointer | 是 | 所属企业 | → Company |
| product | Pointer | 否 | 所属产品 | → Product |
| module | Pointer | 否 | 所属模块 | → ProductRequire |
| parent | Pointer | 否 | 父级 | → ProductRequire |
| isDeleted | Boolean | 否 | 软删除标记 | false |
| createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z |
| updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z |

**type 枚举值**:
- `module`: 功能模块（可以有子模块）
- `require`: 具体需求（归属于某个模块）

**树状结构说明**:
- 一级模块: type="module", module=null, parent=null
- 二级模块: type="module", module=一级模块ID, parent=一级模块ID
- 具体需求: type="require", module=所属模块ID

**关系**:
- 多对一: ProductRequire → Project（所属项目）
- 多对一: ProductRequire → Company（所属企业）
- 多对一: ProductRequire → Product（所属产品）
- 树状结构: ProductRequire → ProductRequire (module/parent)

**使用场景**:
```typescript
// 查询项目的模块列表
const moduleQuery = new Parse.Query("ProductRequire");
moduleQuery.equalTo("project", projectId);
moduleQuery.equalTo("type", "module");
moduleQuery.addDescending("updatedAt");
const modules = await moduleQuery.find();

// 查询某产品下的需求
const requireQuery = new Parse.Query("ProductRequire");
requireQuery.equalTo("project", projectId);
requireQuery.equalTo("type", "require");
requireQuery.equalTo("product", productId);
requireQuery.limit(1000);
const requires = await requireQuery.find();

// 查询某模块及其子模块的所有需求
function getModulePathIds(module, allModules) {
  let ids = [module.id];
  allModules.forEach(mitem => {
    if (mitem.get("module")?.id == module.id) {
      ids.push(mitem.id);
    }
    if (mitem.get("parent")?.id == module.id) {
      ids.push(mitem.id);
    }
  });
  return ids;
}

const query = new Parse.Query("ProductRequire");
query.equalTo("type", "require");
query.containedIn("module", modulePathIds);
```

**索引建议**:
- `project + type + isDeleted`
- `product + type`
- `module + type`
- `parent + type`
- `updatedAt` (降序)

---

### 9. OKR（目标管理周期表）

**用途**: 管理OKR周期（年度/季度），支持公司级目标管理。

**表结构**:

| 字段名 | 类型 | 必填 | 说明 | 示例值 |
|--------|------|------|------|--------|
| objectId | String | 是 | 主键ID | "okr001" |
| title | String | 是 | OKR名称 | "2024年度OKR" |
| company | Pointer | 是 | 所属企业 | → Company |
| startDate | Date | 否 | 开始日期 | 2024-01-01T00:00:00.000Z |
| endDate | Date | 否 | 结束日期 | 2024-12-31T23:59:59.999Z |
| isDeleted | Boolean | 否 | 软删除标记 | false |
| createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z |
| updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z |

**关系**:
- 多对一: OKR → Company（所属企业）
- 一对多: OKR → OKRObject（OKR对象/目标）

**使用场景**:
```typescript
// 查询企业的OKR列表
const query = new Parse.Query("OKR");
query.equalTo("company", companyId);
query.notEqualTo("isDeleted", true);
query.addDescending("updatedAt");
const okrs = await query.find();

// 创建年度OKR
const OKR = Parse.Object.extend("OKR");
const okr = new OKR();
okr.set("title", "2024年度OKR");
okr.set("company", company.toPointer());
okr.set("startDate", new Date("2024-01-01"));
okr.set("endDate", new Date("2024-12-31"));
await okr.save();
```

**索引建议**:
- `company + isDeleted`
- `startDate + endDate`
- `updatedAt` (降序)

---

### 10. OKRObject（OKR对象表）

**用途**: 存储OKR的指标树和具体目标，支持公司/部门/个人三级架构，采用BSC平衡计分卡。

**表结构**:

| 字段名 | 类型 | 必填 | 说明 | 示例值 |
|--------|------|------|------|--------|
| objectId | String | 是 | 主键ID | "okrobj001" |
| title | String | 是 | 目标/指标树名称 | "年度营收目标" |
| type | String | 是 | 对象类型 | "tree" / "objective" |
| okr | Pointer | 是 | 所属OKR周期 | → OKR |
| company | Pointer | 是 | 所属企业 | → Company |
| department | Pointer | 否 | 所属部门 | → Department |
| profile | Pointer | 否 | 所属个人 | → Profile |
| tree | Pointer | 否 | 所属指标树 | → OKRObject |
| parent | Pointer | 否 | 父级指标树 | → OKRObject |
| bsc | String | 否 | 平衡计分卡维度 | "财务" / "客户" / "内部运营" / "学习成长" |
| value | Number | 否 | 目标值 | 1000000 |
| unit | String | 否 | 单位 | "万元" / "%" |
| index | Number | 否 | 排序索引 | 1 |
| isDeleted | Boolean | 否 | 软删除标记 | false |
| createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z |
| updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z |

**type 枚举值**:
- `tree`: 指标树节点（用于分类组织）
- `objective`: 具体目标（O或KR）

**BSC 平衡计分卡维度**:
- `财务`: 财务指标（如：营收、利润等）
- `客户`: 客户相关指标（如：客户满意度、客户数等）
- `内部运营`: 内部流程指标（如：交付效率、质量等）
- `学习成长`: 学习与创新指标（如：培训时长、新技能等）

**三级架构说明**:
1. **公司级OKR**: department=null, profile=null
2. **部门级OKR**: department不为空, profile=null
3. **个人级OKR**: department可选, profile不为空

**关系**:
- 多对一: OKRObject → OKR（所属OKR周期）
- 多对一: OKRObject → Company（所属企业）
- 多对一: OKRObject → Department（部门OKR，可选）
- 多对一: OKRObject → Profile（个人OKR，可选）
- 树状结构: OKRObject → OKRObject (tree/parent, 指标树层级)

**使用场景**:
```typescript
// 查询公司级指标树
const treeQuery = new Parse.Query("OKRObject");
treeQuery.equalTo("okr", okrId);
treeQuery.equalTo("type", "tree");
treeQuery.equalTo("department", null);
treeQuery.equalTo("profile", null);
treeQuery.ascending("index");
const trees = await treeQuery.find();

// 查询部门OKR
const deptOKRQuery = new Parse.Query("OKRObject");
deptOKRQuery.equalTo("okr", okrId);
deptOKRQuery.equalTo("department", departmentId);
deptOKRQuery.addDescending("updatedAt");
const deptOKRs = await deptOKRQuery.find();

// 查询个人OKR
const personalOKRQuery = new Parse.Query("OKRObject");
personalOKRQuery.equalTo("okr", okrId);
personalOKRQuery.equalTo("profile", profileId);
const personalOKRs = await personalOKRQuery.find();

// 查询某指标树下的目标
const objectiveQuery = new Parse.Query("OKRObject");
objectiveQuery.equalTo("okr", okrId);
objectiveQuery.equalTo("tree", treeId);
objectiveQuery.equalTo("type", "objective");
const objectives = await objectiveQuery.find();

// 按BSC维度筛选
const bscQuery = new Parse.Query("OKRObject");
bscQuery.equalTo("bsc", "财务");
bscQuery.equalTo("okr", okrId);
```

**创建目标示例**:
```typescript
// 创建公司级指标树
const OKRObject = Parse.Object.extend("OKRObject");
const tree = new OKRObject();
tree.set("title", "财务指标");
tree.set("type", "tree");
tree.set("okr", okr.toPointer());
tree.set("company", company.toPointer());
tree.set("bsc", "财务");
tree.set("index", 1);
await tree.save();

// 创建具体目标
const objective = new OKRObject();
objective.set("title", "实现营收1000万");
objective.set("type", "objective");
objective.set("okr", okr.toPointer());
objective.set("company", company.toPointer());
objective.set("tree", tree.toPointer());
objective.set("bsc", "财务");
objective.set("value", 1000);
objective.set("unit", "万元");
await objective.save();

// 创建部门OKR（继承指标树）
const deptOKR = new OKRObject();
deptOKR.set("title", "技术部营收贡献500万");
deptOKR.set("type", "objective");
deptOKR.set("okr", okr.toPointer());
deptOKR.set("company", company.toPointer());
deptOKR.set("department", department.toPointer());
deptOKR.set("tree", tree.toPointer());
deptOKR.set("bsc", "财务");
deptOKR.set("value", 500);
deptOKR.set("unit", "万元");
await deptOKR.save();
```

**索引建议**:
- `okr + type + isDeleted`
- `okr + department`
- `okr + profile`
- `tree + type`
- `bsc + okr`
- `index + okr`

---

### 11. NoteSpace（知识空间表）

**用途**: 文档空间管理，通常与项目关联，作为项目Wiki。

**表结构**:

| 字段名 | 类型 | 必填 | 说明 | 示例值 |
|--------|------|------|------|--------|
| objectId | String | 是 | 主键ID | "space001" |
| title | String | 是 | 空间标题 | "CRM系统的Wiki空间" |
| type | String | 是 | 空间类型 | "project" |
| company | Pointer | 是 | 所属企业 | → Company |
| project | Pointer | 否 | 关联项目 | → Project |
| isDeleted | Boolean | 否 | 软删除标记 | false |
| createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z |
| updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z |

**type 枚举值**:
- `project`: 项目空间

**关系**:
- 多对一: NoteSpace → Company（所属企业）
- 一对一: NoteSpace → Project（关联项目）
- 一对多: NoteSpace → NotePad（空间笔记）

**使用场景**:
```typescript
// 创建项目Wiki空间（自动）
const NoteSpace = Parse.Object.extend("NoteSpace");
const space = new NoteSpace();
space.set("title", project.get("title") + "的Wiki空间");
space.set("type", "project");
space.set("company", company.toPointer());
space.set("project", project.toPointer());
await space.save();

// 查询项目的Wiki空间
const query = new Parse.Query("NoteSpace");
query.equalTo("project", projectId);
query.equalTo("type", "project");
query.notEqualTo("isDeleted", true);
const space = await query.first();

// 查询用户有权访问的空间（通过项目团队）
const teamQuery = new Parse.Query("ProjectTeam");
teamQuery.equalTo("profile", profileId);
const teams = await teamQuery.find();
const projectIds = teams.map(t => t.get("project").id);

const spaceQuery = new Parse.Query("NoteSpace");
spaceQuery.containedIn("project", projectIds);
const spaces = await spaceQuery.find();
```

**索引建议**:
- `project + type`
- `company + isDeleted`

---

### 12. NotePad（文档笔记表）

**用途**: 存储具体的文档笔记，支持树状结构（目录层级）。

**表结构**:

| 字段名 | 类型 | 必填 | 说明 | 示例值 |
|--------|------|------|------|--------|
| objectId | String | 是 | 主键ID | "note001" |
| title | String | 否 | 笔记标题 | "API接口设计" |
| space | Pointer | 是 | 所属空间 | → NoteSpace |
| profile | Pointer | 是 | 创建者 | → Profile |
| parent | Pointer | 否 | 父笔记 | → NotePad |
| content | String | 否 | 笔记内容 | Markdown格式 |
| isDeleted | Boolean | 否 | 软删除标记 | false |
| createdAt | Date | 自动 | 创建时间 | 2024-01-01T00:00:00.000Z |
| updatedAt | Date | 自动 | 更新时间 | 2024-01-01T00:00:00.000Z |

**关系**:
- 多对一: NotePad → NoteSpace（所属空间）
- 多对一: NotePad → Profile（创建者）
- 树状结构: NotePad → NotePad (parent, 支持多层级目录)

**使用场景**:
```typescript
// 查询空间的一级笔记（根目录）
const query = new Parse.Query("NotePad");
query.equalTo("space", spaceId);
query.doesNotExist("parent"); // 或 query.equalTo("parent", null)
query.notEqualTo("isDeleted", true);
const rootNotes = await query.find();

// 查询某笔记的子笔记
const childQuery = new Parse.Query("NotePad");
childQuery.equalTo("parent", parentNoteId);
childQuery.notEqualTo("isDeleted", true);
const children = await childQuery.find();

// 创建笔记
const NotePad = Parse.Object.extend("NotePad");
const note = new NotePad();
note.set("title", "接口文档");
note.set("space", space.toPointer());
note.set("profile", profile.toPointer());
note.set("content", "# API接口设计\n\n...");
await note.save();

// 递归查询笔记层级结构（SQL方式）
const sql = `
WITH RECURSIVE notepad_hierarchy AS (
  SELECT np."objectId", np."parent", np."title", 1 AS "level"
  FROM "NotePad" np
  WHERE np."parent" IS NULL
    AND np."isDeleted" IS NOT TRUE
    AND np."space" = $1
  UNION ALL
  SELECT np2."objectId", np2."parent", np2."title", nh."level" + 1
  FROM "NotePad" np2
  JOIN notepad_hierarchy nh ON nh."objectId" = np2."parent"
  WHERE np2."isDeleted" IS NOT TRUE
)
SELECT * FROM notepad_hierarchy
ORDER BY "level", "createdAt"
`;
```

**索引建议**:
- `space + isDeleted`
- `parent + space`
- `profile + space`
- `updatedAt` (降序)

---

## 通用字段说明

所有 Parse Server 表都包含以下系统字段：

| 字段名 | 类型 | 说明 |
|--------|------|------|
| objectId | String | 唯一标识符，自动生成，主键 |
| createdAt | Date | 创建时间，自动生成 |
| updatedAt | Date | 更新时间，自动维护 |
| ACL | ACL | 访问控制列表（权限控制） |

---

## 软删除模式

系统采用**软删除模式**，几乎所有表都包含 `isDeleted` 字段：

```typescript
// 标准查询模式（排除已删除数据）
query.notEqualTo("isDeleted", true);

// 或
query.equalTo("isDeleted", null);
```

**优势**:
- 数据可恢复
- 保持关联完整性
- 支持审计追踪
- 避免级联删除问题

---

## 多租户隔离

系统采用**多租户架构**，所有业务表都包含 `company` 字段：

```typescript
// 获取当前企业ID
const companyId = localStorage.getItem("Parse/CompanyId") || localStorage.getItem("company");

// 所有查询都需要加上企业隔离
query.equalTo("company", companyId);
```

---

## 关键查询模式

### 1. 分页查询
```typescript
query.limit(pageSize);
query.skip(pageSize * (pageIndex - 1));
```

### 2. 排序
```typescript
query.descending("createdAt");  // 降序
query.ascending("index");       // 升序
query.addDescending("priority"); // 添加额外排序
```

### 3. 关联查询（Include）
```typescript
// 单层级关联
query.include("assignee", "owner");

// 多层级关联
query.include(["project", "assignee.user", "assignee.department"]);
```

### 4. 字段筛选
```typescript
// 只返回指定字段
query.select("title", "startDate", "assignee");
```

### 5. 计数查询
```typescript
const count = await query.count();

// 带计数的查询
query.withCount();
const result = await query.find();
console.log(result.count); // 总数
console.log(result.results); // 结果列表
```

### 6. 树状结构查询
```typescript
// 查询根节点
const roots = list.filter(item => !item.get("parent"));

// 查询子节点
const children = list.filter(item => item.get("parent")?.id === parentId);

// 递归构建树
function buildTree(nodes, parentId = null) {
  return nodes
    .filter(node => node.get("parent")?.id === parentId)
    .map(node => ({
      ...node.toJSON(),
      children: buildTree(nodes, node.id)
    }));
}
```

---

## 性能优化建议

### 1. 索引策略

**必建索引**:
- 所有表: `company + isDeleted`
- 所有表: `updatedAt` (降序)
- 关联字段: 所有 Pointer 字段
- 查询字段: 经常用于筛选的字段

**复合索引示例**:
```javascript
// Project表
{ company: 1, isDeleted: 1, isStar: 1 }
{ company: 1, owner: 1, isDeleted: 1 }

// ProjectTask表
{ project: 1, isDeleted: 1, stateList: 1 }
{ assignee: 1, isDeleted: 1, deadline: 1 }
{ company: 1, startDate: -1 }

// OKRObject表
{ okr: 1, type: 1, isDeleted: 1 }
{ okr: 1, department: 1, profile: 1 }
```

### 2. 查询优化

**避免N+1查询**:
```typescript
// ❌ 不好的做法
const tasks = await query.find();
for (const task of tasks) {
  const assignee = await task.get("assignee").fetch(); // N次查询
}

// ✅ 好的做法
query.include("assignee");
const tasks = await query.find(); // 1次查询
```

**批量操作**:
```typescript
// 批量保存
await Parse.Object.saveAll(objects);

// 批量删除
await Parse.Object.destroyAll(objects);
```

**使用 select 限制字段**:
```typescript
// ❌ 返回所有字段
const tasks = await query.find();

// ✅ 只返回需要的字段
query.select("title", "startDate", "stateList");
const tasks = await query.find();
```

### 3. 缓存策略

项目中实现了简单的内存缓存：

```typescript
// 检查是否需要更新数据
async hasUpdateObject(list: Parse.Object[], querySrc: Parse.Query, refresh = false) {
  if (refresh) { return true; }

  if (list?.length > 0) {
    // 获取最新的一条数据
    const query = Parse.Query.fromJSON(querySrc.className, querySrc.toJSON());
    query.addDescending("updatedAt");
    query.withCount();
    query.limit(1);
    const data = await query.find();

    // 比较更新时间和数量
    if (data.results[0]?.updatedAt > list[0].updatedAt) {
      return true; // 有更新
    }
    if (data.count !== list.length) {
      return true; // 数量变化
    }
    return false; // 无需更新
  }

  return true; // 首次加载
}
```

---

## 数据完整性约束

### 必填字段（应用层校验）

| 表名 | 必填字段 |
|------|---------|
| Company | name |
| Profile | name, company |
| Department | name, type, company |
| Project | title, company, owner |
| ProjectTask | title, project, company, owner, startDate |
| ProjectTeam | project, profile |
| Product | title, project, company |
| ProductRequire | title, type, project, company |
| OKR | title, company |
| OKRObject | title, type, okr, company |
| NoteSpace | title, type, company |
| NotePad | space, profile |

### 外键约束

所有 Pointer 字段在应用层需要保证引用完整性：
- 删除操作应采用**软删除**
- 级联更新应谨慎处理
- 关联查询前应检查对象是否存在

---

## 特殊业务逻辑

### 1. 工时管理

**基准工时**: 26天 × 7小时 = 182小时/月

```typescript
// ProjectTask 字段
duration: Number  // 实际工时（小时）
estimate: Number  // 预估工时（小时）
```

**工时统计SQL**:
```sql
SELECT
    pt."assignee",
    SUM(COALESCE(pt."duration", 0)) as actual_hours,
    SUM(COALESCE(pt."estimate", 0)) as estimated_hours,
    SUM(COALESCE(pt."duration", 0)) / 182.0 * 100 as completion_rate
FROM "ProjectTask" pt
WHERE pt."company" = $1
  AND (pt."isDeleted" != true OR pt."isDeleted" IS NULL)
  AND pt."startDate" >= $2
  AND pt."startDate" < $3
GROUP BY pt."assignee"
```

### 2. 任务状态流转

```
待分配 → 进行中 → 测试中 → 已完成 → 已上线
```

**状态映射**:
```typescript
const stateColorMap = {
  '待分配': 'default',
  '进行中': 'processing',
  '测试中': 'warning',
  '已完成': 'success',
  '已上线': 'gold',
};
```

### 3. 优先级映射

```typescript
const priorityMap = {
  1:   { text: '最低', color: 'default' },
  50:  { text: '普通', color: 'blue' },
  70:  { text: '较高', color: 'orange' },
  90:  { text: '重要', color: 'red' },
  100: { text: '严重', color: '#f50' },
};
```

### 4. OKR 三级架构

```typescript
// 公司级 OKR
okrObject.set("department", null);
okrObject.set("profile", null);

// 部门级 OKR
okrObject.set("department", department.toPointer());
okrObject.set("profile", null);

// 个人级 OKR
okrObject.set("profile", profile.toPointer());
// department 可选
```

### 5. 平衡计分卡（BSC）

```typescript
const bscList = [
  { label: "财务", value: "财务" },
  { label: "客户", value: "客户" },
  { label: "内部运营", value: "内部运营" },
  { label: "学习成长", value: "学习成长" },
];
```

---

## SQL 查询示例

### 1. 用户参与项目统计

```sql
SELECT DISTINCT(task."project"), pro."title" AS "name"
FROM "ProjectTask" task
LEFT JOIN "Project" pro ON pro."objectId" = task."project"
WHERE task."isDeleted" IS NOT TRUE
  AND task."isClosed" IS NOT TRUE
  AND (task."assignee" = $1 OR task."owner" = $1)
  AND task."project" IS NOT NULL
ORDER BY pro."updatedAt" DESC
```

### 2. 笔记层级结构查询

```sql
WITH RECURSIVE notepad_hierarchy AS (
  -- 查询根节点
  SELECT
    np."objectId",
    np."parent",
    np."title",
    np."space",
    1 AS "level"
  FROM "NotePad" np
  WHERE np."parent" IS NULL
    AND np."isDeleted" IS NOT TRUE
    AND np."space" = $1

  UNION ALL

  -- 递归查询子节点
  SELECT
    np2."objectId",
    np2."parent",
    np2."title",
    np2."space",
    nh."level" + 1
  FROM "NotePad" np2
  JOIN notepad_hierarchy nh ON nh."objectId" = np2."parent"
  WHERE np2."isDeleted" IS NOT TRUE
)
SELECT * FROM notepad_hierarchy
ORDER BY "level", "createdAt"
```

### 3. 月度工时统计

```sql
SELECT
    p."name",
    p."objectId" as profile_id,
    COALESCE(SUM(pt."duration"), 0) as actual_hours,
    COALESCE(SUM(pt."estimate"), 0) as estimated_hours,
    COUNT(pt."objectId") as task_count
FROM "Profile" p
LEFT JOIN "ProjectTask" pt ON pt."assignee" = p."objectId"
    AND pt."isDeleted" IS NOT TRUE
    AND pt."startDate" >= $1
    AND pt."startDate" < $2
WHERE p."company" = $3
  AND p."isDeleted" IS NOT TRUE
GROUP BY p."objectId", p."name"
ORDER BY actual_hours DESC
```

---

## 文件位置索引

**核心服务文件**:
- 项目服务: `src/modules/project/project.service.ts`
- OKR服务: `src/modules/okr/okr.service.ts`
- 部门服务: `src/modules/okr/depart.service.ts`

**主要组件**:
- 项目管理: `src/modules/project/project-manage/project-manage.component.ts`
- 甘特图: `src/modules/project/project-gantt/project-gantt.component.ts`
- 看板: `src/modules/project/project-kanban/project-kanban.component.ts`
- 产品管理: `src/modules/project/project-product/project-product.component.ts`
- OKR面板: `src/modules/okr/page-okr-panel/page-okr-panel.component.ts`
- OKR仪表板: `src/modules/okr/okr-dashboard/okr-dashboard.component.ts`

---

## 附录

### A. 数据表清单

| 序号 | 表名 | 中文名 | 用途 |
|------|------|--------|------|
| 1 | Company | 企业表 | 多租户核心 |
| 2 | Profile | 用户档案表 | 用户信息 |
| 3 | Department | 部门表 | 组织架构 |
| 4 | Project | 项目表 | 项目管理 |
| 5 | ProjectTask | 任务表 | 任务管理 |
| 6 | ProjectTeam | 项目团队表 | 成员关系 |
| 7 | Product | 产品表 | 产品管理 |
| 8 | ProductRequire | 产品需求表 | 需求管理 |
| 9 | OKR | OKR周期表 | 目标周期 |
| 10 | OKRObject | OKR对象表 | 目标管理 |
| 11 | NoteSpace | 知识空间表 | 文档空间 |
| 12 | NotePad | 文档笔记表 | 笔记管理 |

### B. 关系类型说明

- **一对多 (1:N)**: 一个父记录对应多个子记录
- **多对多 (N:N)**: 通过中间表实现
- **一对一 (1:1)**: 一个记录对应另一个记录
- **树状结构**: 通过 parent 字段实现自引用

### C. 数据类型说明

| Parse 类型 | 说明 | 示例 |
|-----------|------|------|
| String | 字符串 | "项目名称" |
| Number | 数字 | 100 |
| Boolean | 布尔值 | true / false |
| Date | 日期时间 | ISO 8601 格式 |
| Array | 数组 | ["tag1", "tag2"] |
| Object | JSON对象 | { key: "value" } |
| Pointer | 关联引用 | { __type: "Pointer", className: "Profile", objectId: "abc" } |
| Relation | 多对多关系 | Parse.Relation |
| File | 文件 | Parse.File |

---

**文档版本**: v1.0
**最后更新**: 2025-10-13
**维护者**: Nova Project Team
