> **本文回答**：完整的 CAD 实体类型 `name='xx'` 列表、后台数据库表结构、所有 SQL 字段含义对照、各类查询接口（条件 / 点 / 矩形 / 多边形 / 分页）的用法、查询结果的字段与绘制姿势。
>
> 本文是后台数据查询的"**主参考**"。简化速查见 [query-sql](query-sql.md)；表达式查询（内存模式）见 [query-expression](query-expression.md)；综合用例见 [query-cases](query-cases.md)；全文搜索见 [query-fulltext](query-fulltext.md)；服务端高亮 / 过滤见 [svr-style-var](svr-style-var.md)。

## 一、查询的前置条件

- **几何渲染方式打开**（GeomRender）：后台走几何渲染查询命令。能用 `rectQueryFeature` / `pointQueryFeature`（空间查询）。

  ```js
  await svc.openMap({ mapid, mapopenway: vjmap.MapOpenWay.GeomRender });
  ```

  > ✅ **公共云 sys_zp、GeomRender 下**：`conditionQueryFeature` 在 GeomRender 下可用——`condition:"objectid>0"` + `limit:3` 返回 3 条（recordCount=6992），空条件返回全部。字段条件、limit、beginpos 分页都生效。
  >
  > 注意区分：`conditionQueryFeature`（SQL 条件）是**几何渲染专属**——内存模式进程收到 `querytype:"condition"` 直接返回 `{error:"not support query type!"}`；`exprQueryFeature`（表达式查询）在 GeomRender / Memory 下都可用（GeomRender 下能跑但不走空间库，较慢）。

- **内存模式打开**（Memory）：只能用 [query-expression](query-expression.md) 的 `exprQueryFeature` 与 `pointQueryFeature`/`rectQueryFeature`（点查询恒返回 1 条，几何只给外包矩形），**不能**用 `conditionQueryFeature`。

- **`limit`/`beginpos` 分页**：GeomRender 生效——rect 全图 + `limit:3` 返回 3 条（不传 limit 默认上限 100），condition + `limit`/`beginpos` 正常翻页。**0 命中时没有 `result` 键**：条件查询返回 `{recordCount:0}`，点/矩形查询返回 `{}`——统一 `res.result ?? []` 兜底。

- 任何查询 SDK 调用都返回 `{ error?, recordCount, result: [...] }`，业务上**必须**先判 `error`。

## 二、后台数据库表结构

把图以"几何渲染"方式打开后，每个实体在后台都是一行记录。SQL 条件**只写 `where` 之后的部分**（不要写 `select * from xxx where`）。

| 字段名 | 类型 | 说明 |
|---|---|---|
| `id` | integer | 自增 ID |
| `objectid` | text | 实体唯一 ID（图重新加载后稳定）。命名规则见下文 |
| `layerindex` | integer | 图层索引 |
| `name` | text | **实体类型值**（**字符串**，如 `'1'` = AcDbLine）。所有取值见第三节 |
| `color` | int | 颜色（RGB+Alpha 编码，常见为负数，见第二节末） |
| `data` | blob | 几何数据（二进制，前端不直接用） |
| `s1` | text | 线型 |
| `s2` | text | 扩展字典数据 |
| `s3` | text | 字符型属性 3（**含义随实体类型变**，见第四节） |
| `s4` | text | 字符型属性 4（**含义随实体类型变**） |
| `s5` | text | 字符型属性 5（**含义随实体类型变**） |
| `n1` | float | 颜色索引 |
| `n2` | float | 线型比例 |
| `n3` | float | 线宽 |
| `n4` | float | 透明度 |
| `n5` | float | 数值型属性 5（**含义随实体类型变**） |
| `n6` | float | 数值型属性 6（**含义随实体类型变**） |
| `n7` | float | 数值型属性 7（**含义随实体类型变**） |
| `n8` | float | 数值型属性 8（**含义随实体类型变**） |
| `n9` | float | 数值型属性 9（**含义随实体类型变**） |
| `n10` | float | 数值型属性 10（**含义随实体类型变**） |
| `geom` | GEOMETRY | 实体外包矩形（用于空间查询，墨卡托坐标） |

### `objectid` 命名规则（重要）

- **普通实体**：`{实体句柄}`，如 `1A`；同一实体拆成多行时追加 `_{序号}`（如 `9EA9_0`、`1A_1`…）
- **块内实体**：`{块参照id链}_{实体id}_{标记}`，如 `9BE_5C_3F_#`。id 链按"最外层块参照 → 直接所属块"排列；尾部标记区分来源：`_` = 一般组合实体、`_@` = 表格内、`_#` = 块参照内（无标注块）、`_$` = 标注或含标注块的块内
- **组（group）**：`{实体id}${组id}`，如 `5C$2A`（实体在前，组在后）
- **表格（table）**：`{块参照id链}_{实体id}_@`，如 `1A_5C_@`

> 用 `objectid like 'EA_%'` 可查到最外层块参照 id 为 `EA` 的所有子实体。

### `color` 编码

