-*- coding: utf-8 -*-

# EZDML JavaScript 编程参考指南

本指南详细介绍了在 EZDML 的 JavaScript 脚本引擎（基于 Besen JS 引擎，兼容 ECMAScript 5 规范）中可调用的全局变量、全局常量、全局方法以及各种系统类与元数据类。

通过这些接口，用户可以编写脚本来自动化执行模型图、数据表和字段的操作，读写文件、操作数据库 SQL、与系统剪贴板交互以及进行自定义的前端交互。

---

## 一、 全局变量 (Global Variables)

脚本启动时，EZDML 自动在全局上下文中注入了以下变量，以便直接访问当前的工程元数据和系统资源：

| 变量名 | 类型 | 说明 | 对应源码文件 |
| :--- | :--- | :--- | :--- |
| `allModels` | [TCtDataModelGraphList](file:///E:/gitH/ezdml_x/DML/besen/DmlBsCtDataModelGraphList.pas) | **全局模型图列表对象**。管理当前项目内的所有模型图区（包括普通模型和目录节点）。 | [DmlBsCtDataModelGraphList.pas](file:///E:/gitH/ezdml_x/DML/besen/DmlBsCtDataModelGraphList.pas) |
| `curModel` | [TCtDataModelGraph](file:///E:/gitH/ezdml_x/DML/besen/DmlBsCtDataModelGraph.pas) \| `null` | **当前活动模型图对象**。当前处于编辑状态或活动窗口所展示的模型图。 | [DmlBsCtDataModelGraph.pas](file:///E:/gitH/ezdml_x/DML/besen/DmlBsCtDataModelGraph.pas) |
| `curTable` | [TCtMetaTable](file:///E:/gitH/ezdml_x/DML/besen/DmlBsCtMetaTable.pas) \| `null` | **当前选中的数据表对象**。若未选中表，则为 `null`。 | [DmlBsCtMetaTable.pas](file:///E:/gitH/ezdml_x/DML/besen/DmlBsCtMetaTable.pas) |
| `curField` | [TCtMetaField](file:///E:/gitH/ezdml_x/DML/besen/DmlBsCtMetaField.pas) \| `null` | **当前选中的字段对象**。若未选中字段，则为 `null`。 | [DmlBsCtMetaField.pas](file:///E:/gitH/ezdml_x/DML/besen/DmlBsCtMetaField.pas) |
| `curOut` | [TStringList](file:///E:/gitH/ezdml_x/DML/besen/DmlBsStrings.pas) | **脚本输出缓存控制台**。常用于在生成代码或控制台输出时写入文本内容。 | [DmlBsStrings.pas](file:///E:/gitH/ezdml_x/DML/besen/DmlBsStrings.pas) |
| `curSettingsPanel` | [TDmlScriptControlList](file:///E:/gitH/ezdml_x/DML/besen/DmlBsDmlScriptControl.pas) \| `null` | **脚本配置面板对象**。用于动态向界面添加输入控件，与用户交互获取自定义执行参数。 | [DmlBsDmlScriptControl.pas](file:///E:/gitH/ezdml_x/DML/besen/DmlBsDmlScriptControl.pas) |
| `application` | [TApplication](file:///E:/gitH/ezdml_x/DML/besen/DmlBsApplication.pas) | **LCL GUI 应用程序全局实例**。可用于控制窗口最小化、弹出原生消息框、终止运行等。 | [DmlBsApplication.pas](file:///E:/gitH/ezdml_x/DML/besen/DmlBsApplication.pas) |
| `screen` | [TScreen](file:///E:/gitH/ezdml_x/DML/besen/DmlBsScreen.pas) | **LCL 屏幕全局实例**。可用于获取桌面工作区尺寸、多显示器监视器信息、获取当前活动窗口等。 | [DmlBsScreen.pas](file:///E:/gitH/ezdml_x/DML/besen/DmlBsScreen.pas) |

### 常用环境参数
以下为常用环境参数获取方式。`GetEnv` 也可写作旧式 `_getEnv`。

| 获取方式 | 说明 |
| :--- | :--- |
| `application.exeName` | 主程序 EXE 文件名。 |
| `GetEnv('APPFOLDER')` | 应用程序文件目录。 |
| `application.mainForm` | 主窗口对象。 |
| `screen.activeForm` | 当前焦点所在窗口。 |
| `screen.activeControl` | 当前焦点控件。 |
| `CurDbType()` | 当前或最近一次连接的数据库类型。 |
| `GetEnv('WINUSER')` | 当前 Windows 用户名。 |
| `GetEnv('COMPUTER')` | 当前 Windows 计算机名。 |
| `GetEnv('IP')` | 当前机器 IP。 |
| `GetEnv('DMLFILEPATH')` | 当前 DML 文件全名。 |
| `GetEnv('CMDLINE')` | 当前程序命令行。 |
| `GetSelectedCtMetaObj()` | 当前选中的元数据对象，可能是模型图、表或字段。 |
| `GetEnv('SYSTEMTYPE')` | 当前系统类型，如 `WINDOWS`、`DARWIN`、`UNIX`。 |
| `GetEnv('ARCHBITS')` | 当前系统架构位数，如 `32` 或 `64`。 |

---

## 二、 全局常量 (Global Constants)

为了支持原生 Win32/LCL 消息对话框按钮及图标样式，全局中预置了以下整型常量（一般在调用 `_msgBox` 或 `application.messageBox` 时使用）：

### 对话框按钮定义
*   `MB_OK` (0x00000000): 仅包含“确定”按钮。
*   `MB_OKCANCEL` (0x00000001): 包含“确定”和“取消”按钮。
*   `MB_ABORTRETRYIGNORE` (0x00000002): 包含“中止”、“重试”和“忽略”按钮。
*   `MB_YESNOCANCEL` (0x00000003): 包含“是”、“否”和“取消”按钮。
*   `MB_YESNO` (0x00000004): 包含“是”和“否”按钮。
*   `MB_RETRYCANCEL` (0x00000005): 包含“重试”和“取消”按钮。

### 对话框图标样式
*   `MB_ICONQUESTION` (0x00000020): 显示问号图标（询问）。
*   `MB_ICONWARNING` (0x00000030): 显示感叹号图标（警告）。
*   `MB_ICONERROR` / `MB_ICONSTOP` (0x00000010): 显示红叉/停止图标（错误）。
*   `MB_ICONINFORMATION` (0x00000040): 显示蓝色“i”图标（信息提示）。

### 默认焦点按钮
*   `MB_DEFBUTTON1` (0x00000000): 默认焦点在第 1 个按钮。
*   `MB_DEFBUTTON2` (0x00000100): 默认焦点在第 2 个按钮。
*   `MB_DEFBUTTON3` (0x00000200): 默认焦点在第 3 个按钮。
*   `MB_DEFBUTTON4` (0x00000300): 默认焦点在第 4 个按钮。

### 对话框返回值代表的按钮
*   `IDOK` (1): 用户点击了“确定”。
*   `IDCANCEL` (2): 用户点击了“取消”或按了 ESC。
*   `IDABORT` (3): 用户点击了“中止”。
*   `IDRETRY` (4): 用户点击了“重试”。
*   `IDIGNORE` (5): 用户点击了“忽略”。
*   `IDYES` (6): 用户点击了“是”。
*   `IDNO` (7): 用户点击了“否”。
*   `IDCLOSE` (8): 用户点击了“关闭”。
*   `IDCONTINUE` (11): 用户点击了“继续”。

### 常用枚举类型
JS 包装中的字段、表、模型的枚举属性都是按枚举名字符串读写，例如 `if(fd.dataType == 'cfdtString') fd.indexType = 'cfitNormal'`。以下为当前脚本注册中常用的枚举名；`cfdtUnknow` 是历史拼写，保持与代码一致。

| 枚举类型 | 常用属性/方法 | 可用值 |
| :--- | :--- | :--- |
| `TctDataLevel` | `dataLevel` | `ctdlUnknown`, `ctdlNormal`, `ctdlNew`, `ctdlModify`, `ctdlDeleted`, `ctdlDraft`, `ctdlDebug` |
| `TCtFieldDataType` | `dataType` | `cfdtUnknow`, `cfdtString`, `cfdtInteger`, `cfdtFloat`, `cfdtDate`, `cfdtBool`, `cfdtEnum`, `cfdtBlob`, `cfdtObject`, `cfdtCalculate`, `cfdtList`, `cfdtFunction`, `cfdtEvent`, `cfdtOther` |
| `TCtKeyFieldType` | `keyFieldType`, `getSpecKeyNames` | `cfktNormal`, `cfktId`, `cfktPid`, `cfktRid`, `cfktName`, `cfktCaption`, `cfktComment`, `cfktTypeName`, `cfktOrgId`, `cfktDeptId`, `cfktCreatorId`, `cfktCreatorName`, `cfktCreateDate`, `cfktModifierId`, `cfktModifierName`, `cfktModifyDate`, `cfktVersionNo`, `cfktHistoryId`, `cfktLockStamp`, `cfktInstNo`, `cfktProcID`, `cfktURL`, `cfktStatus`, `cfktOrderNo`, `cfktOthers` |
| `TCtFieldIndexType` | `indexType` | `cfitNone`, `cfitUnique`, `cfitNormal` |
| `TCtFieldDropDownMode` | `dropDownMode` | `cfddNone`, `cfddFixed`, `cfddEditable`, `cfddAppendable`, `cfddAutoComplete`, `cfddAutoCompleteFixed` |
| `TCtFieldFixColType` | `fixColType` | `cffcNone`, `cffcLeft`, `cffcRight` |
| `TCtTextAlignment` | `textAlign` | `cftaAuto`, `cftaLeft`, `cftaRight`, `cftaCenter` |
| `TCtModulePublishType` | `publishType` | `cmptAuto`, `cmptNone`, `cmptFunction`, `cmptModule`, `cmptMenu` |

---

## 三、 全局方法 (Global Methods)

> [!TIP]
> 所有的全局方法均默认使用 **去除下划线首字母大写** 的名称 (例如 `Print`)。由于历史兼容原因，仍保留了可以使用 **带下划线的前缀名** (例如 `_print`) 的旧版本。下面每项方法的详细说明中，都专门添加了对应的带下划线的前缀名旧版说明。

### 1. 终端输出与调试 (Output & Log)
*   **`Print(val)`** / **`Write(val)`** / **`print(val)`** / **`write(val)`**
    *   **旧版**: `_print(val)` / `_write(val)`
    *   **参数**: `val: any` - 待输出的数据。
    *   **说明**: 向终端/脚本控制台输出信息，不带换行。
*   **`Println(val)`** / **`Writeln(val)`** / **`println(val)`** / **`writeln(val)`**
    *   **旧版**: `_println(val)` / `_writeln(val)`
    *   **参数**: `val: any` - 待输出的数据（可选）。
    *   **说明**: 向终端/脚本控制台输出信息，带换行。
*   **`Trace(val)`**
    *   **旧版**: `_trace(val)`
    *   **参数**: `val: any` - 调试数据。
    *   **说明**: 追踪并打印变量的详细内部结构或信息。
*   **`Readln(question)`**
    *   **旧版**: `_readln(question)`
    *   **参数**: `question: string` - 输入提示文字。
    *   **返回值**: `string` - 用户输入的文本。
    *   **说明**: 读取一行用户输入。
*   **`PrintVar(val)`**
    *   **旧版**: `_printVar(val)`
    *   **参数**: `val: any` - 待输出的数据。
    *   **说明**: 向终端/脚本控制台输出信息，不带换行
*   **`WriteLog(str)`**
    *   **旧版**: `_writeLog(str)`
    *   **参数**: `str: string` - 日志行文本。
    *   **说明**: 将记录写入系统级日志。

### 2. 界面与弹窗交互 (Dialogs & GUI)
*   **`Alert(msg)`** / **`alert(msg)`** /  **`ShowMessage(msg)`**
    *   **旧版**: `_alert(msg)` / `_showMessage(msg)`
    *   **参数**: `msg: string` - 提示消息。
    *   **说明**: 弹出原生系统警告框。
*   **`Confirm(msg)`** / **`confirm(msg)`**
    *   **旧版**:  `_confirm(msg)`
    *   **参数**: `msg: string` - 询问信息。
    *   **返回值**: `Boolean` - 点击“是/确定”返回 `true`，点击“否/取消”返回 `false`。
    *   **说明**: 弹出是否确认的选择框。
*   **`Prompt(msg, initVal)`** / **`prompt(msg, initVal)`**
    *   **旧版**: `_prompt(msg, initVal)`
    *   **参数**: 
        *   `msg: string` - 输入提示信息。
        *   `initVal: string` - 默认初始值。
    *   **返回值**: `string` - 用户输入的文本，取消则返回空。
    *   **说明**: 弹出一个单行文本输入交互框。
*   **`Toast(msg, closeTimeMs)`** / **`toast(msg, closeTimeMs)`**
    *   **旧版**: `_toast(msg, closeTimeMs)`
    *   **参数**:
        *   `msg: string` - 吐司气泡文字。
        *   `closeTimeMs: number` - 自动关闭时长（毫秒）。
    *   **说明**: 在主窗口侧边弹出一个悬浮淡出式“吐司”提示框。
*   **`Choice(msg, items, initVal)`** / **`choice(msg, items, initVal)`**
    *   **旧版**: `_choice(msg, items, initVal)`
    *   **参数**:
        *   `msg: string` - 选项面板标题提示。
        *   `items: string` - 逗号或换行分隔的可选列表选项字符串。
        *   `initVal: string` - 缺省定位的选项。
    *   **返回值**: `string` - 用户选择的值。
    *   **说明**: 弹出一个下拉单选选择框。
*   **`MsgBox(msg, title, flags)`**
    *   **旧版**: `_msgBox(msg, title, flags)`
    *   **参数**:
        *   `msg: string` - 询问内容。
        *   `title: string` - 弹出框标题。
        *   `flags: number` - 常量按钮及图标的复合掩码值（如 `MB_YESNO | MB_ICONQUESTION`）。
    *   **返回值**: `number` - 代表所按按钮的 ID（如 `IDYES` / `IDNO`）。
    *   **说明**: 高级原生询问框定制。
*   **`InputBox(title, query, defaultVal)`**
    *   **旧版**: `_inputBox(title, query, defaultVal)`
    *   **参数**: 标题、查询提示及缺省默认值。
    *   **返回值**: `string`。
*   **`InputMemoQuery(title, query, textVal)`**
    *   **旧版**: `_inputMemoQuery(title, query, textVal)`
    *   **参数**: 标题、多行文字描述提示、默认输入的大段多行文本。
    *   **返回值**: `string` - 用户编写的完整大段文本。
    *   **说明**: 弹出一个支持多行文本编辑的对话框。
*   **`ShellOpen(fileName, params, dir)`**
    *   **旧版**: `_shellOpen(fileName, params, dir)`
    *   **说明**: 调用系统打开文件、目录或外部程序。
*   **`OpenFileDialog(title, filter, fileName, multi)`** / **`OpenPicDialog(title, filter, fileName, multi)`**
    *   **旧版**: `_openFileDialog(...)` / `_openPicDialog(...)`
    *   **说明**: 打开文件/图片选择对话框。

### 3. 文件系统与磁盘操作 (File & Directory)
*   **`ReadFile(filePath)`**
    *   **旧版**: `_readFile(filePath)`
    *   **参数**: `filePath: string` - 文件绝对路径。
    *   **返回值**: `string` - 读取的整个文件文本内容。
*   **`WriteFile(filePath, content)`**
    *   **旧版**: `_writeFile(filePath, content)`
    *   **参数**:
        *   `filePath: string` - 文件绝对路径。
        *   `content: string` - 要写入的文本。
    *   **说明**: 写入文本到文件（如果文件存在则会覆盖）。
*   **`DeleteFile(filePath)`**
    *   **旧版**: `_deleteFile(filePath)`
    *   **参数**: `filePath: string` - 文件路径。
    *   **返回值**: `Boolean` - 是否删除成功。
*   **`RenameFile(oldName, newName)`**
    *   **旧版**: `_renameFile(oldName, newName)`
    *   **参数**: 原始文件名，新文件名。
    *   **返回值**: `Boolean`。
*   **`FileExists(filePath)`** / **`DirectoryExists(dirPath)`**
    *   **旧版**: `_fileExists(filePath)` / `_directoryExists(dirPath)`
    *   **参数**: 路径。
    *   **返回值**: `Boolean` - 是否存在该文件/文件夹。
*   **`ForceDirectories(dirPath)`** / **`CreateDir(dirPath)`**
    *   **旧版**: `_forceDirectories(dirPath)` / `_createDir(dirPath)`
    *   **参数**: 文件夹路径。
    *   **说明**: 递归创建目录（若中间父级目录不存在将自动补全）。
*   **`RemoveDir(dirPath)`**
    *   **旧版**: `_removeDir(dirPath)`
    *   **说明**: 删除空目录。
*   **`ReadDirectory(dirPath)`**
    *   **旧版**: `_readDirectory(dirPath)`
    *   **参数**: 文件夹路径。
    *   **返回值**: `string` - 以换行分隔的该目录下所有文件及子文件夹名单。
*   **`GetCurrentDir()`** / **`SetCurrentDir(dir)`**
    *   **旧版**: `_getCurrentDir()` / `_setCurrentDir(dir)`
    *   **说明**: 获取/修改当前脚本运行环境的工作目录。
*   **`FileAge(filePath)`**
    *   **旧版**: `_fileAge(filePath)`
    *   **返回值**: `number` - 文件的时间戳代码（失败返回 -1）。
*   **`FileGetDate(handle)`** / **`FileSetDate(handle, age)`**
    *   **旧版**: `_fileGetDate(handle)` / `_fileSetDate(handle, age)`
    *   **说明**: 针对打开的文件句柄进行日期读写。
*   **`FileGetAttr(filePath)`** / **`FileSetAttr(filePath, attr)`**
    *   **旧版**: `_fileGetAttr(filePath)` / `_fileSetAttr(filePath, attr)`
    *   **说明**: 读写文件属性标志（如只读、隐藏、系统文件等）。
*   **`FileIsReadOnly(filePath)`**
    *   **旧版**: `_fileIsReadOnly(filePath)`
    *   **返回值**: `Boolean` - 文件是否被设为了写保护。
*   **`FileSearch(name, list)`**
    *   **旧版**: `_fileSearch(name, list)`
    *   **说明**: 在分号分隔的路径列表中搜索指定名字的文件。
*   **`DiskFree(drive)`** / **`DiskSize(drive)`**
    *   **旧版**: `_diskFree(drive)` / `_diskSize(drive)`
    *   **参数**: `drive: number` - 磁盘驱动器盘符代号（0 代表当前，1 代表 A 盘，3 代表 C 盘）。
    *   **返回值**: `number` - 磁盘空闲/总容量大小（字节）。
*   **`FileDateToDateTime(fileDate)`** / **`DateTimeToFileDate(dateTime)`**
    *   **旧版**: `_fileDateToDateTime(fileDate)` / `_dateTimeToFileDate(dateTime)`
    *   **说明**: 在文件日期整型值和 Delphi `TDateTime` 浮点值之间转换。

### 4. 路径处理 (Path Parsing)
*   **`ExtractFilePath(filePath)`**
    *   **旧版**: `_extractFilePath(filePath)`
    *   **返回值**: `string` - 返回路径中最后的斜杠（及之前）的目录部分（如 `C:\dir\`）。
*   **`ExtractFileDir(filePath)`**
    *   **旧版**: `_extractFileDir(filePath)`
    *   **返回值**: `string` - 返回去除末尾斜杠后的目录部分（如 `C:\dir`）。
*   **`ExtractFileDrive(filePath)`**
    *   **旧版**: `_extractFileDrive(filePath)`
    *   **返回值**: `string` - 返回盘符（如 `C:`）。
*   **`ExtractFileName(filePath)`**
    *   **旧版**: `_extractFileName(filePath)`
    *   **返回值**: `string` - 返回包含后缀的纯文件名（如 `test.txt`）。
*   **`ExtractFileExt(filePath)`**
    *   **旧版**: `_extractFileExt(filePath)`
    *   **返回值**: `string` - 返回带点号的扩展名（如 `.txt`）。
*   **`ChangeFileExt(filePath, newExt)`**
    *   **旧版**: `_changeFileExt(filePath, newExt)`
    *   **说明**: 替换原路径中的后缀名并返回新路径。
*   **`ExpandFileName(filePath)`**
    *   **旧版**: `_expandFileName(filePath)`
    *   **说明**: 将相对路径解析转换成绝对路径。
*   **`ExtractRelativePath(baseName, destName)`**
    *   **旧版**: `_extractRelativePath(baseName, destName)`
    *   **说明**: 计算 `destName` 相对 `baseName` 的相对路径。
*   **`ExtractShortPathName(filePath)`**
    *   **旧版**: `_extractShortPathName(filePath)`
    *   **说明**: 获取系统短路径名。

### 5. 时间与日期 (Date & Time)
*   **`_now()`**
    *   **返回值**: `number` - 代表当前时间的 Delphi 浮点 TDateTime。
    *   **说明**: 当前代码仅注册下划线版本，未生成 `Now()` 别名。
*   **`_date()`** / **`_time()`**
    *   **说明**: 获取当天日期/当前时间的浮点 TDateTime 值。
*   **`CurrentTimeMillis()`**
    *   **旧版**: `_currentTimeMillis()`
    *   **返回值**: `number` - Java 风格的毫秒级时间戳。
*   **`EncodeDate(year, month, day)`** / **`EncodeTime(hour, min, sec, msec)`**
    *   **旧版**: `_encodeDate(year, month, day)` / `_encodeTime(hour, min, sec, msec)`
    *   **说明**: 根据年月日时分秒装配并返回浮点型 TDateTime。
*   **`DayOfWeek(dateTime)`**
    *   **旧版**: `_dayOfWeek(dateTime)`
    *   **参数**: `dateTime: number` - TDateTime 浮点数。
    *   **返回值**: `number` - 星期几（1 代表星期天，2 代表星期一，...，7 代表星期六）。
*   **`DateTimeToJSTime(dateTime)`** / **`JSTimeToDateTime(jsTime)`**
    *   **旧版**: `_dateTimeToJSTime(dateTime)` / `_jsTimeToDateTime(jsTime)`
    *   **说明**: 负责在 Delphi TDateTime 浮点与 JS 自带 Date 毫秒级时间戳之间互相转换。
*   **`DateToStr(date)`** / **`TimeToStr(time)`** / **`DateTimeToStr(dateTime)`**
    *   **旧版**: `_dateToStr(date)` / `_timeToStr(time)` / `_dateTimeToStr(dateTime)`
    *   **说明**: 将 TDateTime 格式化转换为系统缺省习惯的日期、时间或完整文本字符串。
*   **`StrToDate(str)`** / **`StrToTime(str)`** / **`StrToDateTime(str)`**
    *   **旧版**: `_strToDate(str)` / `_strToTime(str)` / `_strToDateTime(str)`
    *   **说明**: 从规范字符串反解析成浮点型 TDateTime（失败则抛出异常）。
*   **`StrToTimeDef(str, def)`** / **`StrToDateTimeDef(str, def)`** / **`StrToFloatDef(str, def)`**
    *   **旧版**: `_strToTimeDef(str, def)` / `_strToDateTimeDef(str, def)` / `_strToFloatDef(str, def)`
    *   **说明**: 解析字符串时间或浮点数，失败则采用传入的默认值。当前代码未注册 `StrToDateDef`。
*   **`FormatDateTime(formatStr, dateTime)`**
    *   **旧版**: `_formatDateTime(formatStr, dateTime)`
    *   **参数**:
        *   `formatStr: string` - 格式化模板，如 `'yyyy-mm-dd hh:nn:ss.zzz'`。
        *   `dateTime: number` - 待转化时间。
    *   **返回值**: `string`。

### 6. 文字编码与通用工具 (Encoding & Utils)
*   **`StringReplace(str, oldPattern, newPattern, flags)`**
    *   **旧版**: `_stringReplace(str, oldPattern, newPattern, flags)`
    *   **参数**:
        *   `str: string` - 原始文字。
        *   `oldPattern: string` - 被替换词。
        *   `newPattern: string` - 新词。
        *   `flags: string` - `'rfReplaceAll'`（全部替换）和 `'rfIgnoreCase'`（忽略大小写）组成的选项串。
    *   **返回值**: `string`。
*   **`Format(formatStr, argsArray)`**
    *   **旧版**: `_format(formatStr, argsArray)`
    *   **参数**: Delphi 风格的格式化串（如 `'%s has %d tables'`）以及对应的参数数组（如 `['ModelA', 15]`）。
    *   **返回值**: `string`。
*   **`EscapeXml(val)`**
    *   **旧版**: `_escapeXml(val)`
    *   **说明**: 对文本中的 XML 敏感字（如 `<`, `>`, `&`, `"`）进行实体转码。
*   **`CodeTextForLang(text, lang)`**
    *   **旧版**: `_codeTextForLang(text, lang)`
    *   **说明**: 将文本块按目标语言的字符串语法规则转义（如转义 JS/Java 双引号）。
*   **`ExtractCompStr(str, startMark, endMark, caseInsensitive, def)`** / **`AddOrModifyCompStr(str, subVal, startMark, endMark, caseInsensitive)`**
    *   **旧版**: `_extractCompStr(...)` / `_addOrModifyCompStr(...)`
    *   **说明**: 提取或新增/修改成对标记之间的片段文本。
*   **`StringExtToWideCode(str)`** / **`WideCodeNarrow(str)`**
    *   **旧版**: `_stringExtToWideCode(str)` / `_wideCodeNarrow(str)`
    *   **说明**: 扩展字符串与宽字符编码文本转换。
*   **`Utf8Encode(str)`** / **`Utf8Decode(str)`**
    *   **旧版**: `_utf8Encode(str)` / `_utf8Decode(str)`
    *   **说明**: UTF-8 编码/解码。
*   **`URLEncode(str)`** / **`URLDecode(str)`**
    *   **旧版**: `_uRLEncode(str)` / `_uRLDecode(str)`
    *   **说明**: 对 URL 中的特殊非安全字符进行 ASCII `%` 转义。
*   **`Utf8URLEncode(str)`**
    *   **旧版**: `_utf8URLEncode(str)`
    *   **说明**: 先按 UTF-8 编码后再做 URL 转义。
*   **`DmlStrLength(str)`**
    *   **旧版**: `_dmlStrLength(str)`
    *   **说明**: 按 EZDML 规则计算字符串长度。
*   **`ChnToPY(chnStr, opt)`**
    *   **旧版**: `_chnToPY(chnStr, opt)`
    *   **参数**: `chnStr: string` - 汉字文本。`opt: string` - 转换模式，如 `'pinyin'` (拼音全拼) 或 `'first'` (拼音首字母)。
    *   **返回值**: `string`。
    *   **说明**: 汉字快速拼音化工具。
*   **`AutoCapProc(str, opt)`**
    *   **旧版**: `_autoCapProc(str, opt)`
    *   **说明**: 根据 EZDML 命名规则进行自动大小写/命名转换。
*   **`IfElse(condition, trueVal, falseVal)`**
    *   **旧版**: `_ifElse(condition, trueVal, falseVal)`
    *   **说明**: 按条件返回两个值之一。
*   **`Clipboard()`**
    *   **旧版**: `_clipboard()`
    *   **返回值**: [TClipboard](file:///E:/gitH/ezdml_x/DML/besen/DmlBsClipboard.pas) - 系统剪贴板的包装对象。
*   **`IsReservedKeyword(word)`**
    *   **旧版**: `_isReservedKeyword(word)`
    *   **说明**: 判断字符串是否为数据库常用保留字。
*   **`Randomize()`** / **`RandomI(range)`** / **`RandomD()`**
    *   **旧版**: `_randomize()` / `_randomI(range)` / `_randomD()`
    *   **说明**: 初始化随机种子，产生随机整数（在 `[0, range-1]` 区间），产生随机浮点数（在 `[0, 1]` 区间）。
*   **`Beep()`**
    *   **旧版**: `_beep()`
    *   **说明**: 触发系统提示音。
*   **`RunCmd(cmd, timeout)`** / **`ExecAppCmd(cmd, param1, param2)`**
    *   **旧版**: `_runCmd(cmd, timeout)` / `_execAppCmd(cmd, param1, param2)`
    *   **说明**: 执行控制台命令或在独立进程环境执行外部命令。
*   **`GetUrlData(url, postData, opts)`**
    *   **旧版**: `_getUrlData(url, postData, opts)`
    *   **说明**: 发起 HTTP 请求并返回内容。
*   **`GetEnv(name)`** / **`GetEnvVar(name, def)`** / **`SetEnvVar(name, value)`**
    *   **旧版**: `_getEnv(name)` / `_getEnvVar(name, def)` / `_setEnvVar(name, value)`
    *   **说明**: 读取或设置环境变量。
*   **`CreateComponent`** / **`ReadDfmComponents`** / **`FindChildComp`**
    *   **旧版**: `_createComponent` / `_readDfmComponents` / `_findChildComp`
    *   **说明**: 动态创建、读取和查找 LCL 组件。
*   **`SetCompPropValue`** / **`GetCompPropValue`** / **`SetCompPropObject`** / **`GetCompPropObject`**
    *   **旧版**: 对应下划线版本。
    *   **说明**: 读写组件属性值或对象引用。
*   **`GetPointerByObj(obj)`** / **`GetObjByPointer(ptr)`**
    *   **旧版**: `_getPointerByObj(obj)` / `_getObjByPointer(ptr)`
    *   **说明**: 对象和指针整数之间互转，属于低层桥接工具。
*   **`Send_Msg(handle, msg, wParam, lParam)`**
    *   **旧版**: `_send_Msg(handle, msg, wParam, lParam)`
    *   **说明**: 发送窗口消息。
*   **`TextToShortCut(text)`**
    *   **旧版**: `_textToShortCut(text)`
    *   **说明**: 将快捷键文本转换为快捷键代码。

### 7. 数据模型与正向工程 (Database & Model)
*   **`CurDbType()`**
    *   **旧版**: `_curDbType()`
    *   **返回值**: `string` - 当前模型连接的数据库方言引擎代号（如 `'ORACLE'`, `'MYSQL'`, `'POSTGRESQL'`）。
*   **`ExecCtDbLogon(dbType, dbName, user, pwd, savePwd, autoLogin, showDlg, opt)`**
    *   **旧版**: `_execCtDbLogon(dbType, dbName, user, pwd, savePwd, autoLogin, showDlg, opt)`
    *   **说明**: 触发数据库连接登录流程，若参数指定了 `showDlg = true` 则弹出数据库登录 UI 弹窗。
*   **`ExecSql(sql, opts)`**
    *   **旧版**: `_execSql(sql, opts)`
    *   **参数**: 
        *   `sql: string` - 执行的查询或非查询 SQL 语句。
        *   `opts: string` - 配置参数项。
    *   **返回值**: 非查询SQL返回空；查询SQL返回JSON字典对象，包含字段和记录信息，示例：
        *   脚本：var ds = _execSql("SELECT user_id, user_name FROM sys_user WHERE user_id > 1");
            curOut.add(JSON.stringify(ds)); 
        *   输出：{"fields":["user_id","user_name"],"rows":[{"user_id":2,"user_name":"admin"},{"user_id":7,"user_name":"guest"}]}
    *   **说明**: 对已连接的物理数据库发起 SQL 指令。
*   **`SyncTableProps(tableObj)`**
    *   **旧版**: `_syncTableProps(tableObj)`
    *   **说明**: 强制使指定的物理表属性结构快速覆盖分发同步到其它模型图中的快捷映射副本上。
*   **`GetDbQuotName(dbType, name)`** / **`GetIdxName(tableName, fields, typeName)`**
    *   **旧版**: `_getDbQuotName(dbType, name)` / `_getIdxName(tableName, fields, typeName)`
    *   **说明**: 取得对应数据库方言包围保护的合法标识名称；或根据规则为表合成出特定字段的唯一索引物理名称。
*   **`GetCtDropDownItemsText(dropDownItems)`** / **`GetCtDropDownTextOfValue(...)`** / **`GetCtDropDownValueOfText(...)`**
    *   **旧版**: `_getCtDropDownItemsText(dropDownItems)` / `_getCtDropDownTextOfValue(...)` / `_getCtDropDownValueOfText(...)`
    *   **说明**: 快速辅助翻译解析字段枚举设置中（如 `1:男,2:女`）的选项值与展示标签。
*   **`GenData(rule)`** / **`GenDataEx(field, rule, defVal, rowIndex, opt, dataSet)`**
    *   **旧版**: `_genData(rule)` / `_genDataEx(field, rule, defVal, rowIndex, opt, dataSet)`
    *   **说明**: 调用 EZDML 内置的数据生成引擎生产用于仿真的测试假数据。
*   **`GetSelectedCtMetaObj()`**
    *   **旧版**: `_getSelectedCtMetaObj()`
    *   **返回值**: 当前选中的元数据对象，未选中时返回 `null`。
*   **`CtGenGUID()`**
    *   **旧版**: `_ctGenGUID()`
    *   **说明**: 生成 GUID 字符串。
*   **`CtObjToJsonStr(obj, fullProps, skipChild)`** / **`ReadCtObjFromJsonStr(obj, jsonStr)`**
    *   **旧版**: `_ctObjToJsonStr(obj, fullProps, skipChild)` / `_readCtObjFromJsonStr(obj, jsonStr)`
    *   **说明**: 元数据对象与 JSON 字符串互相转换。
*   **`GetAppDefTempPath()`** / **`GetAppTempFileName(fileName)`** / **`GetUnusedFileName(fileName)`**
    *   **旧版**: `_getAppDefTempPath()` / `_getAppTempFileName(fileName)` / `_getUnusedFileName(fileName)`
    *   **说明**: 获取应用临时目录、临时文件名或未占用文件名。
*   **`IsEnglish()`**
    *   **旧版**: `_isEnglish()`
    *   **说明**: 判断当前语言环境是否英文。

### 8. 全局跨域参数字典 (Global Properties)
*   **`GetGParamValue(name)`** / **`SetGParamValue(name, val)`**
    *   **旧版**: `_getGParamValue(name)` / `_setGParamValue(name, val)`
    *   **说明**: 读取/设置跨脚本会话保存的全局强类型字符串键值。
*   **`SetGParamValueEx(name, val, obj)`**
    *   **旧版**: `_setGParamValueEx(name, val, obj)`
    *   **说明**: 写入全局参数值并关联对象引用。
*   **`GetGParamObject(name)`** / **`SetGParamObject(name, obj)`**
    *   **旧版**: `_getGParamObject(name)` / `_setGParamObject(name, obj)`
    *   **说明**: 跨会话暂存或拉取一个 JS/Pascal 原生对象引用。

### 9. 脚本执行与流控 (Script Control)
*   **`LoadFile(filePath)`**
    *   **旧版**: `_loadFile(filePath)`
    *   **说明**: 引入、加载并立即执行另外一个外部 JavaScript 文件的内容（类似 Node.js 的 `require`）。
*   **`RunDmlScript(fileName, scriptText)`**
    *   **旧版**: `_runDmlScript(fileName, scriptText)`
    *   **说明**: 动态装载并编译执行一段 EZDML 自有 DSL 脚本。
*   **`Sleep(ms)`**
    *   **旧版**: `_sleep(ms)`
    *   **参数**: `ms: number` - 睡眠时长（毫秒）。
    *   **说明**: 阻断挂起当前脚本执行流一段时间。
*   **`RaiseErr(msg)`** / **`Abort()`**
    *   **旧版**: `_raiseErr(msg)` / `_abort()`
    *   **说明**: 显式抛出异常或静默中断当前执行流。
*   **`RaiseErrOut(msg)`** / **`AbortOut()`**
    *   **旧版**: `_raiseErrOut(msg)` / `_abortOut()`
    *   **说明**: 输出错误/中断信息后停止当前脚本。
*   **`Exit()`**
    *   **旧版**: `_exit()`
    *   **说明**: 强行终止退出当前的 JavaScript 脚本执行流。

---

## 四、 核心元数据类引用

所有的元数据类都可以通过属性向下挖掘层级：
`allModels` -> `curModel` -> `tables` -> `metaFields`。

### 1. 实体根类 [TCtObject](file:///E:/gitH/ezdml_x/DML/besen/DmlBsCtObject.pas)
所有模型图（`TCtDataModelGraph`）、表（`TCtMetaTable`）和字段（`TCtMetaField`）均继承自该类。

#### **读写属性**
*   `id`: `number` - 对象的内部唯一整型标识（如表 ID，字段 ID）。
*   `ctGuid`: `string` - 对象的全球唯一匹配识别 GUID。
*   `pid`: `number` - 父级对象的 ID。
*   `rid`: `number` - 关联的根对象 ID。
*   `name`: `string` - 逻辑名称（代码引用名，如表名 `sys_user`）。
*   `caption`: `string` - 展示标题说明（中文描述，如表中文名 `用户表`）。
*   `typeName`: `string` - 对象的内部类型分类标签。
*   `memo`: `string` - 备注内容。
*   `createDate` / `modifyDate`: `number` - 创建与修改的浮点型 TDateTime。
*   `creator` / `modifier`: `number` - 创建及修改者用户内部 ID。
*   `creatorName` / `modifierName`: `string` - 创建与修改者名字。
*   `historyID`: `number` - 历史记录 ID。
*   `versionNo`: `number` - 对象的修改版本次数。
*   `lockStamp`: `string` - 锁定戳。
*   `dataLevel`: `TctDataLevel` - 数据级别。
*   `orderNo`: `number` - 用于控制排序的浮点数。
*   `subItems`: `TCtObjectList` - 子集列表容器。
*   `parentList`: `TCtObjectList` - 自身被接纳所处的父级容器列表。
*   `globeList`: `TCtObjectList` - 全局对象列表。
*   `customAttr1` ~ `customAttr5`: `string` - 5个供二次开发自由读写的自定义字段属性。
*   `calValue`: `number` - 临时计算使用的整型缓存变量。
*   `calString`: `string` - 临时计算使用的字符串缓存变量.
*   `jsonStr`: `string` - 元数据对象的完整 JSON 表达文本；MCP JSON 工具读写的也是该属性。
*   `metaModified`: `Boolean` - 脏标记，表示元数据自上次保存后是否有变动。
*   `isSelected`: `Boolean` - 在设计区画布上是否被鼠标选中。
*   `isChecked`: `Boolean` - 在列表多选框中是否被勾选。

#### **只读属性**
*   `nameCaption`: `string` - 返回复合的“名称 - 标题”样式文字。
*   `displayText`: `string` - UI上实际呈递表现出的字符串。
*   `hasSubItems`: `Boolean` - 是否存在下辖子级。
*   `userObjectList`: `TStringList` - 用户自定义对象名列表。
*   `userObjectCount`: `number` - 用户自定义对象数量。
*   `paramList`: `TStringList` - 参数列表。
*   `paramCount`: `number` - 附加扩展参数的个数。

#### **方法**
*   `getParam(name)` / `setParam(name, value)`: 读写任意名字的附加配置参数。
*   `getUserObject(name)` / `setUserObject(name, obj)`: 绑定/读取用户自定义数据对象。
*   `sortByOrderNo()` / `sortByName()`: 对当前对象直辖下的子集列表按照 `orderNo` 或 `name` 重排。
*   `reset()`: 清空或重置该对象所有属性到初始默认配置。
*   `assignFrom(srcObj)`: 从另一个 `TCtObject` 深度拷贝全部属性值到自身。
*   `loadFromFile(path)` / `saveToFile(path)`: 从外部 JSON 元数据文件加载或序列化保存。
*   `saveToTempFile(ext)`: 快速存盘至系统的临时文件夹中，返回临时文件的绝对路径。
*   `execCmd(cmd, p1, p2)`: 向底层实体引擎派发特定的底层定制命令并获取返回字符串。
*   `doCustomEvent(a, b)`: 触发对象自定义事件。

---

### 2. 集合基类 [TCtObjectList](file:///E:/gitH/ezdml_x/DML/besen/DmlBsCtObjectList.pas)
继承自 `TList`，支持 **像普通 JavaScript 数组一样进行遍历和下标索引访问**。
  例如：`tables[0]` 代表获取第一个表。
  可以用for in循环遍历：for(var idx in tables) println(tables[idx].name)。
  兼容JS ARRAY的属性和方法，如length、push、pop、slice、forEach、some、map、filter等。

#### **只读属性**
*   `count`: `number` - 列表中包含的实体总数。
*   `capacity`: `number` - 列表内部容量。

#### **方法**
*   `getItem(index)`: 根据从 0 开始的物理序号提取对象。
*   `setItem(index, obj)`: 在指定位置强制注入/替换对象指针。
*   `getCtItem(index)` / `setCtItem(index, obj)`: 元数据对象索引读写接口。
*   `add(obj)`: 追加一个元素对象，返回新添加位置索引。
*   `clear()`: 彻底清空列表（注意：元数据列表清空将同时释放其管理的对象内存）。
*   `delete(index)`: 移除并销毁指定索引位置的对象。
*   `exchange(index1, index2)`: 交换两个元素位置。
*   `insert(index, obj)`: 在指定位置插入对象。
*   `move(curIndex, newIndex)`: 移动对象位置。
*   `remove(obj)`: 检索并移除销毁指定的对象。
*   `mereRemove(obj)`: 只从列表移除对象，不释放对象。
*   `indexOf(obj)`: 检索对象的物理索引序号，未找到返回 -1。
*   `pack()`: 重新排版数组并清除占位的空指针实体。
*   `assignFrom(srcList)`: 从另一个列表复制内容。
*   `newObj()`: 实例化一个当前列表所管理类型的新元素并追加至末尾。
*   `notifyChildFree(obj)`: 子项释放通知。
*   `createGlobeList()`: 创建全局列表。
*   `itemByID(id)`: 根据整型 ID 全局匹配查找子实体，失败返回 `null`。
*   `itemByName(name)`: 根据逻辑名称匹配子实体（缺省忽略大小写）。
*   `itemByCtGuid(guid)`: 根据 GUID 检索子实体。
*   `nameOfID(id)`: 查询指定 ID 实体对象的名字。
*   `sortByOrderNo()` / `sortByName()`: 按照物理显示顺序或字母重排实体数组。
*   `saveCurrentOrder()`: 将物理索引转换为各子项的 `orderNo` 值保存。
*   `checkMaxSeq()`: 检查并修正最大序号。

---

### 3. 模型列表与模型图对象

#### **[TCtDataModelGraphList](file:///E:/gitH/ezdml_x/DML/besen/DmlBsCtDataModelGraphList.pas) (`allModels` 的类型)**
继承自 `TCtObjectList`，拥有以下特有接口：
*   **属性 `curDataModel`**: `TCtDataModelGraph` [读写] - 读写当前前台展示的活动模型页面。
*   **方法 `loadFromFile(path)` / `saveToFile(path)`**: 从文件加载或保存模型列表。
*   **方法 `newModelItem()`**: 新建一个可视化的模型图页面并返回它。
*   **方法 `newCatalogItem()`**: 新建一个分组目录节点并返回它。
*   **方法 `tableCount()`**: 统计该层级下的表总数。

#### **[TCtDataModelGraph](file:///E:/gitH/ezdml_x/DML/besen/DmlBsCtDataModelGraph.pas) (`curModel` 的类型)**
继承自 `TCtObject`，代表一个模型图页面。
*   **只读属性 `displayName`**: UI 上实际显示的模型图名称。
*   **读写属性 `graphWidth` / `graphHeight`**: 画布的像素宽度与高度。
*   **读写属性 `defDbEngine`**: 数据库默认方言类型（如 `'ORACLE'`, `'MYSQL'`）。
*   **读写属性 `dbConnectStr`**: 数据源的默认物理连接字符串。
*   **读写属性 `configStr`**: 该页面独立的复杂行为控制选项。
*   **读写属性 `modelPath`**: 导出文件或生成代码时的归档目录相对路径。
*   **读写属性 `purviewRoles`**: 配置具备访问当前模块的角色名。
*   **读写属性 `publishType`**: TCtModulePublishType - 模块发布类别。
*   **读写属性 `extraProps`**: 模型图扩展属性。
*   **读写属性 `tables`**: [TCtMetaTableList](#4-数据表列表与数据表对象) - 该画布页面中呈现的数据表集合列表。
*   **只读属性 `ownerList`**: 所属模型图列表。
*   **方法 `isCatalog()`**: `Boolean` - 是否为单纯的分组目录节点。
*   **方法 `isModel()`**: `Boolean` - 是否为容纳实体表的真正模型图。

---

### 4. 数据表列表与数据表对象

#### **[TCtMetaTableList](file:///E:/gitH/ezdml_x/DML/besen/DmlBsCtMetaTableList.pas)**
继承自 `TCtObjectList`。
*   **只读属性 `ownerModel`**: 指向持有此表列表的模型图页面对象。
*   **读写属性 `describe`**: 该表列表总括性描述。
*   **方法 `newTableItem()`**: 创建并加入一张新表，返回该表对象。

#### **[TCtMetaTable](file:///E:/gitH/ezdml_x/DML/besen/DmlBsCtMetaTable.pas)**
继承自 `TCtObject`，承载数据库物理表结构的元数据。

##### **主要属性**
*   `ownerList`: [TCtMetaTableList](#4-数据表列表与数据表对象) [只读] - 直属的容器列表。
*   `customModId`: `string` [读写] - 自定义模块 ID。
*   `metaFields`: [TCtMetaFieldList](#5-字段列表与字段对象) [只读] - 该表拥有的字段（列）集合列表。
*   `keyFieldName`: `string` [只读] - 提取的主键列名称（若为联合主键则返回第一个）。
*   `realTableName`: `string` [只读] - 结合命名规则自动计算并替换后缀后的实际物理表名。
*   `physicalName`: `string` [读写] - 用户定义写入的原始物理表名。
*   `UIDisplayName`: `string` [只读] - 中文或UI上的综合标识名称（包含中文注释标题）。
*   `UIDisplayText`: `string` [读写] - 强制用户指定的画布别名。
*   `bgColor`: `number` [读写] - 颜色整型代码（如 RGB 数值）。
*   `graphDesc`: `string` [读写] - 表在画布中的几何定位及排布坐标配置。
*   `describe`: `string` [读写] - 详细的表结构描述说明。
*   `sketchyDescribe`: `string` [只读] - 简述文本。
*   `designNotes`: `string` [读写] - 设计备忘录。
*   `genDatabase` / `genCode`: `Boolean` [读写] - 正向建库/代码生成时是否包含该表的开关。
*   `publishType`: `TCtModulePublishType` [读写] - 发布类型。为cmptNone时默认不应生成代码，为 cmptAuto 取决上所属父模型的发布类型。
*   `isReadOnly`: `Boolean` [读写] - 表是否处于界面只读防修改保护。
*   `viewSQL` / `listSQL`: `string` [读写] - 用于非物理表（视图 SQL 编写或界面分页查询连表 SQL）。
*   `extraSQL`: `string` [读写] - 建表指令后紧跟并下发给数据库的附带批量 SQL 代码。
*   `UILogic` / `businessLogic`: `string` [读写] - 表表单界面前端拦截与保存时后台脚本逻辑。
*   `extraProps`: `string` [读写] - 扩展属性。
*   `customConfigs`: `string` [读写] - JSON 序列化存储的扩展定制配置项。
*   `scriptRules`: `string` [读写] - 表强校验和填补规则的表达式。
*   `SQLWhereClause` / `SQLOrderByClause` / `SQLAlias`: `string` [读写] - 连表提取数据的各种过滤、排序和别名子句。
*   `ownerCategory` / `groupName`: `string` [读写] - 归档目录与 UI 中的分组栏位名。
*   `partitionInfo`: `string` [读写] - 针对海量数据的分区表方案定义。
*   `identifyCode`: `string` [读写] - 表级别的特殊验证特征码。
*   `purviewRoles` / `dataPurview`: `string` [读写] - 表单访问控制角色名与行级过滤 SQL 权限串。

##### **主要方法**
*   `syncPropFrom(table)`: 从另一张表同步属性。
*   `getTableComments()`: 生成表注释文本。
*   `isTable()` / `isText()` / `isSqlText()`: 是否为真实物理表、便签面板、或存储过程 SQL 文本。
*   `isManyToManyLinkTable()`: `Boolean` - 是否为多对多交叉桥接关联表。
*   `getPrimaryKeyNames(quotDbType)`: 获取主键字段名集合，逗号分隔，可指定数据库引用风格。
*   `getTitleFieldName()`: 获取标题字段名。
*   `getPrimaryKeyField()`: 返回第一个主键字段对象 `TCtMetaField`。
*   `getOneToManyInfo(fksOnly)`: 获取一对多关联信息。
*   `getManyToManyInfo()`: 获取多对多关联信息。
*   `fieldOfChildTable(childTableName)`: 搜索在此表中对外引用了 `childTableName` 的外键字段对象。
*   `genSqlEx(createTb, fk, dbType)`: 生成 DDL，可控制是否包含建表和外键。
*   `genSql(dbType)`: 返回适应目标数据库类型的 `CREATE TABLE` DDL 建表 SQL 文本。
*   `genSqlWithoutFK()`: 生成不包含 `FOREIGN KEY` 声明的建表 DDL。
*   `genFKSql()`: 单独生成添加外键约束的 `ALTER TABLE` DDL 语句。
*   `genDqlDmlSql(dbType)`: 生成 DQL/DML SQL。
*   `genSelectSql(maxCount, dbType)`: 自动装配并返回一个标准取数的 `SELECT * FROM ...` SQL 语句。
*   `getSpecKeyNames(keyFieldTp, quotDbType)`: 获取指定键类型字段名。
*   `getPossibleKeyName(keyFieldTp)`: 获取推荐键名。
*   `getDemoJsonData(rowIndex, opt, fields)`: 生成调试用的假数据 JSON 数组文本。
*   `getCustomConfigValue(name)` / `setCustomConfigValue(name, val)`: 读写特定配置 JSON 中的值。

---

### 5. 字段列表与字段对象

#### **[TCtMetaFieldList](file:///E:/gitH/ezdml_x/DML/besen/DmlBsCtMetaFieldList.pas)**
继承自 `TCtObjectList`。
*   **只读属性 `ownerTable`**: 指向持有此字段列表的父表对象 `TCtMetaTable`。
*   **方法 `newMetaField()`**: 在表末尾追加创建一个新的字段对象 `TCtMetaField` 并返回它。
*   **方法 `fieldByName(name)`**: 根据字段逻辑名称进行查找，忽略大小写。
*   **方法 `fieldByDisplayName(dispName)`**: 根据字段的 DisplayName 别称匹配寻找。
*   **方法 `fieldByLabelName(label)`**: 根据界面表单的标签文字查找字段。

#### **[TCtMetaField](file:///E:/gitH/ezdml_x/DML/besen/DmlBsCtMetaField.pas)**
继承自 `TCtObject`，代表字段（列）元数据。

##### **主要属性**
*   `ownerList`: [TCtMetaFieldList](#5-字段列表与字段对象) [只读] - 字段所归属的列表。
*   `ownerTable`: [TCtMetaTable](#4-数据表列表与数据表对象) [只读] - 字段所归属的主表对象。
*   `displayName`: `string` [读写] - 字段中文说明/业务名。
*   `dataType`: `TCtFieldDataType` [读写] - 内部中立数据类型代号。
*   `dataTypeName`: `string` [读写] - 物理数据库对应的具体类型声明（如 `'VARCHAR2(100)'`）。
*   `keyFieldType`: `TCtKeyFieldType` [读写] - 是否是主键/外键等（普通, 主键PK, 外键FK）。
*   `relateTable`: `string` [读写] - 外键所映射关联的主表逻辑名（如 `'sys_user'`）。
*   `relateTableRealName`: `string` [只读] - 关联主表在后缀计算后真实的物理表名。
*   `relateField`: `string` [读写] - 关联主表的关联字段（常为主键）。
*   `indexType`: `TCtFieldIndexType` [读写] - 索引形式（无,  普通索引, 唯一约束 UNIQUE）。
*   `indexFields`: `string` [读写] - 联合索引中共同参编的其它协作字段列表。
*   `url`: `string` [读写] - 链接地址。
*   `resType`: `number` [读写] - 资源类型。
*   `resSQL`: `string` [读写] - 资源 SQL。
*   `resSQLWhere`: `string` [读写] - 资源 SQL 条件。
*   `nullable`: `Boolean` [读写] - 数据库底层是否允许 `NULL`。
*   `required`: `Boolean` [读写] - 前端表单是否为必填项（是否打红星）。
*   `dataLength`: `number` [读写] - 物理字符/字节长度。
*   `dataScale`: `number` [读写] - 小数精度。
*   `maxLength`: `number` [读写] - 界面输入控制的最大字符数限制。
*   `defaultValue`: `string` [读写] - 建表时的默认值。
*   `initValue`: `string` [读写] - 界面新增记录时预填入的初始文本值。
*   `valueMin` / `valueMax`: `string` [读写] - 取值的区间限制上限与下限。
*   `DBCheck`: `string` [读写] - 字段绑定的物理 `CHECK` 过滤约束条件。
*   `SQLExpression`: `string` [读写] - 对应虚拟字段的提取拼接 SQL 表达式。
*   `formula` / `formulaCondition`: `string` [读写] - 满足前置条件时触发回填运算的计算公式。
*   `aggregateFun`: `string` [读写] - 聚合函数。
*   `measureUnit`: `string` [读写] - 计量单位。
*   `validateRule`: `string` [读写] - 校验规则。
*   `editorType`: `string` [读写] - 指定前端录入渲染的组件微件类型（如 `'TEXT'`, `'DATE'`, `'MEMO'`, `'COMBO'` 等）。
*   `labelText`: `string` [读写] - 表单标签文字。
*   `editorReadOnly` / `editorEnabled`: `Boolean` [读写] - 编辑状态下置灰或只读。
*   `explainText` / `hint`: `string` [读写] - 气泡提示语或辅助性输入注解文字。
*   `visibility`: `number` [读写] - 显示级别。
*   `isHidden` / `hideOnList` / `hideOnEdit` / `hideOnView`: `Boolean` [读写] - 分别控制该列在不同使用场景下的显隐遮蔽。
*   `displayFormat` / `editFormat` / `valueFormat`: `string` [读写] - 数字千分位或日期展示掩码。
*   `fontName` / `fontSize` / `fontStyle` / `foreColor` / `backColor`: [读写] - 控制界面上单元格展现的字体、大小、高亮色及背景色。
*   `textAlign`: `TCtTextAlignment` [读写] - 对齐方式（靠左, 居中, 靠右）。
*   `fixColType`: `TCtFieldFixColType` [读写] - 表格列冻结样式（不冻结, 左侧固定, 右侧固定）。
*   `colWidth`: `number` [读写] - 初始列的像素宽度。
*   `searchable` / `queryable` / `exportable`: `Boolean` [读写] - 是否可搜索、可查询、可导出。
*   `autoMerge` / `colSortable` / `showFilterBox`: `Boolean` [读写] - 控制重复相邻行内容自动合并、允许点击列头重新排序、或顶部显示快捷过滤框。
*   `dropDownItems`: `string` [读写] - 枚举静态下拉选项，多行换行分割。
*   `dropDownSQL`: `string` [读写] - 动态拉取下拉列表的 SQL 指令。
*   `dropDownMode`: `TCtFieldDropDownMode` [读写] - 下拉选择限制模式。
*   `itemColCount`: `number` [读写] - 下拉/选项每行列数。
*   `textClipSize`: `number` [读写] - 文本裁剪长度。
*   `sheetGroup` / `colGroup`: `string` [读写] - 表单分页选项卡（Tab）的归类名字，以及多层复合表头的分组名。
*   `extraProps`: `string` [读写] - 扩展属性。
*   `editorProps`: `string` [读写] - 编辑器扩展属性。
*   `graphDesc`: `string` [读写] - 图形描述。
*   `customConfigs`: `string` [读写] - 自定义配置。
*   `designNotes`: `string` [读写] - 字段设计注解。
*   `autoTrim`: `Boolean` [读写] - 是否自动去除首尾空格。
*   `UILogic` / `businessLogic`: `string` [读写] - 前端逻辑与业务逻辑。
*   `isFactMeasure`: `Boolean` [读写] - 是否标记为度量分析值。
*   `desensitised`: `Boolean` [读写] - 界面渲染时是否脱敏打码。
*   `testDataRules` / `testDataNullPercent`: [读写] - 模拟仿真生成假数据的规律引擎及随机空白几率。
*   `fieldWeight`: `number` [读写] - 字段权重。

##### **主要方法**
*   `isPK()` / `isFK()` / `isPhysicalField()` / `isSqlSelField()`: 判断是否为主键、外键、物理存在的字段、参与 SQL 选择的字段。
*   `getLogicDataTypeName()`: 返回逻辑数据类型名。
*   `isLobField(dbType)`: `Boolean` - 是否为大文本块 LOB 字段。
*   `getPhyDataTypeName(dbType)`: 返回对应的物理数据库类型名（如 `NVARCHAR2` 等）。
*   `getFieldTypeDesc(bPhy, dbType)`: 返回包含长度精度的完整属性陈述描述（如 `VARCHAR2(50)` ）。
*   `getFieldComments()`: 返回字段注释文本。
*   `getFieldDefaultValDesc(dbType)`: 返回默认值描述。
*   `getConstraintStr(dbType)`: 获取字段约束的 DDL 构建串。
*   `setConstraintStr(value)`: 写入字段约束串。
*   `getConstraintStrEx(withKeys, withRelate)`: 获取扩展字段约束串。
*   `setConstraintStrEx(value, force)`: 写入扩展字段约束串。
*   `hasValidComplexIndex()`: 判断是否有有效复合索引。
*   `possibleKeyFieldType()`: 推断键类型。
*   `canDisplay(tp)`: 判断指定显示场景下是否可显示。
*   `isRequired()`: 判断字段是否必填。
*   `getLabelText()`: 获取标签文字。
*   `possibleEditorType()`: 推断编辑器类型。
*   `getSQLSelExpression()`: 获取 SQL 选择表达式。
*   `possibleTextAlign()`: 推断文本对齐方式。
*   `getRelateTableObj()`: 返回所指向引用的外键主表对象 `TCtMetaTable`（若非外键返回 `null`）。
*   `getRelateTableField()`: 返回所引用的外键表的主键字段对象 `TCtMetaField`。
*   `getRelateTableTitleField()`: 返回所引用的外键表中通常用于显示中文代称的标识字段对象。
*   `genDemoData(rowIndex, opt, dataset)`: 根据规则随机产出该列的一个假数据样本。
*   `getDemoItemList(textOnly)`: 获取演示下拉项。
*   `possibleDemoDataRule()`: 推断测试数据生成规则。
*   `extractDropDownItemsFromMemo()`: 从备注中提取下拉项。
*   `getRelateTableDemoJson(rowIndex, opt)`: 获取关联表演示 JSON。
*   `getCustomConfigValue(name)` / `setCustomConfigValue(name, val)`: 读写特定配置 JSON 中的值。

---

## 五、 脚本配置面板类引用

用于在脚本运行前动态生成参数输入界面，目前仅在 表属性、字段属性 的 快速生成代码 和 自定义属性 等GUI 界面上使用。全局变量 `curSettingsPanel` 即为 [TDmlScriptControlList](file:///E:/gitH/ezdml_x/DML/besen/DmlBsDmlScriptControl.pas)。

### 1. 控件列表类 [TDmlScriptControlList](file:///E:/gitH/ezdml_x/DML/besen/DmlBsDmlScriptControl.pas)

#### **读写属性**
*   `curFileName`: `string` - 当前脚本文件名。
*   `curAction`: `string` - 当前动作。
*   `textDesc`: `string` - 配置面板说明文本。
*   `jsonValStr`: `string` - 控件值 JSON 文本。
*   `parentWnd`: `TWinControl` - 父窗口对象。

#### **方法**
*   `newItem()`: 新建一个控件配置项 `TDmlScriptControl`。
*   `getItem(index)` / `putItem(index, obj)`: 读写指定索引的控件配置项。
*   `getItemValue(name)` / `setItemValue(name, value)`: 按控件名读取或写入控件值。
*   `regenControls()`: 重新生成界面控件。
*   `saveSettings()`: 保存当前设置。

### 2. 控件配置类 [TDmlScriptControl](file:///E:/gitH/ezdml_x/DML/besen/DmlBsDmlScriptControl.pas)

#### **实例化构造**
*   `var ctl = new TDmlScriptControl();`

#### **读写属性**
*   `id`: `number` - 控件 ID。
*   `controlType`: `string` - 控件类型。
*   `name`: `string` - 控件名。
*   `caption`: `string` - 控件标题。
*   `items`: `string` - 候选项。
*   `value`: `string` - 当前值。
*   `params`: `string` - 扩展参数。
*   `textDesc`: `string` - 说明文本。
*   `control`: `TControl` - 实际 LCL 控件对象。

#### **方法**
*   `hasValue()`: 是否有有效值。

---

## 六、 系统与功能类引用

在自动化生成、读写文件或进行网络请求时，EZDML JavaScript 提供了若干核心的 Pascal 类包裹。

### 1. 列表操作类 [TStringList](file:///E:/gitH/ezdml_x/DML/besen/DmlBsStrings.pas)
常用于文本行的保存、文件读写、INI 项加载等。全局变量 `curOut` 就是其实例。

#### **读写属性**
*   `capacity`: `number` - 内部数组的预分配容量。
*   `text`: `string` - 整个列表作为一大段多行字符串的表现（各行以换行符连接）。
*   `commaText`: `string` - 逗号分隔拼接的文本单行表现形式。
*   `delimitedText`: `string` - 依照 `delimiter` 和 `quoteChar` 构筑的防冲突分割拼接大文本。
*   `delimiter` / `quoteChar` / `nameValueSeparator`: `string` (单个字符) - 定义分割符、包围符、及 `Name=Value` 下的名值分隔符。
*   `lineBreak`: `string` - 行分隔换行字符。
*   `strictDelimiter`: `Boolean` - 是否强制严格遵循分隔符。

#### **只读属性**
*   `count`: `number` - 列表中目前容纳的文件文本行数。

#### **方法**
*   `add(str)`: 在尾部新增一行文本，返回索引。
*   `addObject(str, obj)`: 写入文本行并同时捆绑关联一个指针对象。
*   `append(str)`: 追加一行文本。
*   `addStrings(stringsObj)`: 整体合并导入另一个 `TStringList`。
*   `clear()`: 彻底清空列表。
*   `delete(index)`: 移除指定物理行的文字。
*   `indexOf(str)`: 查找所在行数索引，未找到返回 -1。
*   `insert(index, str)`: 在特定行插入文本。
*   `loadFromFile(filePath)` / `saveToFile(filePath)`: 读取或保存到物理文件中。
*   `sort()`: 对列表行进行字母表升序排序。
*   `getString(index)` / `setString(index, str)`: 读写指定行的文本。
*   `getName(index)`: 提取该行格式为 `Name=Value` 时的 `Name` 部分。
*   `getValue(name)` / `setValue(name, value)`: 读写 `Name=Value` 中指定键的 `Value` 值。
*   `getValueFromIndex(index)` / `setValueFromIndex(index, value)`: 根据索引读写 `Value` 部分。

---

### 2. 二进制文件流类 [File](file:///E:/gitH/ezdml_x/DML/besen/DmlBsFileStream.pas)
用于对文件进行字节级的读写定位。

#### **实例化构造**
*   `var f = new File(filePath, mode)`
    *   `mode` 可选参数：
        *   `'c'`: 创建新文件（若存在则清空重构）。
        *   `'r'`: 只读模式打开文件。
        *   `'w'`: 只写模式打开。
        *   `'rw'`: 读写混合模式（默认）。

#### **读写属性**
*   `position`: `number` - 读写指针目前的绝对字节偏移位置。
*   `size`: `number` - 物理文件的总大小。

#### **只读属性**
*   `fileName`: `string` - 所持有的物理文件绝对路径。
*   `eof`: `Boolean` - 读写指针是否已越过文件末尾。

#### **方法**
*   `read(length)`: 读取指定长度的字节，返回读取的**字符串内容**。若未指定长度，则默认一直读取至文件结束。
*   `write(str)`: 向文件写入字符串的二进制值。
*   `seek(offset, origin)`: 移动读写指针偏移。`origin` 指针基准参数：`0` 代表文件头，`1` 代表当前位置，`2` 代表文件尾。
*   `copyFrom(sourceStream, count)`: 从另一个数据流或文件流中直接对拷 `count` 字节的数据。
*   `flush()`: 强制刷新文件写入缓冲区物理落盘。
*   `close()`: 显式关闭并释放文件句柄。

---

### 3. 配置类 [TIniFile](file:///E:/gitH/ezdml_x/DML/besen/DmlBsIniFile.pas)
用于读写标准的 Windows `*.ini` 结构格式的配置参数。

#### **读写属性**
*   `caseSensitive`: `Boolean` - 控制配置的小数点、键名大小写敏感性。

#### **只读属性**
*   `fileName`: `string` - 配置文件路径。

#### **主要方法**
*   `readString(section, key, defaultVal)`: 获取对应节点键下的文本。
*   `writeString(section, key, val)`: 写入键值文本。
*   `readInteger(section, key, defaultVal)` / `writeInteger(section, key, val)`: 读写整数。
*   `readBool(section, key, defaultVal)` / `writeBool(section, key, val)`: 读写布尔值。
*   `readFloat(...)` / `writeFloat(...)`: 读写浮点数。
*   `readDate(...)` / `writeDate(...)`: 读写日期值。
*   `readTime(...)` / `writeTime(...)`: 读写时间值。
*   `readDateTime(...)` / `writeDateTime(...)`: 读写日期时间值。
*   `readBinaryStream(...)` / `writeBinaryStream(...)`: 读写二进制流。
*   `readSections(stringsObj)`: 获取所有的节点名称（Section 名）装填进 TStringList。
*   `readSection(section, stringsObj)`: 获取指定节点下的所有键名写入到 TStringList。
*   `readSectionValues(section, stringsObj)`: 获取指定节点下的所有名值对 `Key=Value` 行。
*   `sectionExists(section)`: `Boolean` - 判断节点是否存在。
*   `valueExists(section, key)`: `Boolean` - 判断节点下的键是否存在。
*   `eraseSection(section)`: 删除整个节点。
*   `deleteKey(section, key)`: 仅删除节点下的某个指定键。
*   `updateFile()`: 强制内存中的缓存配置刷新到物理磁盘文件中。

---

### 4. 剪贴板类 [TClipboard](file:///E:/gitH/ezdml_x/DML/besen/DmlBsClipboard.pas)
通过全局函数 `Clipboard()` 获取系统剪贴板包装对象。

#### **主要属性**
*   `asText`: `string` [读写] - 剪贴板文本内容。
*   `formatCount`: `number` [只读] - 当前剪贴板格式数量。

#### **主要方法**
*   `open()` / `close()`: 打开或关闭剪贴板访问。
*   `clear()`: 清空剪贴板。
*   `assign(source)`: 从其它对象复制内容。
*   `hasFormat(formatId)`: 判断是否包含指定格式。
*   `getFormats(index)`: 获取指定索引的格式 ID。
*   `getAsHandle(formatId)` / `setAsHandle(formatId, handle)`: 读写指定格式的句柄。
*   `getTextBuf(buffer, bufSize)` / `setTextBuf(buffer)`: 低层文本缓冲访问。

---

### 5. 前端窗口类 [TForm](file:///E:/gitH/ezdml_x/DML/besen/DmlBsForm.pas)
可在脚本中弹出包含自定义 UI 控件的原生前端弹窗。

#### **主要属性**
*   `active`: `Boolean` [只读] - 窗口是否正处于活动焦点状态。
*   `modalResult`: `number` [读写] - 对话框返回结果，常用 `IDOK` / `IDCANCEL` 控制弹窗返回。
*   `windowState`: `number` [读写] - 窗口状态（0: 普通, 1: 最小化, 2: 最大化）。
*   `borderStyle`: `number` [读写] - 边框样式（0: 无边框, 1: 单线, 2: 标准对话框）。

#### **主要方法**
*   `show()`: 非模态弹出窗口。
*   `showModal()`: **模态阻塞式弹出窗口**（常用于参数录入，并检测 `modalResult`）。
*   `close()`: 发起关闭窗口请求。
*   `hide()`: 隐藏窗口。
*   `release()`: 强制销毁释放该窗口占用的内存资源。

---

## 七、 实用脚本说明与示例

本节为脚本常用经验，偏向“怎么写脚本”，接口全集仍以前文为准。

### 1. 脚本窗口与运行约定
*   脚本编辑窗口中按 `F9` 运行，按 `F1` 显示帮助。
*   `File | New` 会初始化示例脚本；连续新建时，可在 JS 与 Pascal 示例之间切换。
*   JS 脚本目前不支持断点和单步调试，通常通过 `curOut.add(...)`、`alert(...)`、`WriteLog(...)` 或 `println(...)` 辅助观察。
*   PrintLn、WriteLn等默认输出转到curOut，而ReadLn则会弹出提示输入的对话框。
*   `curOut` 在不同场景指向不同输出位置：调试时通常是脚本窗口输出框，表属性生成时是生成结果框，批量生成时会被保存为目标文件内容；某些临时执行场景下可能不会显示。
*   脚本窗口关闭、编译或运行时，会把当前内容自动保存到临时文件；可通过 `File | Show Temporary File` 找回历史临时文件。
*   JS 与 Pascal 脚本文件均使用 UTF-8 编码，建议外部编辑器也保存为 UTF-8。

### 2. 遍历模型、表和字段
JS 对大小写敏感，核心对象通常使用 lowerCamelCase。列表对象可通过 `getItem(index)` 或JS ARRAY的方式（forEach等）访问元素。

```javascript
// 本示例展示用 for in、for++、forEach 等不同的方法遍历列表

for (var i in allModels) {
  var md = allModels[i];
  println('Model' + i + ': ' + md.name);

  for (var j = 0; j < md.tables.count; j++) {
    var tb = md.tables.getItem(j);
    curOut.add('  Table' + j + ': ' + tb.name);

    tb.metaFields.forEach(function(fd, index, array) {   
      curOut.add('    Field' + index + ': ' + fd.name);
    });
  }

  // JS 占用较高时，可按需触发一次回收。
  _gc();
}  
```

只处理当前表时，要先判断 `curTable` 是否为空：

```javascript
if (!curTable) {
  AbortOut();
}

for (var i = 0; i < curTable.metaFields.count; i++) {
  var fd = curTable.metaFields.getItem(i);
  curOut.add('member1.' + fd.name + ' = member2.' + fd.name + ';');
}
```

请注意EZDML的JS引擎不支持不同类型的值进行真假布尔运算，需要拆开，如：

```javascript
var hasTwo=(allModels.count>1);
if (curTable && hasTwo) {//错误
  //
}
if (curTable) {
  if (hasTwo) {//正确
    //
  }
}
```

### 3. 批量修改字段

以下示例给每个包含 `id` 字段、但尚无 `memo` 字段的表追加备注字段。字段类型、索引类型等枚举值在 JS 中通常可用字符串形式赋值。

```javascript
for (var i = 0; i < allModels.count; i++) {
  var md = allModels.getItem(i);

  for (var j = 0; j < md.tables.count; j++) {
    var tb = md.tables.getItem(j);
    if (!tb.metaFields.fieldByName('id')) {
      continue;
    }

    var fd = tb.metaFields.fieldByName('memo');
    if (!fd) {
      fd = tb.metaFields.newMetaField();
      fd.name = 'memo';
      fd.displayName = '备注';
      fd.memo = '脚本批量添加的字段';
      fd.dataType = 'cfdtString';
      fd.dataLength = 512;
      fd.indexType = 'cfitNormal';
      fd.nullable = true;
      curOut.add(tb.name + ': memo field added');
    }
  }
}
```

如果只修改了某一张物理表，而同名表在其它模型图中存在快捷映射，需要在修改后调用 `SyncTableProps(tb)` / `_syncTableProps(tb)` 同步属性。

删除字段可用列表的 `remove`：

```javascript
var fd = curTable.metaFields.fieldByName('remark');
if (fd) {
  curTable.metaFields.remove(fd);
}
```

### 4. 页面模板、Include 与生成代码
脚本内容以 `<%` 开头时，会按页面模板方式预处理。`<% ... %>` 中写原始 JS，其它内容会输出到 `curOut`；模板中可用 `${expr}` 插入表达式。

```html
<%
for (var i = 0; i < curTable.metaFields.count; i++) {
  var f = curTable.metaFields.getItem(i);
%>
${f.name}: ${f.displayName}
<% } %>
```

模板规则：
*   不希望 `${...}` 被识别时，可在模板中加入 `//[NO_DOLLAR_EXPRESSION]//`，改用 `@[expr]`。
*   某段模板内容需要原样输出 `${...}` 时，可用单独成行的 `[[[` 与 `]]]` 包住。
*   JS include 写法为 `#include "file.js"`，文件名通常按宿主脚本所在目录解析。EZDML 会在执行前拼接 include 内容。

表属性“生成”页与“模型 | 生成代码”会使用 `Templates` 目录下的模板文件。如果同名 JS 和 Pascal 模板同时存在，通常 JS 优先。批量生成时可在子目录放置 `_dml_config.INI`，常见配置包括：

```ini
[index_top.html]
rename=#curmodel_name#_index_top.html
run_as_script=js
encoding=utf8

[table_ui]
rename=ui_#curtable_name:LowerCase#
loop_each_table=1
skip_exists=1
```

生成文件名支持 `UpperCase`、`LowerCase`、`AutoCapitalize`、`CamelCaseToUnderline`、`UnderlineToCamelCase`、`ChnToPY`、`ClassName`、`FieldName` 等转换器，可用冒号连续串接。

生成脚本运行前，系统会设置常用全局参数：`GCODE_SRC_ROOT`、`GCODE_DST_ROOT`、`GCODE_SRC_FILENAME`、`GCODE_DST_FILETEMPLATE`、`GCODE_DST_FILENAME`、`GCODE_ENCODING`。可用 `GetGParamValue` / `SetGParamValue` 读取或修改。若脚本自行保存文件，或不希望系统保存 `curOut`，可清空 `GCODE_DST_FILENAME` 或调用 `AbortOut()`。

`CustomTools` 目录下的文件会自动生成工具菜单项；其中 JS/Pascal 文件会尝试作为脚本执行。自定义表属性 UI 与字段属性 UI 分别由 `Templates/CustomTableDef.js_/.ps_` 和 `Templates/CustomFieldDef.js_/.ps_` 控制，JS 文档中的示例以 `.js_` 为主，通常配合参数面板与对象的 `customConfigs` 使用。

### 5. 参数面板
在表、字段属性 GUI 的生成页或自定义属性页中，可在脚本开头写入 `SettingsPanel` 注释块生成参数面板。JS 文件中需要再用 JS 注释包住这段配置。

```javascript
/*
(*[SettingsPanel]
Control="Label";Caption="Please choose parameters";Params="[FULLWIDTH][HEIGHT=40]"
Control="Edit";Name="Author";Caption="Author";Value="huz";Params="[FULLWIDTH]"
Control="ComboBox";Name="GenType";Caption="Generate type";Items="Type1,Type2,Type3";Value="Type1"
[/SettingsPanel]*)
*/

var author = curSettingsPanel ? curSettingsPanel.getItemValue('Author') : '';
```

第一次加载执行时，`curSettingsPanel.curAction` 常为 `init`。后续控件值改变或按钮触发时，该值会更新并重新执行脚本。

### 6. 外部程序、混合脚本与事件限制
*   `ShellOpen(fileName, params, dir)` 可打开 EXE、文档或目录。
*   `RunCmd(cmd, timeout)` 可执行命令行并返回输出。
*   `RunDmlScript(fileName, scriptText)` / `_runDmlScript(...)` 可按文件后缀执行 JS 或 Pascal 脚本。
*   JS 不能直接声明外部 DLL 函数；需要时可通过 `RunDmlScript` 调用 Pascal 脚本，再用全局参数传回结果。
*   全局事件脚本 `GlobalScript.ps_` 目前仅支持 Pascal，用于接管生成 SQL、生成测试数据 SQL、自定义命令等事件。

EZDML 也支持通过命令行运行脚本：只传脚本文件名时会加载并执行该脚本；传入模型文件和脚本文件两个参数时，会先打开模型再执行脚本。无界面批处理脚本常在完成后调用 `AbortOut()` 退出当前执行流程。

