# 树形数据管理模块技术文档

## 概述

本模块用于根据数据库表结构和配置文件，自动生成基于树形控件（Tree）的前端 UI 配置及后端 CRUD 接口代码。适用于快速构建具有父子层级关系的数据管理系统。

该工具支持通过 `.xlsx` 或其他格式描述的数据模型生成完整的树形界面与操作逻辑，包括：
- 树形展示界面 (`index.ui`)
- 获取节点数据接口
- 新增、更新、删除节点接口

---

## 依赖说明

### 外部依赖

```python
import os
import sys
import codecs
import json
```

### 内部模块依赖

| 模块路径 | 功能 |
|--------|------|
| `appPublic.dictObject` | 提供 `DictObject` 类，将字典转换为可点式访问的对象 |
| `appPublic.folderUtils` | 文件夹操作工具：`listFile`, `_mkdir` |
| `appPublic.myTE` | 自定义模板引擎 `MyTemplateEngine`，支持 Jinja2 风格语法 |
| `xlsxData.xlsxFactory` | 从 Excel 文件中读取数据模型 |
| `xls2crud.build_dbdesc` | 构建数据库描述对象 |
| `xls2crud.field_list` | 提取字段列表 |
| `xls2crud.subtable2toolbar` | 将子表信息转为工具栏按钮配置 |
| `xls2crud.filter_backslash` | 过滤字符串中的多余反斜杠 |
| `tmpls.*_tmpl` | 各类模板字符串（新增、更新、删除、获取数据等） |

---

## 模板定义

### `ui_tmpl` - 树形组件 UI 配置模板

此模板用于生成 `index.ui` 文件，定义前端 Tree 组件的配置项。

#### 参数说明

| 字段名 | 类型 | 是否必需 | 描述 |
|-------|------|----------|------|
| `widgettype` | string | 是 | 固定为 `"Tree"` |
| `title` | string | 否 | 页面标题；若未提供则使用 `summary[0].title` |
| `description` | string | 否 | 页面描述 |
| `toolbar` | array | 否 | 工具栏按钮配置（JSON 格式输出） |
| `editable` | object | 否 | 编辑功能开关及 URL 配置 |
| &nbsp;&nbsp;`add_url` | string | 否 | 新增接口地址，默认为 `./new_{tblname}.dspy` |
| &nbsp;&nbsp;`update_url` | string | 否 | 更新接口地址，默认为 `./update_{tblname}.dspy` |
| &nbsp;&nbsp;`delete_url` | string | 否 | 删除接口地址，默认为 `./delete_{tblname}.dspy` |
| `checkField` | string | 否 | 可选复选框字段 |
| `parentField` | string | 是 | 父节点字段名（如 `parent_id`） |
| `idField` | string | 是 | 主键字段名 |
| `textField` | string | 是 | 显示文本字段名 |
| `typeField` | string | 否 | 节点类型字段 |
| `params` | object | 否 | 请求附加参数 |
| `newdata_params` | object | 否 | 新增时携带参数 |
| `node_typeicons` | object | 否 | 不同类型节点图标映射 |
| `dataurl` | string | 否 | 获取节点数据接口地址，默认为 `./get_{tblname}.dspy` |
| `binds` | object | 否 | 数据绑定配置（JSON 格式输出，缩进4格） |

> **注意**：模板中使用 `{%- raw -%}` 和 `{%- endraw %}` 包裹动态路径表达式以防止被提前渲染。

---

### `get_nodes_tmpl` - 获取树节点数据脚本模板

生成用于查询树节点的 Python 异步脚本（`.dspy`），支持父子层级过滤。

#### SQL 查询逻辑

```sql
SELECT * FROM {tblname}
WHERE {parentField} = ${id}$   -- 当前节点的子节点
   OR {parentField} IS NULL    -- 根节点
ORDER BY {textField}
```

#### 上下文变量

- `params_kw`: 前端传入参数字典
- `db`: 使用 `DBPools()` 获取数据库连接池
- `dbname`: 通过 `get_module_dbname(modulename)` 获取模块对应数据库名

返回结果为查询到的记录列表。

---

## 核心函数说明

### `gen_tree_ui(d, pat)`
生成树形 UI 配置文件 `index.ui`

#### 参数
- `d` (dict/DictObject): 渲染上下文数据
- `pat` (str): 输出目录路径

#### 行为
1. 使用 `MyTemplateEngine` 渲染 `ui_tmpl`
2. 写入 `pat/index.ui` 文件
3. 调用 `filter_backslash` 清理反斜杠

---

### `gen_get_nodedata(d, pat)`
生成获取节点数据的 `.dspy` 脚本