- 颜色由 RGB + Alpha 组合：`color = 0xAABBGGRR`（低字节是 R）
- 例：黑色不透明 = `0xFF000000`，按有符号 32 位读取就是 `-16777216`
- 例：红色不透明 = `0xFF0000FF`（红在低位），即 `-16776961`
- 实际查询时用整数：`name='13' and color=-16776961`（红色单行文字）

> 前端拿到后转 HTML 颜色：`vjmap.entColorToHtmlColor(color)`。

## 三、所有实体类型 `name='xx'` 完整列表

> ⚠️ `name` 是**字符串**，SQL 里要写 `name='1'` 而不是 `name=1`。

| `name` | 类名 | 中文 | 备注 |
|:---:|:---|:---|:---|
| `'1'`  | AcDbLine | 直线 | |
| `'2'`  | AcDbPolyline | 多段线（LWPolyline） | |
| `'3'`  | AcDb2dPolyline | 二维折线 | |
| `'4'`  | AcDb3dPolyline | 三维多段线 | |
| `'5'`  | AcDbSpline | 样条曲线 | |
| `'6'`  | AcDbArc | 圆弧 | |
| `'7'`  | AcDbCircle | 圆 | |
| `'8'`  | AcDbEllipse | 椭圆 | |
| `'9'`  | AcDbCurve | 曲线 | |
| `'10'` | AcDbBlockReference | 块参照 | 子实体的 `objectid` 以块 ID 开头 |
| `'11'` | AcDbHatch | 填充 | |
| `'12'` | AcDbMText | 多行文本 | |
| `'13'` | AcDbText | 单行文本 | |
| `'14'` | AcDbShape | 型实体 | |
| `'15'` | AcDbRasterImage | 栅格图片 | |
| `'16'` | AcDbWipeout | 遮罩实体 | |
| `'17'` | AcDb2LineAngularDimension | 角度标注（两条线） | |
| `'18'` | AcDb3PointAngularDimension | 角度标注（三点） | |
| `'19'` | AcDbAlignedDimension | 对齐标注 | |
| `'20'` | AcDbArcDimension | 圆弧标注 | |
| `'21'` | AcDbDiametricDimension | 直径标注 | |
| `'22'` | AcDbOrdinateDimension | 坐标标注 | |
| `'23'` | AcDbRadialDimension | 半径标注 | |
| `'24'` | AcDbRadialDimensionLarge | 半径折线标注 | |
| `'25'` | AcDbRotatedDimension | 转角标注 | |
| `'26'` | AcDbAttributeDefinition | 属性注记 | 文本类 |
| `'27'` | AcDbAttribute | 块属性 | 文本类，块内 |
| `'28'` | AcDbTable | 表格 | |
| `'29'` | AcDbMLeader | 引线标注 | |
| `'30'` | AcDbRegion | 面域 | |
| `'31'` | AcDbPolyFaceMesh | 多面网格实体 | |
| `'32'` | AcDbPolygonMesh | 多边形网格 | |
| `'33'` | AcDbSurface | 曲面 | |
| `'34'` | AcDb3dSolid | 三维实体 | |
| `'35'` | AcDbFace | 三维面 | |
| `'36'` | AcDbSolid | 实线实体 | |

### 常用分组（写 SQL 时常合并查询）

```sql
-- 所有"线段"类（直线、二三维多段线）
name='1' or name='2' or name='3' or name='4'

-- 所有"曲线"类（圆弧、圆、椭圆、样条、曲线）
name='5' or name='6' or name='7' or name='8' or name='9'

-- 所有"文字"类（单行 / 多行 / 属性注记 / 块属性）
name='12' or name='13' or name='26' or name='27'

-- 所有"标注"类
name='17' or name='18' or name='19' or name='20' or name='21'
or name='22' or name='23' or name='24' or name='25' or name='29'

-- 所有"网格 / 面 / 体"类
name='30' or name='31' or name='32' or name='33' or name='34' or name='35'
```

### 不要硬编码 ID（推荐做法）

后台返回的 `name` ID 在不同版本可能调整。**生产代码里**用映射表：

```js
const { entTypeIdMap } = await svc.getConstData();
// entTypeIdMap 形如 { '1': 'AcDbLine', '2': 'AcDbPolyline', ... }

const getTypeIdByName = name =>
  Object.keys(entTypeIdMap).find(k => entTypeIdMap[k] === name);

const lineId = getTypeIdByName('AcDbLine');
const cond = `name='${lineId}'`;
```

## 四、字段含义随类型变化（s3/s4/s5/n5~n10）

下表显示**各实体类型**对应字段的实际含义。空白处表示该类型不使用该字段。

