Files
workspace/code/g3soft-libs/docs/content/api/data.md
T
2026-10-12 22:25:41 +08:00

299 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: 数据查询
description: describe / loaddata / page / loaddatabysql / nextid / nextcode
pageClass: g3-api
---
# 数据查询
六个只读接口。除了 `nextid`(纯取号,不碰数据库),其余都会落到**当前机构自己的数据库**上执行。
共用规则:
- **表名、视图名、列名都会先过标识符校验**(只允许 `[A-Za-z_][A-Za-z0-9_]*`,可带限定名如 `dbo.v_x`),不会做字符串拼接 —— 所以别指望能塞入非法标识符。
- `search_condition` 是**原样拼进 `WHERE` 的 SQL 条件片段**;拼好的整条 SQL 之后会过只读校验(禁分号、禁注释、禁写关键字),所以它只能是布尔表达式。
- `order_by` 由后端校验并加 `[]`:支持 `字段 [ASC|DESC]`,或 `CASE ... END` 表达式,多列用逗号分隔。
- 返回的行是普通对象,键是**库里的原始列名**。
## `POST` `/data/describe`
探测表或视图的列结构,用于动态列、字段同步。
<G3ApiParams>
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `table` | string | 是 | 表或视图名 |
</G3ApiParams>
<G3ApiPayload title="请求体">
```json
{
"table": "v_b_othercompany"
}
```
</G3ApiPayload>
<G3ApiPayload title="响应" :code="0">
```json
{
"code": 0,
"message": "操作成功",
"data": [
{ "name": "b_id", "type": "varchar", "nullable": false, "size": 32 },
{ "name": "b_name", "type": "nvarchar", "nullable": true, "size": 128 }
]
}
```
</G3ApiPayload>
`type` 是数据库原生类型名(`varchar` / `nvarchar` / `decimal` / `datetime2` / `rowversion` …)。表不存在或没有可识别字段时返回 `1000`。
## `POST` `/data/loaddata`
按视图 + 条件 + 排序 + 字段列表查询。
<G3ApiParams>
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `view_name` | string | 是 | 表或视图名 |
| `search_columns` | string[] | | 只取这些列;省略等价于 `*` |
| `search_condition` | string | | `WHERE` 片段 |
| `order_by` | string | | 排序,多列逗号分隔 |
</G3ApiParams>
<G3ApiPayload title="请求体">
```json
{
"view_name": "v_b_othercompany",
"search_columns": ["b_id", "b_name", "b_canuse"],
"search_condition": "b_canuse = 1",
"order_by": "b_id ASC, b_name DESC"
}
```
</G3ApiPayload>
<G3ApiPayload title="响应" :code="0">
```json
{
"code": 0,
"message": "操作成功",
"data": [{ "b_id": "C001", "b_name": "XX 公司", "b_canuse": 1 }]
}
```
</G3ApiPayload>
> **没有行数上限。** `loaddata` 会把命中的行全部返回;列表页请用 `/data/page`。它的典型用途是取一个小字典(下拉选项)或按主键取单行。
## `POST` `/data/page`
分页查询。
<G3ApiParams>
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `view_name` | string | 是 | 表或视图名 |
| `order_by` | string | 是 | 分页必须有序(SQL Server 的 `OFFSET / FETCH` 要求) |
| `search_columns` | string[] | | 只取这些列 |
| `search_condition` | string | | `WHERE` 片段 |
| `page_no` | number | | 默认 `1`,从 1 开始 |
| `page_size` | number | | 默认 `20` |
</G3ApiParams>
<G3ApiPayload title="请求体">
```json
{
"view_name": "v_b_othercompany",
"search_condition": "b_canuse = 1",
"order_by": "b_id ASC",
"page_no": 2,
"page_size": 20
}
```
</G3ApiPayload>
<G3ApiPayload title="响应" :code="0">
```json
{
"code": 0,
"message": "操作成功",
"data": {
"rows": [{ "b_id": "C021", "b_name": "XX 公司" }],
"row_count": 20,
"total": 137,
"page_no": 2,
"page_size": 20
}
}
```
</G3ApiPayload>
<G3ApiParams title="data 字段">
| 字段 | 说明 |
|---|---|
| `rows` | 当前页数据 |
| `row_count` | **当前页**的行数(等于 `rows.length`) |
| `total` | 命中总行数 |
| `page_no` / `page_size` | 回显请求里的分页参数 |
</G3ApiParams>
> `row_count` 不是总行数,**总行数是 `total`**。算总页数用 `total`,别用 `row_count`。
>
> `page_no` 或 `page_size` 小于 1、或不是整数,都会得到 `1000`(`page_no 必须是大于 0 的整数`)。
翻到最后一页之后(`page_no` 超出范围)`rows` 为空,但 `total` 仍然正确 —— 所以判断「没数据」和「翻过了头」要靠 `total`。
## `POST` `/data/loaddatabysql`
配置表达不出来的复杂只读查询走这里。
<G3ApiParams>
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `sql` | string | 是 | 必须以 `SELECT` 或 `WITH` 开头 |
</G3ApiParams>
<G3ApiPayload title="请求体">
```json
{
"sql": "SELECT TOP 10 b_id, b_name FROM v_b_othercompany ORDER BY b_id"
}
```
</G3ApiPayload>
<G3ApiPayload title="响应" :code="0">
```json
{
"code": 0,
"message": "操作成功",
"data": [{ "b_id": "C001", "b_name": "XX 公司" }]
}
```
</G3ApiPayload>
被拒的情况(都是 `1000`):不是 `SELECT` / `WITH` 开头、包含 `;`、包含注释(`--` 或 `/* */`)、出现 `insert` `update` `delete` `drop` `truncate` `alter` `exec` `grant` 等关键字。
> 判定前会先把**字符串字面量整体掩掉**,所以在 `WHERE b_name = 'insert'` 这类写法里,字面量里的关键字不会误判。反过来也说明:不能在字面量之外藏写操作。
## `POST` `/data/nextid`
取雪花 ID。
<G3ApiParams>
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `count` | number | | 默认 `1`;`<= 1` 时 `data` 是单个 id,否则是数组 |
</G3ApiParams>
请求体**可以整个省略** —— 不带 body 或传 `{}` 是等价的,`count` 都取默认的 `1`:
<G3ApiPayload title="请求体">
```json
{}
```
</G3ApiPayload>
<G3ApiPayload title="响应" :code="0">
```json
{
"code": 0,
"message": "操作成功",
"data": "1873456789012345678"
}
```
</G3ApiPayload>
`count: 3` 时:
<G3ApiPayload title="响应" :code="0">
```json
{
"code": 0,
"message": "操作成功",
"data": [
"1873456789012345678",
"1873456789012345679",
"1873456789012345680"
]
}
```
</G3ApiPayload>
> 返回的是**字符串**(见 [快速开始](/api/getting-started) 里的序列化约定),不要转成数字。
## `POST` `/data/nextcode`
按模块配置的自动编码规则取业务编码(规则来自 `s_autocode`:前缀、日期格式、序号位数、分隔符、重置周期等)。
<G3ApiParams>
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `moduleId` | string | 是 | 模块编码(注意是 camelCase 的 `moduleId`) |
| `count` | number | | 默认 `1`;`<= 1` 时返回单个字符串,否则返回数组 |
</G3ApiParams>
<G3ApiPayload title="请求体">
```json
{
"moduleId": "othercompany",
"count": 1
}
```
</G3ApiPayload>
<G3ApiPayload title="响应" :code="0">
```json
{
"code": 0,
"message": "操作成功",
"data": "HT20261012001"
}
```
</G3ApiPayload>
行为要点:
- **会占用号段** —— 服务端取号后立即把序号写回 `s_autocode`,所以连续调用得到的是不同编码。别拿它做「探测一下看看格式」的试调,试出来的号就废了。
- 生成时会**检查目标表里该编码是否已存在**,已被占用(比如人工插过一条)就自动往后顺延,所以不一定严格等于「当前序号 + 1」。
- 模块没有配置启用的编码规则、或没配保存表 → `1000`(`当前模块未配置启用的自动编码规则` / `模块未配置保存表,无法生成自动编号`)。
- 生成的编码超过目标字段长度 → `1000`(`自动编号长度超过目标字段长度`)。