#### 输出文件
`get_{tblname}.dspy`

#### 示例输出
```python
ns = params_kw.copy()
sql = '''select * from my_table where 1 = 1'''
id = ns.get('parent_id')
if id:
    sql += " and parent_id = ${id}$"
else:
    sql += " and parent_id is null"
sql += " order by name "
...
```

---

### `gen_new_nodedata(d, pat)`
生成新增节点接口脚本

#### 输出文件
`new_{tblname}.dspy`

调用 `data_new_tmpl` 模板进行渲染。

---

### `gen_update_nodedata(d, pat)`
生成更新节点接口脚本

#### 输出文件
`update_{tblname}.dspy`

调用 `data_update_tmpl` 模板进行渲染。

---

### `gen_delete_nodedata(d, pat)`
生成删除节点接口脚本

#### 输出文件
`delete_{tblname}.dspy`

调用 `data_delete_tmpl` 模板进行渲染。

---

### `build_tree_ui(tree_data, dbdesc)`
主入口函数：根据树配置和数据库结构生成全部文件

#### 参数
- `tree_data`: 包含 `output_dir`, `tblname`, `params` 的对象
- `dbdesc`: 数据库结构描述字典（由 `build_dbdesc` 生成）

#### 流程
1. 创建输出目录
2. 提取当前表结构并封装为 `DictObject`
3. 添加额外参数（如 title、toolbar 等）
4. 调用 `subtable2toolbar(tbldesc)` 自动生成工具栏
5. 计算可编辑字段列表（排除 `edit_exclouded_fields`、`idField`、`parentField`）
6. 依次调用各 `gen_*` 函数生成所有文件

---

### `main(dbdesc, outdir, modulename, fn)`
解析输入 JSON/XLSX 配置文件并执行生成流程

#### 参数
- `dbdesc`: 数据库描述对象
- `outdir`: 输出目录
- `modulename`: 模块名称（用于确定数据库）
- `fn`: 输入配置文件路径（JSON 或 XLSX）

> ⚠️ 注意：函数重复定义两次，应保留一个。

---

## 命令行运行方式

```bash
python tree_generator.py <model_path> <outpath> <modelname> <tree_desc_file> [...]
```

### 参数说明

| 参数 | 说明 |
|------|------|
| `model_path` | 数据模型路径（通常是 `.xlsx` 文件或模型目录） |
| `outpath` | 输出代码的目标目录 |
| `modelname` | 模块名（用于查找数据库配置） |
| `tree_desc_file...` | 一个或多个树形结构定义文件（JSON 或 XLSX） |

### 示例

```bash
python tree_generator.py ./models/db.xlsx ./output/admin usermgr ./trees/org_tree.json
```

---

## 配置文件结构示例（JSON）

```json
{
  "tblname": "org_dept",
  "output_dir": "./output/admin/org",
  "title": "组织架构管理",
  "description": "管理部门与人员的树形结构",
  "parentField": "parent_id",
  "idField": "id",
  "textField": "dept_name",
  "typeField": "dept_type",
  "notitle": false,
  "editable": true,
  "new_data_url": "/api/org/add",
  "update_data_url": "/api/org/edit",
  "delete_data_url": "/api/org/remove",
  "get_data_url": "/api/org/nodes",
  "params": {
    "status": "active"
  },
  "newdata_params": {
    "autoCreateCode": true
  },
  "node_typeicons": {
    "company": "icon-company",
    "department": "icon-dept"
  },
  "edit_exclouded_fields": ["created_time", "updated_by"]
}
```

---

## 输出文件结构

在指定 `output_dir` 下生成以下文件：

```
output_dir/
├── index.ui                    # 树形界面配置
├── get_<tblname>.dspy          # 获取节点数据
├── new_<tblname>.dspy          # 新增节点
├── update_<tblname>.dspy       # 更新节点
└── delete_<tblname>.dspy       # 删除节点
```

---

## 扩展建议

1. **增加校验机制**：对必填字段（如 `idField`, `parentField`）做存在性检查
2. **支持更多控件类型**：可通过 `widgettype` 扩展为 TreeGrid、Cascade 等
3. **国际化支持**：在模板中加入 `i18n` 支持
4. **权限控制注入**：可在 `.dspy` 脚本中自动添加权限判断逻辑

---

## 版权与维护

- 项目：通用 CRUD 代码生成器子模块
- 维护者：未知（原始作者）
- 修改建议：请提交 PR 或 issue 至项目仓库

--- 

> ✅ 文档版本：v1.0  
> 📅 最后更新：2025-04-05