| 类型 | 类名 | 中文 | s3 | s4 | s5 | n5 | n6 | n7 | n8 | n9 | n10 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| `'1'` | AcDbLine | 直线 | points | | | thickness | length | | | | |
| `'2'` | AcDbPolyline | 多段线 | points | bulge | data3d | area | isclosed | lineTypeScale | thickness | elevation | |
| `'3'` | AcDb2dPolyline | 二维折线 | points | | | area | isclosed | polyType | thickness | elevation | |
| `'4'` | AcDb3dPolyline | 三维多段线 | points | | | area | isclosed | polyType | | | |
| `'5'` | AcDbSpline | 样条曲线 | points | | | area | isclosed | isFit | fitTol | degree | |
| `'6'` | AcDbArc | 圆弧 | center | points | | area | isclosed | radius | startAngle | endAngle | thickness |
| `'7'` | AcDbCircle | 圆 | center | | | area | isclosed | radius | thickness | | |
| `'8'` | AcDbEllipse | 椭圆 | center | majorAxis | points | area | isclosed | radiusRatio | startAngle | endAngle | majorRadius |
| `'9'` | AcDbCurve | 曲线 | | | | area | isclosed | | | | |
| `'10'` | AcDbBlockReference | 块参照 | positon | attributeDef | blockname | rotate | scaleX | scaleY | scaleZ | | |
| `'11'` | AcDbHatch | 填充 | points | patternName | | elevation | patternAngle | patternScale | | | |
| `'12'` | AcDbMText | 多行文本 | location | contents | text | height | width | rotate | textHeight | actualHeight | actualWidth |
| `'13'` | AcDbText | 单行文本 | location | text | textStyle | height | rotate | horzMode | | | |
| `'14'` | AcDbShape | 型实体 | positon | normal | | rotate | size | | | | |
| `'15'` | AcDbRasterImage | 栅格图片 | origin | sourceFileName | | | | | | | |
| `'16'` | AcDbWipeout | 遮罩实体 | origin | sourceFileName | | | | | | | |
| `'26'` | AcDbAttributeDefinition | 属性注记 | location | text | contents | height | rotate | horzMode | | | |
| `'27'` | AcDbAttribute | 块属性 | location | text | contents | height | rotate | horzMode | | | |
| `'28'` | AcDbTable | 表格 | positon | attributeDef | contents | rotate | scaleX | scaleY | scaleZ | | |
| `'29'` | AcDbMLeader | 引线标注 | location | contents | text | height | width | rotate | textHeight | actualHeight | actualWidth |
| `'30'` | AcDbRegion | 面域 | points | indices | data3d | area | perimeter | | | | |
| `'31'` | AcDbPolyFaceMesh | 多面网格 | points | indices | data3d | | | | | | |
| `'32'` | AcDbPolygonMesh | 多边形网格 | points | indices | data3d | | | | | | |
| `'33'` | AcDbSurface | 曲面 | points | indices | data3d | | | | | | |
| `'34'` | AcDb3dSolid | 三维实体 | points | indices | data3d | | | | | | |
| `'35'` | AcDbFace | 三维面 | points | indices | data3d | | | | | | |
| `'36'` | AcDbSolid | 实线实体 | points | | | thickness | length | isclosed | | | |

> 标注类（`'17'~'25'`）共用同一套专属字段：`s3=location`（标注点）、`s4=text`（标注文字）、`n5=rotate`、`n6=measure`（测量值）。
> 椭圆还有 `minorRadius`（次半径）字段定义，但已超出 `n10` 列上限，查询结果中不出现。

### 字段含义速查（按字段名）

| 字段 | 类型 | 说明 |
|---|---|---|
| `points` | text | 坐标序列（`x,y;x,y;...`） |
| `center` | text | 圆 / 圆弧 / 椭圆中心点 |
| `location` | text | 文字插入点 |
| `positon` | text | 块 / 表格 / 型实体定位点（注：服务端拼写就是 `positon`） |
| `origin` | text | 栅格图片基点 |
| `area` | float | 面积 |
| `length` | float | 长度（直线 / 实体） |
| `radius` | float | 半径 |
| `startAngle` / `endAngle` | float | 圆弧 / 椭圆起止角 |
| `thickness` | float | 厚度 |
| `elevation` | float | 高度 |
| `isclosed` | float | 是否闭合（0/1） |
| `polyType` | float | 多段线类型 |
| `bulge` | text | 多段线凸度 |
| `text` | text | 文本内容（短） |
| `contents` | text | 多行文字（带样式） |
| `height` | float | 文字高（标注高） |
| `width` | float | 文字宽 |
| `rotate` | float | 旋转角度 |
| `textHeight` / `actualHeight` / `actualWidth` | float | 多行文字几何尺寸 |
| `horzMode` | float | 水平对齐模式 |
| `blockname` | text | 块名 |
| `attributeDef` | text | 块属性定义 |
| `scaleX` / `scaleY` / `scaleZ` | float | 块缩放 |
| `patternName` | text | 填充图案名 |
| `patternAngle` / `patternScale` | float | 填充角度 / 比例 |
| `majorAxis` | text | 椭圆长轴 |
| `normal` | text | 法向量 |
| `size` | float | 大小 |
| `isFit` / `fitTol` / `degree` | float | 样条拟合参数 |
| `indices` | text | 网格 / 面索引序列 |
| `data3d` | text | 3D 实体材质 / 顶点扩展 |
| `perimeter` | float | 面域周长 |
| `sourceFileName` | text | 栅格图片 / 遮罩的源文件名 |
| `textStyle` | text | 单行文本的文字样式名 |
| `radiusRatio` | float | 椭圆半径比（次轴/主轴） |
| `majorRadius` | float | 椭圆主轴半径（`minorRadius` 超出 n10 不上库） |
| `measure` | float | 标注测量值 |
| `lineTypeScale` | float | 多段线线型比例（注意大写 T；通用字段 n2 是 `linetypeScale` 小写 t，两者不同名） |

