# 开发规范与最佳实践

## 后端开发

### PageType定义

**位置**: `jingrow/{module}/pagetype/{name}/`

**文件结构**:
```
pagetype/{name}/
├── {name}.json      # 字段定义(必需)
├── {name}.py        # 控制器(可选)
└── test_{name}.py   # 测试(可选)
```

**JSON基本结构**:
```json
{
  "name": "My Page Type",
  "module": "Core",
  "fields": [
    {"fieldname": "title", "fieldtype": "Data", "label": "Title", "reqd": 1}
  ],
  "permissions": [
    {"role": "System Manager", "read": 1, "write": 1, "create": 1, "delete": 1}
  ]
}
```

### 控制器编写
```python
from jingrow.model.page import Page
import jingrow

class MyPageType(Page):
    def validate(self):
        # 保存前验证,可抛异常阻止保存
        if not self.title:
            jingrow.throw("标题不能为空")
    
    def before_save(self):
        # 保存前处理
        self.modified_title = self.title.upper()
    
    def after_insert(self):
        # 插入后处理
        jingrow.msgprint(f"创建成功: {self.name}")
    
    def on_update(self):
        # 更新后处理
        pass
    
    @jingrow.whitelist()
    def custom_action(self):
        # 暴露为API的自定义方法
        return {"status": "done"}
```

### 代码规范
- 缩进使用Tab
- 行长度限制110字符
- 使用ruff进行代码检查
- 遵循 `pyproject.toml` 配置

### 数据库操作
```python
# 推荐: 使用ORM
pg = jingrow.get_pg("PageType", "name")
pg.field = "value"
pg.save()

# 批量操作
jingrow.db.sql("UPDATE ... WHERE ...")
jingrow.db.commit()

# 事务处理(自动管理)
# 每个请求在一个事务内,失败自动回滚
```

## 前端开发

### 组件编写
```vue
<template>
  <n-card :title="t('Title')">
    <n-form ref="formRef" :model="formData">
      <n-form-item :label="t('Name')" path="name">
        <n-input v-model:value="formData.name" />
      </n-form-item>
    </n-form>
  </n-card>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { getRecord, updateRecord } from '@/shared/api/common'
import { t } from '@/shared/i18n'

const route = useRoute()
const formData = ref({ name: '' })

onMounted(async () => {
  const { success, data } = await getRecord('PageType', route.params.id as string)
  if (success) formData.value = data
})

const handleSave = async () => {
  const { success } = await updateRecord('PageType', route.params.id as string, formData.value)
  if (success) message.success(t('Saved'))
}
</script>
```

### 状态管理
- 全局状态使用Pinia store
- 组件局部状态使用ref/reactive
- 避免prop drilling,使用provide/inject或store

### 错误处理
```typescript
try {
  const { success, data, message: msg } = await api.call('method')
  if (!success) throw new Error(msg)
} catch (error: any) {
  message.error(error.message || t('Operation failed'))
}
```

## 常见模式

### 列表页面
1. 获取PageType元数据
2. 根据元数据动态渲染表格列
3. 实现分页、筛选、排序

### 详情页面
1. 获取记录数据
2. 获取PageType元数据
3. 动态渲染表单字段
4. 处理子表数据

### 权限检查
```python
# 后端
pg.check_permission("read")  # 抛异常如果无权限
jingrow.has_permission("PageType", "write")  # 返回True/False
```
```typescript
// 前端
permissionStore.canRead('PageType')
permissionStore.hasPermission('PageType', 'write')
```

## 调试技巧

### 后端
```python
jingrow.log("debug message")      # 输出到debug_log
jingrow.msgprint("user message")  # 返回给前端显示
jingrow.throw("error message")    # 抛出错误
jingrow.errprint(traceback)       # 错误日志
print(jingrow.as_json(data))      # 打印JSON
```

### 前端
```typescript
console.log(JSON.stringify(data, null, 2))
// 使用Vue DevTools查看状态
```

## 测试

### 后端测试
```bash
cd /path/to/jingrow
bench --site site_name run-tests --module module_name
bench --site site_name run-tests --pagetype "PageType Name"
```

### 前端构建
```bash
cd frontend
npm install
npm run dev      # 开发服务器
npm run build    # 构建产物
```

## 常见问题

### 分页参数
- `limit_start` - 起始位置
- `limit_page_length` - 每页数量(0=无限制)

### 权限问题
1. 检查用户角色 (User → Role)
2. 检查PageType权限设置
3. 检查字段级权限 (permlevel)
4. 检查User Permission过滤

### API调用失败
1. 检查方法是否有`@whitelist`装饰器
2. 检查请求参数格式
3. 检查用户权限
4. 查看Error Log PageType

### 缓存问题
```python
jingrow.clear_cache()  # 清除所有缓存
jingrow.clear_cache(pagetype="PageType")  # 清除特定PageType缓存
```
