# PageType系统详解

## 概述

PageType是Jingrow的核心概念，定义了数据结构和行为。每个PageType对应一张数据库表。

## 文件结构

```
{module}/pagetype/{name}/
├── {name}.json       # 字段和权限定义(必需)
├── {name}.py         # 控制器类(可选)
├── {name}.js         # 前端脚本(可选,旧版前端)
└── test_{name}.py    # 单元测试(可选)
```

## JSON定义

### 基本结构
```json
{
  "name": "Task",
  "module": "Projects",
  "naming_rule": "autoincrement",
  "autoname": "TASK-.#####",
  "title_field": "subject",
  "is_submittable": 0,
  "istable": 0,
  "track_changes": 1,
  "fields": [],
  "permissions": []
}
```

### 常用属性

| 属性 | 说明 |
|------|------|
| `name` | PageType名称(唯一标识) |
| `module` | 所属模块 |
| `naming_rule` | 命名规则: `autoincrement`/`hash`/`by_fieldname` |
| `autoname` | 自动命名格式 |
| `title_field` | 标题字段(用于显示) |
| `is_submittable` | 是否可提交(0/1) |
| `istable` | 是否为子表(0/1) |
| `track_changes` | 是否跟踪变更(0/1) |
| `issingle` | 是否为单例(0/1) |

## 字段类型

### 数据字段
| 类型 | 说明 |
|------|------|
| `Data` | 单行文本 |
| `Text` | 多行文本 |
| `Small Text` | 短文本 |
| `Long Text` | 长文本 |
| `Text Editor` | 富文本编辑器 |
| `Code` | 代码编辑器 |
| `HTML Editor` | HTML编辑器 |
| `Markdown Editor` | Markdown编辑器 |
| `Password` | 密码 |

### 数值字段
| 类型 | 说明 |
|------|------|
| `Int` | 整数 |
| `Float` | 浮点数 |
| `Currency` | 货币 |
| `Percent` | 百分比 |
| `Check` | 复选框(0/1) |

### 日期时间
| 类型 | 说明 |
|------|------|
| `Date` | 日期 |
| `Datetime` | 日期时间 |
| `Time` | 时间 |
| `Duration` | 时长 |

### 关联字段
| 类型 | 说明 |
|------|------|
| `Link` | 关联到其他PageType |
| `Dynamic Link` | 动态关联 |
| `Table` | 子表(关联子PageType) |
| `Table MultiSelect` | 多选子表 |

### 选择字段
| 类型 | 说明 |
|------|------|
| `Select` | 下拉选择 |
| `Autocomplete` | 自动完成 |

### 特殊字段
| 类型 | 说明 |
|------|------|
| `Attach` | 附件 |
| `Attach Image` | 图片 |
| `Color` | 颜色选择器 |
| `Geolocation` | 地理位置 |
| `Signature` | 签名 |
| `Rating` | 评分 |
| `Read Only` | 只读 |
| `JSON` | JSON数据 |

### 布局字段
| 类型 | 说明 |
|------|------|
| `Section Break` | 分节 |
| `Column Break` | 分列 |
| `Tab Break` | 标签页 |

## 字段定义

```json
{
  "fieldname": "status",
  "fieldtype": "Select",
  "label": "Status",
  "options": "Open\nIn Progress\nClosed",
  "reqd": 1,
  "default": "Open",
  "in_list_view": 1,
  "in_standard_filter": 1,
  "read_only": 0,
  "hidden": 0,
  "permlevel": 0
}
```

### 常用字段属性

| 属性 | 说明 |
|------|------|
| `fieldname` | 字段名(数据库列名) |
| `fieldtype` | 字段类型 |
| `label` | 显示标签 |
| `options` | 选项(Select类型)或关联PageType(Link类型) |
| `reqd` | 是否必填(0/1) |
| `default` | 默认值 |
| `in_list_view` | 在列表视图显示(0/1) |
| `in_standard_filter` | 作为标准筛选器(0/1) |
| `read_only` | 只读(0/1) |
| `hidden` | 隐藏(0/1) |
| `permlevel` | 权限级别(0-9) |
| `depends_on` | 依赖条件(显示/隐藏) |
| `mandatory_depends_on` | 必填条件 |
| `read_only_depends_on` | 只读条件 |

## 权限定义

```json
{
  "permissions": [
    {
      "role": "System Manager",
      "read": 1,
      "write": 1,
      "create": 1,
      "delete": 1,
      "submit": 0,
      "cancel": 0,
      "amend": 0,
      "permlevel": 0
    }
  ]
}
```

## 控制器类

```python
from jingrow.model.page import Page
import jingrow

class Task(Page):
    # 生命周期钩子
    def validate(self):
        """保存前验证,可抛异常阻止保存"""
        if self.priority == "High" and not self.assignee:
            jingrow.throw("高优先级任务必须指定负责人")
    
    def before_save(self):
        """保存前处理"""
        pass
    
    def after_insert(self):
        """插入后"""
        pass
    
    def on_update(self):
        """更新后"""
        pass
    
    def on_submit(self):
        """提交后(仅is_submittable=1)"""
        pass
    
    def on_cancel(self):
        """取消后"""
        pass
    
    def on_trash(self):
        """删除后"""
        pass
    
    def autoname(self):
        """自定义命名"""
        self.name = f"TASK-{jingrow.utils.now_datetime().strftime('%Y%m%d')}-{jingrow.generate_hash(length=4)}"
    
    # 自定义方法
    @jingrow.whitelist()
    def mark_complete(self):
        """暴露为API的方法"""
        self.status = "Closed"
        self.save()
        return {"status": "done"}
```

## 子表(Child Table)

子表是`istable=1`的PageType，用于存储父文档的多条记录。

```json
{
  "name": "Task Item",
  "istable": 1,
  "fields": [
    {"fieldname": "item", "fieldtype": "Data"},
    {"fieldname": "completed", "fieldtype": "Check"}
  ]
}
```

父文档中引用:
```json
{
  "fieldname": "items",
  "fieldtype": "Table",
  "options": "Task Item"
}
```

操作子表:
```python
# 添加子表行
pg.append("items", {"item": "New Item"})

# 遍历子表
for item in pg.items:
    print(item.item)

# 清空子表
pg.items = []
```

## 常用操作

### 创建PageType
```bash
bench --site site_name new-pagetype "My Page Type" --module "Core"
```

### 同步PageType
```bash
bench --site site_name migrate
```

### 获取元数据
```python
meta = jingrow.get_meta("Task")
meta.fields      # 所有字段
meta.get_field("status")  # 获取特定字段
meta.permissions # 权限列表
meta.is_submittable  # 是否可提交
```