> **真实查询时不必死记字段对应**。常见做法：先查少量数据 `console.log` 一次，把字段名记下来再写正式代码。

## 五、SQL 条件示例（按场景分类）

### 5.1 按类型查

```sql
-- 所有直线
name='1'

-- 所有圆
name='7'

-- 所有圆弧 + 圆 + 椭圆
name='6' or name='7' or name='8'

-- 所有文字
name='12' or name='13' or name='26' or name='27'

-- 所有块参照
name='10'
```

### 5.2 类型 + 图层

```sql
-- 0 号图层的三维多段线
name='4' and layerindex=0

-- 0 / 1 / 3 号图层的所有圆
name='7' and (layerindex=0 or layerindex=1 or layerindex=3)
```

### 5.3 类型 + 颜色

```sql
-- 红色单行文字（0xFF0000FF -> -16776961）
name='13' and color=-16776961

-- 蓝色直线（0xFFFF0000 -> -65536）
name='1' and color=-65536

-- 不是黑色的所有文字
(name='12' or name='13') and color != -16777216
```

### 5.4 类型 + 几何属性

```sql
-- 长度为 10 的直线（n6 = length）
name='1' and n6=10

-- 长度大于 100 的直线
name='1' and n6 > 100

-- 半径为 5 的圆（n7 = radius）
name='7' and n7=5

-- 半径在 [10, 20] 之间的圆
name='7' and n7 >= 10 and n7 <= 20

-- 闭合的多段线（n6 = isclosed）
name='2' and n6=1

-- 面积 > 1000 的面域（n5 = area）
name='30' and n5 > 1000
```

### 5.5 类型 + 文字内容

```sql
-- 文字以 "DZ" 开头（s4 = text 字段）
name='13' and s4 like 'DZ%'

-- 文字长度 [2, 12] 且以 J 或 DZ 开头
(name='12' or name='13' or name='26' or name='27')
  and LENGTH(s4) >= 2 and LENGTH(s4) <= 12
  and (s4 like 'J%' or s4 like 'DZ%')

-- 多行文字内容包含"水泵"
name='12' and s4 like '%水泵%'
```

### 5.6 按 objectid 查

```sql
-- 指定 objectid（普通实体就是句柄；块内实体带 id 链和尾部标记）
objectid='1A'
objectid='9BE_5C_3F_#'

-- 块 EA / 10D / 19A 下所有子实体
objectid like 'EA_%' or objectid like '10D_%' or objectid like '19A_%'

-- 某个块的子实体
objectid like '9BE_%'
```

### 5.7 按块名查（块参照）

```sql
-- 块名为 "门" 的所有块参照（s5 = blockname）
name='10' and s5='门'

-- 块名以 "Door" 开头
name='10' and s5 like 'Door%'
```

### 5.8 按填充图案查

```sql
-- 填充图案为 ANSI31
name='11' and s4='ANSI31'
```

## 六、查询接口

### 6.1 条件查询 `conditionQueryFeature`

> ✅ 仅 GeomRender 可用（`objectid>0` 条件 + limit/beginpos 分页正常，见本文 §一）。返回 `{error:"not support query type!"}` 表示请求被路由到了内存进程（图是 Memory 方式打开，或请求里 `geom` 为 false）——显式传 `geom: true`，并确认该图已以 GeomRender 方式打开过。

```ts
svc.conditionQueryFeature(param: IConditionQueryFeatures, cb?): Promise<any>;

interface IConditionQueryFeatures extends IQueryBaseFeatures {
  /** SQL where 条件，必填 */
  condition: string;
  /** 矩形范围（[x1,y1,x2,y2]）或多边形点数组（[[x,y],...]）—— CAD 坐标 */
  bounds?: [number, number, number, number] | [number, number][];
  /** bounds 为点数组时，是否求交点；默认 false */
  isGetIntersections?: boolean;
  /** 起始记录位置（分页用）*/
  beginpos?: number;
  /** 是否包含几何信息（默认仅在 recordCount==1 时返回真实 geojson）*/
  includegeom?: boolean;
  /** 是否每条都返回真实几何 geojson（数据量大时慎用）*/
  realgeom?: boolean;
  /** 范围查询时：true=包含 / false=相交（默认）*/
  isContains?: boolean;
}
```

最小用法：

```js
const q = await svc.conditionQueryFeature({
  condition: `name='13' or name='12' or name='26' or name='27'`,
  fields: "objectid,text,location,envelop",
  geom: true,
  limit: 100000  // 默认 100，要全量必须放大
});
if (q.error) { console.error(q.error); return; }
console.log(q.recordCount, q.result);
```

带空间过滤：

```js
// 矩形 + 类型
await svc.conditionQueryFeature({
  condition: `name='7'`,
  bounds: [100, 200, 500, 800],
  isContains: false,   // false=相交（默认）；true=必须完全在矩形内
  limit: 100000
});

// 多边形 + 类型
await svc.conditionQueryFeature({
  condition: `name='10'`,
  bounds: [[0,0],[100,0],[100,100],[0,100]],
  isContains: true
});
```

### 6.2 点查询 `pointQueryFeature`

```ts
svc.pointQueryFeature(param: IPointQueryFeatures, cb?): Promise<any>;

interface IPointQueryFeatures extends IQueryBaseFeatures {
  /** 查询点 X（CAD 坐标）*/
  x: number;
  /** 查询点 Y */
  y: number;
  /** 像素容差（屏幕几像素内都算命中）*/
  pixelsize?: number;
  /** 进一步用 SQL 过滤 */
  condition?: string;
  /** 单实体最大返回字节数（防 OOM）*/
  maxGeomBytesSize?: number;
  /** 一像素表示的几何长度（不传则按 zoom 算）*/
  pixelToGeoLength?: number;
}
```

典型场景——**鼠标点击选实体**：

```js
map.on("click", async (e) => {
  const cad = map.fromLngLat(e.lngLat);
  const q = await svc.pointQueryFeature({
    x: cad.x, y: cad.y,
    pixelsize: 5,
    zoom: map.getZoom(),
    limit: 20,
    geom: true,
    toMapCoordinate: true
  });
  console.log(q.result);
});
```

### 6.3 矩形查询 `rectQueryFeature`

```ts
svc.rectQueryFeature(param: IRectQueryFeatures, cb?): Promise<any>;

interface IRectQueryFeatures extends IQueryBaseFeatures {
  /** 矩形左下点 X（不传则查整图）*/
  x1?: number;
  y1?: number;
  /** 矩形右上点 X */
  x2?: number;
  y2?: number;
  /** 进一步用 SQL 过滤 */
  condition?: string;
  /** 单实体最大几何字节 */
  maxGeomBytesSize?: number;
}
```

```js
await svc.rectQueryFeature({
  x1: 0, y1: 0, x2: 1000, y2: 1000,
  condition: `name='7'`,
  limit: 100000,
  geom: true
});
```

> 矩形查询也可改用 `conditionQueryFeature({ bounds: [x1,y1,x2,y2] })`，效果相同。

### 6.4 多边形查询

vjmap **没有独立的多边形查询接口**，使用 `conditionQueryFeature` + `bounds` 数组：

```js
await svc.conditionQueryFeature({
  condition: `name='10'`,
  bounds: [[100,100],[500,100],[500,500],[100,500]],   // 多边形顶点
  isContains: true     // true=完全在多边形内；false=相交
});
```

### 6.5 分页查询（数据量大时必须）

`limit` 不能无限大，超过后台限制会被截断。万级以上结果集分页：

```js
async function queryAll(condition, fields = "") {
  const all = [];
  let begin = 0;
  while (true) {
    const q = await svc.conditionQueryFeature({
      condition, fields,
      beginpos: begin,
      limit: 10000   // 每次 1 万
    });
    if (q.error) throw new Error(q.error);
    all.push(...(q.result || []));
    begin += q.result.length;
    if (all.length >= q.recordCount) break;
  }
  return all;
}

const lines = await queryAll(
  `name='1' or name='2' or name='3' or name='4'`,
  "objectid,points,envelop"
);
```

## 七、统一查询参数 `IQueryBaseFeatures`

所有查询接口都继承下面这组通用参数：

```ts
interface IQueryBaseFeatures {
  /** 当前缩放级别（影响 pixel→几何转换、几何简化精度）*/
  zoom?: number;
  /** 地图 ID（不传则用当前已 open 的图）*/
  mapid?: string;
  /** 地图版本 */
  version?: string;
  /** 图层名 */
  layer?: string;
  /** 最大返回条数。条件/矩形默认 100，要全量必须自己设大；点查询默认只返回 1 条（Memory 下恒为 1） */
  limit?: number;
  /** 字段过滤，逗号分隔。如 "objectid,text,envelop"。空字符串 "" 表示返回所有字段。
      既可写属性名（objectid/text/area），也可写原始列名 s1..s5 / n1..n10（结果里以列名为键）*/
  fields?: string;
  /** 是否走几何渲染空间库查询（不是"是否返回几何"）；不传时 SDK 取当前已打开图的打开方式。要几何用 includegeom/realgeom */
  geom?: boolean;
  /** GeoJSON 简化容差（墨卡托单位），减少传输量。0=不简化 */
  simplifyTolerance?: boolean;
  /** 启用查询缓存（仅内存模式） */
  useCache?: boolean;
  /** true=直接返回 CAD 坐标；false=返回墨卡托坐标（默认）*/
  toMapCoordinate?: boolean;
}
```

### 字段过滤建议

不写 `fields` 会返回所有字段，移动端 / 弱网下流量大。建议明确列出：

```js
// 只要 ID 和外包矩形
fields: "objectid,envelop"

// 文本类查询
fields: "objectid,text,location,height,rotate"

// 圆查询
fields: "objectid,center,radius,area"
```

## 八、查询返回结果字段

`q.result[i]` 中可能出现的字段（取决于 `fields` 与实体类型）：

| 字段 | 类型 | 说明 |
|---|---|---|
| `objectid` | text | 实体唯一 ID（可作为 key） |
| `name` | text | 实体类型 ID（同上文） |
| `layerindex` | int | 图层索引 |
| `color` | int | 颜色（用 `vjmap.entColorToHtmlColor()` 转 HTML——**要求 0xAABBGGRR 打包 32 位整数**；小整数如 `7` 的 hex 不足 8 位会得到畸形 `"#"`，见文末坑位） |
| `linetype` | text | 线型 |
| `linetypeScale` | float | 线型比例 |
| `lineWidth` | float | 线宽 |
| `alpha` | float | 透明度 |
| `xdata` | any | 扩展数据 |
| `bounds` | text | 外包矩形（**CAD 坐标**，`[minx,miny,maxx,maxy]` 字符串） |
| `envelop` | text | 外包矩形（**墨卡托 WKT**，`map.getEnvelopBounds()` 解析） |
| `geojson` | text | 真实几何 **GeoJSON 字符串**（默认**原始墨卡托**坐标；`toMapCoordinate:true` 时为 **CAD 坐标**；条件查询仅 `includegeom:true` 时才有值——不加 `realgeom` 时多条结果给的是外包矩形多边形；指定 `fields` 时须把 `geojson` 列进去） |
| `geom` | object | SDK `_processQueryResult` 转换后的几何（**渲染经纬度**，可直接进 source；`isMapCoordinate` 或 `geojson` 为空时不生成）——坐标空间细节见 [coord/query-coords](../coord/query-coords.md) |
| `isEnvelop` | bool | 查询时是否仅给外包盒 |
| `points` | text | 坐标序列 `x,y;x,y;...` |
| `indices` | text | 索引序列（网格 / 面） |
| `center` | text | 圆心 |
| `radius` | float | 半径 |
| `startAngle` / `endAngle` | float | 弧度 |
| `area` / `length` / `perimeter` | float | 几何度量 |
| `isclosed` | bool | 是否闭合 |
| `text` / `contents` | text | 文本 |
| `height` / `width` / `textHeight` / `actualHeight` / `actualWidth` | float | 文字几何 |
| `rotate` / `scaleX` / `scaleY` / `scaleZ` | float | 块 / 表格变换 |
| `blockname` | text | 块名 |
| `location` / `positon` / `origin` | text | 位置点 |
| `normal` | text | 法向量 |
| `thickness` / `elevation` | float | 厚度 / 高程 |
| `bulge` | text | 多段线凸度 |
| `polyType` | float | 多段线类型 |
| `data3d` | text | 3D 材质 / 数据 |
| `majorAxis` | text | 椭圆长轴 |
| `u` / `v` | float | UV 坐标 |
| `size` | float | 大小 |
| `isFit` / `fitTol` / `degree` | float | 样条参数 |
| `horzMode` | float | 水平对齐 |

## 九、绘制查询结果到地图

### 9.1 用外包矩形画 Polygon（最快，适合大量结果高亮）

```js
const polygons = q.result.map(r => ({
  points: map.toLngLat(map.getEnvelopBounds(r.envelop).toPointArray()),
  properties: {
    id: r.objectid,
    color: vjmap.entColorToHtmlColor(r.color),
    text: r.text
  }
}));

const layer = new vjmap.Polygon({
  data: polygons,
  fillColor: ['case', ['to-boolean', ['feature-state', 'hover']], 'yellow', '#f0f'],
  fillOpacity: ['case', ['to-boolean', ['feature-state', 'hover']], 0.6, 0.4],
  fillOutlineColor: ['get', 'color'],
  isHoverPointer: true,
  isHoverFeatureState: true
});
layer.addTo(map);
layer.hoverFeatureState(e => {
  if (e.features) {
    map.logInfo(`选中 ${e.features[0].properties.id}: ${e.features[0].properties.text}`);
  }
});
```

> `map.logInfo(text, type?)`：向 `document.body` 末尾追加 `#vjmapinfolog` 容器、内部每条消息是一个 `span.vjmapinfolog-{type}`（type 如 `success`）——**不是**挂在地图容器内的 DOM，自动化断言或截图取景时别在 map 容器里找它。同类 `logWarn`/`logError` **不存在**，只有 `logInfo` 一个入口。

### 9.2 用真实几何画 GeoJSON 线 / 面

```js
// 查询时加 includegeom:true + realgeom:true：SDK 已把每条几何转成渲染经纬度写到 r.geom
// ⚠️ 不要直接 JSON.parse(r.geojson) 进 source——那是原始墨卡托坐标，会全部出界
const fc = {
  type: "FeatureCollection",
  features: (q.result ?? []).filter(r => r.geom).map(r => ({
    type: "Feature",
    geometry: r.geom.geometries[0],
    properties: { id: r.objectid }
  }))
};
map.addSource("q", { type: "geojson", data: fc });
map.addLayer({
  id: "q-line",
  type: "line",
  source: "q",
  paint: { "line-color": "#ff0", "line-width": 2 }
});
```

### 9.3 中心点 Marker

```js
for (const r of q.result) {
  const center = map.getEnvelopBounds(r.envelop).center();
  new vjmap.Marker()
    .setLngLat(map.toLngLat(center))
    .setPopup(new vjmap.Popup().setHTML(r.text || r.objectid))
    .addTo(map);
}
```

### 9.4 批量定位 fitBounds

```js
const all = new vjmap.GeoBounds();
for (const r of q.result) all.updateByBounds(map.getEnvelopBounds(r.envelop));
map.fitMapBounds(all, { padding: 80 });
```

### 9.5 闪烁定位（AI MCP 常用）

```js
async function flashBounds(boundsArray) {
  const pts = vjmap.GeoBounds.fromArray(boundsArray).toPointArray();
  pts.push(pts[0]);
  const layer = new vjmap.Polyline({
    data: [{ points: map.toLngLat(pts), properties: { opacity: 1 } }],
    lineColor: "yellow",
    lineWidth: 3,
    lineOpacity: ["get", "opacity"]
  });
  layer.addTo(map);

  await new Promise(resolve => vjmap.createAnimation({
    from: 1, to: 10, duration: 1000,
    onUpdate: v => {
      const data = layer.getData();
      data.features[0].properties.opacity = parseInt(v) % 2;
      layer.setData(data);
    },
    onComplete: () => { layer.remove(); resolve(); }
  }));
}
```

## 十、典型完整示例

### 10.1 查所有文字并高亮

```js
const { entTypeIdMap } = await svc.getConstData();
const idOf = name => Object.keys(entTypeIdMap).find(k => entTypeIdMap[k] === name);

const cond = ['AcDbText','AcDbMText','AcDbAttributeDefinition','AcDbAttribute']
  .map(n => `name='${idOf(n)}'`).join(' or ');

const q = await svc.conditionQueryFeature({
  condition: cond,
  fields: "objectid,text,envelop,color",
  geom: true,
  limit: 100000
});

if (q.error) return message.error(q.error);

const polygons = q.result.map(r => ({
  points: map.toLngLat(map.getEnvelopBounds(r.envelop).toPointArray()),
  properties: {
    id: r.objectid,
    color: vjmap.entColorToHtmlColor(r.color),
    text: r.text
  }
}));
new vjmap.Polygon({
  data: polygons,
  fillColor: '#f0f', fillOpacity: 0.4,
  fillOutlineColor: ['get', 'color']
}).addTo(map);
```

### 10.2 查指定块下的所有子实体（取面积最大的）

```js
const blockObjectId = '9BE';

const sub = await svc.conditionQueryFeature({
  condition: `objectid like '${blockObjectId}_%'`,
  fields: "objectid,name,n5",   // n5 对多段线 / 圆 / 面域 = area
  limit: 100000
});

const max = sub.result.reduce((a, b) => (a?.n5 || 0) > (b?.n5 || 0) ? a : b);
console.log("最大子实体:", max);
```

### 10.3 查鼠标点击附近的圆并高亮半径

```js
map.on("click", async e => {
  const cad = map.fromLngLat(e.lngLat);
  const q = await svc.pointQueryFeature({
    x: cad.x, y: cad.y,
    pixelsize: 5,
    condition: `name='7'`,        // 限定只查圆
    fields: "objectid,center,radius",
    zoom: map.getZoom(),
    toMapCoordinate: true,
    limit: 5
  });
  q.result.forEach(c => console.log(`圆 ${c.objectid}: 半径 ${c.radius}`));
});
```

### 10.4 分页查所有横竖直线

```js
const queryEntTypes = ['AcDbLine','AcDbPolyline','AcDb2dPolyline','AcDb3dPolyline'];
const cond = queryEntTypes.map(t => `name='${idOf(t)}'`).join(' or ');

const result = [];
let begin = 0;
while (true) {
  const q = await svc.conditionQueryFeature({
    condition: cond,
    fields: "objectid,points,envelop",
    beginpos: begin,
    limit: 100000
  });
  if (q.error) break;
  result.push(...(q.result || []));
  begin += q.result.length;
  if (result.length >= q.recordCount) break;
}

// 过滤纯横竖
const hvLines = result.filter(e => {
  const pts = e.points.split(";");
  if (pts.length !== 2) return false;
  const [a, b] = pts.map(p => vjmap.geoPoint(p.split(",")));
  return vjmap.isZero(a.x - b.x) || vjmap.isZero(a.y - b.y);
});
```

## 十一、性能建议

1. **`fields` 越少越快**。大数据查询禁用 `*`，只列必要字段。
2. **不要用 `geom: false` 省流量**——它会把查询路由到内存进程（条件查询直接报 `not support query type!`）；省流量靠精简 `fields`、不传 `includegeom`。
3. **大结果集必须分页**（`limit` + `beginpos`），避免一次性请求百万记录。
4. **`realgeom: true` 仅在数量少（<= 几百）时用**；批量结果用 `envelop` 即可，足以做高亮 / 定位。
5. **绘制结果用 `Polygon` / `Polyline` 一次 `setData`**，不要循环 `addTo`。
6. **动态查询前 `await map.onLoad()`**，否则 `addLayer` 报错。
7. **能用 SQL 范围过滤就别全量后再过滤**：`bounds` 让后台空间索引发挥作用。
8. **`color` 字段用整数比较**，不要在 SQL 里转换 RGB 字符串。

## 十二、常见坑

1. **`name=1` 查不到结果** → `name` 是字符串字段，必须 `name='1'`。
2. **`color=0xFF0000FF` 写成正数没结果** → 后台保存的是 32 位有符号整数，红色用 `-16776961`。
3. **拿到 `envelop` 直接当 CAD 坐标** → 它是**墨卡托 WKT**，必须 `map.getEnvelopBounds(envelop)` 转 CAD。
4. **用 `name=10` 期望查到块的子实体** → `name='10'` 只是块**参照本身**；子实体是块定义里的实体，要用 `objectid like '块id_%'`。
5. **`limit` 没传** → 默认只返回 100 条（点查询只返回 1 条），业务上易误判"图里只有 100 条"。
6. **多图并存时忘指定 `mapid`** → 查到的是当前 open 的图。查非当前图时必须同时传 `mapid`、`geom: true`、`layer: await svc.getStyleLayerName(mapid)`——否则 SDK 沿用当前图的样式图层名，服务端找不到该样式静默返回 `{}`；或按当前图的打开方式填 `geom`，被路由到内存进程报 `not support query type!`。
7. **`isContains: true` 漏实体** → 完全包含很严格，稍微越界就不算。一般 `false`（相交）符合直觉。
8. **`fields: ""` 期望返回所有字段** → 是的，**空字符串**等价于全字段，但写 `null` 或不传也是同样效果。
9. **拼 SQL 时把用户输入直接拼接** → SQL 注入风险。SDK 没有内置防护，需要自己做白名单 / 转义。
10. **几何渲染图却用 `exprQueryFeature` 全表扫** → 性能差。能用 SQL 一定用 [query-sql](query-sql.md) 走空间库。
11. **多版本下没传 `version`** → 拿到的是当前版本；老版本数据要显式 `version: "v2"`。
12. **`objectid` 当成数字** → 它是**字符串**（如 `"1A"`、`"9BE_5C_3F_#"`、`"5C$2A"`），业务里始终当字符串处理。
13. **服务端字段拼写**：`positon`（不是 `position`）、`bulge`（多段线凸度）等，写 SQL 时容易拼错。
14. **`entColorToHtmlColor(小整数)` 得畸形 `"#"`**→ 实现把数字按 `(c>>>0).toString(16)` 后**定长 8 位切片**（`0xAABBGGRR` 打包布局）。后端 `color` 字段是打包好的 int32（如 `-65536`）→ 正常；自己传小整数（如 `7`）hex 不足 8 位、切片全空 → 返回 `"#"`。字符串颜色原样返回；`#757675` 有 darkMode 特判。
15. **`getEnvelopBounds` 的 WKT 解析很脆**→ 实现是 `replace("POLYGON((","")` 精确串匹配 + 只取前 4 个坐标点。带空格的 `POLYGON ((...))`、孔洞、多边形顶点 ≠4 都会解析错。仅信任 `conditionQueryFeature` 返回的 `envelop` 格式，别拿它解通用 WKT。

## 十三、相关文档

- [query-sql](query-sql.md)：SQL 查询接口快速速查（与本文互补）
- [query-expression](query-expression.md)：表达式查询（内存模式 / 复杂逻辑）
- [query-cases](query-cases.md)：综合查询用例（自动分图 / 提表 / 中心线）
- [query-fulltext](query-fulltext.md)：跨图全文搜索
- [svr-style-var](svr-style-var.md)：服务端条件高亮 / 过滤（不查询、直接出样式）
- [rest-interface](rest-interface.md)：REST 接口直接调用
- [common-map-methods](common-map-methods.md)：`svc.openMap` / `getConstData` 等基础
- 官网原文：[https://vjmap.com/guide/dataQuery.html](https://vjmap.com/guide/dataQuery.html) / [https://vjmap.com/guide/svrStyleVar.html](https://vjmap.com/guide/svrStyleVar.html)
