openapi: 3.1.0
info:
title: vjmap HTTP API
version: "1.0.0"
summary: vjmap web服务 + 图形服务 HTTP 接口
description: |
本规范覆盖 `vjmap` 二次开发最常用的 ~40 个接口,按照 13 大分类组织。
- **Base URL**:`http://127.0.0.1:27660`
- **API 前缀**:`/api/v1`
- **鉴权**:JWT Token,通过请求头 `token:`(优先)或查询参数 `?token=` 传递;REST 不认 `Authorization: Bearer`(仅 MCP 路由认)
- **响应约定**:
- web服务类接口:统一 `{"code":0,"msg":"ok","data":...}`
- 图形服务直通接口(`/api/v1/map/cmd/...`): JSON
- 字节流接口(瓦片 / PBF / PNG):直接返回二进制
> 本规范随新后端文档项目一起分发,Swagger 页面可在线 "Try it out"。
contact:
name: vjmap dev
license:
name: Proprietary
servers:
- url: http://127.0.0.1:27660
description: 本地调试服务
- url: http://127.0.0.1:27660/api/v1
description: API 前缀路径(部分集成场景)
security:
- TokenQuery: []
- TokenHeader: []
tags:
- name: Map Management
description: 地图上传 / 打开 / 关闭 / 删除 / 元数据
- name: Tiles & Styles
description: 栅格 / 矢量瓦片、WMS、样式管理
- name: Query
description: 要素查询、坐标变换
- name: Analysis
description: 图形差分 / 对比 / 表格抽取 等高级分析
- name: Compose & Export
description: 组合拆分地图、导出 PDF / DXF / 离线包
- name: WebCAD
description: 在线 CAD 编辑(可选功能)
- name: Workspace
description: 工作区(命名空间)管理
- name: Data Storage
description: 键值数据存储
- name: Full-text Search
description: CAD 文字全文索引(Bleve)
- name: Symbols
description: 符号库(只读)
- name: System
description: 心跳 / 版本 / 运行状态 / 日志
- name: Misc Services
description: 二维码 / 字体 glyphs / 图片上传
- name: AI
description: 向量检索 / FAQ / 知识库文档
components:
securitySchemes:
TokenQuery:
type: apiKey
in: query
name: token
TokenHeader:
type: apiKey
in: header
name: token
parameters:
MapIdPath:
name: mapid
in: path
required: true
schema: { type: string }
description: 地图 ID
VersionPath:
name: version
in: path
required: true
schema: { type: string, default: v1 }
description: 版本号,默认 v1
schemas:
GatewayError:
description: web服务标准错误包
type: object
properties:
code: { type: integer, example: 7 }
msg: { type: string, example: "Token is invalid" }
data: { type: object, example: { reload: true } }
ServiceOk:
description: /service/* 系列的标准 OK 包
type: object
properties:
status: { type: string, example: "ok" }
data: { }
CmdBoolResult:
description: "/cmd/* 命令返回的 { status: true|false, ... } 结构"
type: object
properties:
status: { type: boolean }
additionalProperties: true
# ---------- Map ----------
UploadResponse:
type: object
description: |
上传结果。同内容文件已被某图使用时 mapid 为该图并带 version/geom;
图片带 maptype;失败时为 {uploadname, error}。
properties:
fileid: { type: string, example: "caf27de8a225", description: "c/t + 内容 md5 前 11 位" }
mapid: { type: string, example: "caf27de8a225" }
uploadname: { type: string, example: "my.dwg", description: 回显上传原文件名 }
version: { type: string, example: "v1" }
geom: { type: boolean }
maptype: { type: string, example: "image" }
error: { type: string }
OpenMapRequest:
type: object
required: [mapid]
description: |
打开地图请求体。
- `mapid` 必填,需与 URL path 中的 `{mapid}` 保持一致。
- `fileid` 选填:首次打开新上传的图时必填(取自 `POST /api/v1/map/uploads`
的返回值);已存在的图可省略。
- 打开方式只看布尔 `geom`(后端缺省 false = Memory);后端不读 `mapopenway`
(客户端枚举,官方 SDK 换算为 `geom = mapopenway !== 'Memory'`)。
- GeomRender 首次打开异步:返回 `{mapid,version,status:"working",error}`,轮询
`cmd/listmaps/{mapid}/{version}` 到 status=finish 后再打开一次。
properties:
mapid: { type: string, example: "demo_123", description: "地图 ID(与 URL path 中的 {mapid} 保持一致)" }
version: { type: string, example: "v1", description: "POST 时只读 body(query 里的 version 不读)" }
fileid: { type: string, example: "caf27de8a225", description: "上传接口返回的 fileid" }
uploadname: { type: string, example: "caf27de8a225.dwg", description: "上传接口返回的 uploadname,选填" }
geom: { type: boolean, default: false, description: "true=GeomRender(几何渲染),false=Memory(内存打开;从未以 true 打开过的图 cmd 走内存进程,不支持 condition 查询)" }
style: { type: object }
secretKey: { type: string, description: "v1 首次打开且 ≥10 位时设为该图密钥(原样存);之后用于校验。同名请求头会覆盖它" }
accessKey: { type: string, description: "该图 accessKey(仅浏览)或实例 map_super_key" }
mapbounds: { type: string, example: "[0,0,100,100]" }
layers: { type: array, items: { type: string } }
example:
mapid: "demo_123"
fileid: "caf27de8a225"
uploadname: "caf27de8a225.dwg"
geom: true
OpenMapResponse:
type: object
additionalProperties: true
properties:
mapid: { type: string }
version: { type: string }
fileid: { type: string }
status: { type: string, description: "GeomRender 首次打开为 working;完成后为 finish" }
geom: { type: string, enum: ["true", "false"], description: 实际打开方式(字符串) }
layer: { type: string, example: "s6d04d896e", description: "当前样式图层名 = 瓦片 URL 的 {layer} 段" }
bounds: { type: string, description: "'[x1,y1,x2,y2]'" }
layers: { type: string, description: "图层数组的 JSON 字符串" }
styles: { type: string, description: "样式数组的 JSON 字符串" }
defaultlayer: { type: string }
error: { type: string }
MapVersionInfo:
type: object
properties:
version: { type: string, example: "v1" }
status: { type: string, example: "finish", description: "working / finish / error / runerror" }
geom: { type: boolean }
db: { type: string }
filename: { type: string }
uploadname: { type: string }
mtime: { type: string, example: "2026-04-10 12:00:00" }
errmsg: { type: string }
ListMapsResponse:
description: |
不带分页参数:{mapid: [MapVersionInfo]}(顶层键是动态 mapid)。
带 curPage/pageCount(均 >0):分页信封 {count, curPage, pageCount, mapIds:[本页 mapid],
mapInfos:{mapid:[MapVersionInfo]}, allMapIds:[实例全部 mapid,不做前缀隐藏]}。
oneOf:
- type: object
additionalProperties:
type: array
items: { $ref: "#/components/schemas/MapVersionInfo" }
- type: object
properties:
count: { type: integer }
curPage: { type: integer }
pageCount: { type: integer }
mapIds: { type: array, items: { type: string } }
mapInfos:
type: object
additionalProperties:
type: array
items: { $ref: "#/components/schemas/MapVersionInfo" }
allMapIds: { type: array, items: { type: string } }
MapMetadata:
description: metadata 返回的 JSON(图形服务 原样返回,可能含字符串 JSON 字段)
type: object
additionalProperties: true
# ---------- Query ----------
QueryFeaturesRequest:
type: object
required: [querytype]
properties:
querytype: { type: string, enum: [point, rect, condition, expresion] }
x: { type: number }
y: { type: number }
pixelsize: { type: number }
x1: { type: number }
y1: { type: number }
x2: { type: number }
y2: { type: number }
expr: { type: string }
condition: { type: string }
bounds:
type: string
description: >-
condition 查询的空间范围,必须是字符串:"x1,y1,x2,y2" / "[x1,y1,x2,y2]",
或 "x,y;x,y;..."(折线,首尾相同为多边形)。传 JSON 数组会被转成空串、过滤静默失效。
zoom: { type: integer, default: 1 }
limit: { type: integer }
fields: { type: string }
geom:
type: boolean
description: >-
命令路由开关(不是返回几何的开关):缺省按图打开方式;false 强制内存进程,
condition 会返回 "not support query type!"。
layername: { type: string }
QueryFeaturesResponse:
type: object
properties:
result:
oneOf:
- type: array
items: { type: object }
- type: object
properties:
features:
type: array
items: { type: object }
total: { type: integer }
CoordTransformRequest:
type: object
required: [srs, crs, points]
properties:
srs: { type: string, example: "EPSG:4326", description: 源坐标系 }
crs: { type: string, example: "EPSG:3857", description: 目标坐标系 }
points: { type: string, example: "116.39,39.9;121.47,31.23", description: '多点串 "x,y;x,y"' }
fourParameter: { type: string, example: "0,0,1,0", description: "xOff,yOff,scale,rotRad" }
isInverseFourParamter: { type: boolean, description: 反向应用四参数(后端拼写 Paramter) }
# ---------- Data storage ----------
KvSaveRequest:
type: object
properties:
value: { type: string }
prop: { type: string }
KvMultipleEntry:
type: object
required: [key]
properties:
key: { type: string }
value: { type: string }
prop: { type: string }
ttl: { type: string, description: 秒数(字符串) }
# ---------- Full-text search ----------
FullSearchDocument:
type: object
description: 全文搜索文档
required: [id]
properties:
id: { type: string, description: 全库唯一,必填 }
map_ver: { type: string, example: "sys_zp_v1" }
content: { type: string, description: 被索引的文本 }
type: { type: integer, description: "1 单行文字 / 2 多行 / 3 属性注记 / 4 块属性注记 / 5 图层 / 6 块名 / 7 线型 / 8 填充 / 9 自定义" }
min_x: { type: number }
min_y: { type: number }
max_x: { type: number }
max_y: { type: number }
props: { type: object, description: 任意附加属性(原样 JSON) }
create_time: { type: string, format: date-time }
workspace: { type: string, description: '默认工作区要显式写 "_"' }
data: { type: string }
FullSearchQuery:
type: object
description: 全文搜索请求(POST 走 JSON,GET 走同名 query)
properties:
query: { type: string }
map_ver: { type: string, description: 多个逗号分隔;纯 mapid 取最新版本 }
type: { type: string, example: "1-3,6" }
workspace: { type: string, description: '多个逗号分隔;缺省 "_","*" 查全部' }
limit: { type: integer, default: 10 }
offset: { type: integer, default: 0 }
fields: { type: string }
facet: { type: boolean }
bounding_box: { type: string, example: "[0,0,1000,1000]" }
time_range: { type: string, example: "2023-01-01~2023-12-31" }
# ---------- AI ----------
VectorSearchRequest:
type: object
required: [query]
properties:
query: { type: string }
numDocuments: { type: integer, default: 20 }
collection: { type: string, default: "vj" }
where: { type: string }
whereDocument: { type: string }
searchDescription: { type: string }
disableSplitSentence: { type: boolean, default: false }
disableSearchKnowledge: { type: boolean, default: false }
documents:
type: array
items:
type: object
properties:
content: { type: string }
metadata: { type: object }
paths:
# ==========================================================
# 1. Map Management
# ==========================================================
/api/v1/map/uploads:
post:
tags: [Map Management]
summary: 上传 DWG(multipart)
description: |
服务端只取第一个文件部分,表单字段(md5、secretKey 等)一律不读;
文件按内容 md5 命名。加密只能在首次 openmap 时设。
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required: [file]
properties:
file: { type: string, format: binary }
md5: { type: string, description: 后端不读(官方 SDK 会带上,无害) }
responses:
"200":
description: OK
content:
application/json:
schema: { $ref: "#/components/schemas/UploadResponse" }
examples:
sample:
value:
fileid: "caf27de8a225"
mapid: "caf27de8a225"
uploadname: "my.dwg"
/api/v1/map/openmap/{mapid}:
post:
tags: [Map Management]
summary: 打开地图
description: |
打开一张地图。请求体中只有 `mapid` 必填(且需与 URL path 中的 `{mapid}` 一致)。
`fileid` / `uploadname` 选填:
- 首次打开刚上传的新图:建议带上 `fileid`(取自 `POST /api/v1/map/uploads` 的返回)。
- 已经存在的图:可只传 `mapid`,服务端会按 mapid 自行定位文件。
parameters:
- $ref: "#/components/parameters/MapIdPath"
- name: version
in: query
schema: { type: string, default: v1 }
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/OpenMapRequest" }
examples:
new_upload:
summary: 首次打开新上传的图(带 fileid,GeomRender)
value:
mapid: "demo_123"
fileid: "caf27de8a225"
uploadname: "caf27de8a225.dwg"
geom: true
existing:
summary: 打开已存在的图(仅 mapid,GeomRender)
value:
mapid: "demo_123"
geom: true
memory:
summary: 内存模式(Memory,geom 为 false 或缺省)
value:
mapid: "demo_123"
geom: false
responses:
"200":
description: OK
content:
application/json:
schema: { $ref: "#/components/schemas/OpenMapResponse" }
/api/v1/map/cmd/closemap/{mapid}/{version}:
get:
tags: [Map Management]
summary: 关闭地图(SDK 走 GET,图形服务 POST 空体会 500)
parameters:
- $ref: "#/components/parameters/MapIdPath"
- $ref: "#/components/parameters/VersionPath"
responses:
"200":
description: OK
content:
application/json:
schema: { $ref: "#/components/schemas/CmdBoolResult" }
/api/v1/map/cmd/deletemap/{mapid}/{version}:
get:
tags: [Map Management]
summary: 删除地图
parameters:
- $ref: "#/components/parameters/MapIdPath"
- $ref: "#/components/parameters/VersionPath"
- name: deleteDwgFile
in: query
description: true=强制删除源文件;缺省时是否删除取决于服务端 noAutoDeleteDwgFile 配置。注意 openapi/旧文档的 keepSource 参数后端没有消费点。
schema: { type: boolean, default: false }
responses:
"200":
description: OK
content:
application/json:
schema: { $ref: "#/components/schemas/CmdBoolResult" }
/api/v1/map/cmd/listmaps/_/v1:
get:
tags: [Map Management]
summary: 列出地图
description: |
非 root 默认隐藏 `ns_` 前缀(config map_list_exclude_prefix),root 隐藏 `ns_temp_`;`temp_` 不隐藏。
`mapIds` 过滤须 POST JSON body `{"mapIds":[...]}`。
parameters:
- name: curPage
in: query
description: 页码(1 起,与 pageCount 同时 >0 才分页并改回分页信封)。旧文档的 keyword/page/pageSize 无消费点
schema: { type: integer }
- name: pageCount
in: query
schema: { type: integer }
responses:
"200":
description: OK
content:
application/json:
schema: { $ref: "#/components/schemas/ListMapsResponse" }
/api/v1/map/cmd/metadata/{mapid}/{version}:
get:
tags: [Map Management]
summary: 获取地图元数据
parameters:
- $ref: "#/components/parameters/MapIdPath"
- $ref: "#/components/parameters/VersionPath"
# 本接口在源码中不读业务参数;官方文档记载的 enableEditMeta/fileid 均无消费点
responses:
"200":
description: OK
content:
application/json:
schema: { $ref: "#/components/schemas/MapMetadata" }
# ==========================================================
# 2. Tiles & Styles
# ==========================================================
/api/v1/map/tile/{mapid}/{version}/{layer}/{z}/{x}/{y}:
get:
tags: [Tiles & Styles]
summary: 栅格瓦片
parameters:
- $ref: "#/components/parameters/MapIdPath"
- $ref: "#/components/parameters/VersionPath"
- { name: layer, in: path, required: true, schema: { type: string } }
- { name: z, in: path, required: true, schema: { type: integer } }
- { name: x, in: path, required: true, schema: { type: integer } }
- { name: y, in: path, required: true, schema: { type: integer } }
- name: tag
in: query
schema: { type: string, description: fileid,用来让 CDN 缓存失效 }
responses:
"200":
description: PNG 瓦片字节流
content:
image/png:
schema: { type: string, format: binary }
/api/v1/map/tile/{mapid}/{version}/{layer}/{z}/{x}/{y}.mvt:
get:
tags: [Tiles & Styles]
summary: 矢量瓦片
parameters:
- $ref: "#/components/parameters/MapIdPath"
- $ref: "#/components/parameters/VersionPath"
- { name: layer, in: path, required: true, schema: { type: string, default: main } }
- { name: z, in: path, required: true, schema: { type: integer } }
- { name: x, in: path, required: true, schema: { type: integer } }
- { name: y, in: path, required: true, schema: { type: integer } }
responses:
"200":
description: MVT 二进制
content:
application/vnd.vjmap-vector-tile:
schema: { type: string, format: binary }
/api/v1/map/cmd/wms/{mapid}/{version}:
get:
tags: [Tiles & Styles]
summary: WMS 单张出图
parameters:
- $ref: "#/components/parameters/MapIdPath"
- $ref: "#/components/parameters/VersionPath"
- name: bbox
in: query
required: true
schema: { type: string, example: "{bbox-epsg-3857}" }
- name: srs
in: query
schema: { type: string, default: "EPSG:3857" }
- name: width
in: query
schema: { type: integer, default: 256 }
- name: height
in: query
schema: { type: integer, default: 256 }
- name: layers
in: query
description: 样式名(注意是复数 layers,非 layer)
schema: { type: string }
- name: crs
in: query
description: 坐标系别名(与 srs 等价,后端两者都读)
schema: { type: string }
- name: transparent
in: query
description: 默认 true;为 false 时可用 backgroundColor 指定底色
schema: { type: string, default: "true" }
- name: backgroundColor
in: query
description: '"r,g,b" 或 "r,g,b,a" 字符串,仅 transparent=false 生效'
schema: { type: string }
- name: fourParameter
in: query
schema: { type: string }
- name: useImageRotate
in: query
schema: { type: boolean }
responses:
"200":
description: PNG
content:
image/png:
schema: { type: string, format: binary }
/api/v1/service/wms:
get:
tags: [Tiles & Styles]
summary: WMS 多图叠加
description: >-
mapid/version/layers/crs/fourParameter 均为 "_," 分隔的等长数组,
长度不一致返回 paramter error。不支持 .mvt。
parameters:
- { name: mapid, in: query, required: true, schema: { type: string, example: "a_,b_,c" } }
- { name: version, in: query, required: true, schema: { type: string, example: "v1_,v1_,v1" } }
- { name: layers, in: query, required: true, schema: { type: string, example: "_,_," } }
- { name: crs, in: query, required: true, schema: { type: string, example: "_,_," } }
- { name: fourParameter, in: query, required: true, schema: { type: string, example: "_,_," } }
- { name: bbox, in: query, required: true, schema: { type: string, example: "{bbox-epsg-3857}" } }
- { name: srs, in: query, schema: { type: string, default: "EPSG:3857" } }
- { name: width, in: query, schema: { type: integer, default: 256 } }
- { name: height, in: query, schema: { type: integer, default: 256 } }
- name: transparent
in: query
description: Go 端会转发到底层单图 wms;backgroundColor 则不转发(仅单图 cmd/wms 有效)
schema: { type: string, default: "true" }
responses:
"200":
description: PNG
content:
image/png:
schema: { type: string, format: binary }
/api/v1/map/cmd/thumbnail/{mapid}/{version}:
get:
tags: [Tiles & Styles]
summary: 缩略图
parameters:
- $ref: "#/components/parameters/MapIdPath"
- $ref: "#/components/parameters/VersionPath"
- { name: width, in: query, schema: { type: integer, default: 200 } }
- { name: height, in: query, schema: { type: integer, default: 200 } }
- { name: darkTheme, in: query, schema: { type: boolean }, description: 暗色主题(仅这三个参数有消费点) }
responses:
"200":
description: PNG
content:
image/png:
schema: { type: string, format: binary }
/api/v1/map/cmd/createMapStyle/{mapid}/{version}:
post:
tags: [Tiles & Styles]
summary: 创建自定义样式
parameters:
- $ref: "#/components/parameters/MapIdPath"
- $ref: "#/components/parameters/VersionPath"
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
stylename: { type: string, description: 样式名(后端读 stylename,不读 name);缺省为系统样式 }
geom: { type: boolean, description: "true 几何样式(s 前缀),false 栅格样式(m 前缀)" }
layeron: { type: string }
layeroff: { type: string }
backcolor: { type: string }
clipbounds: { type: string }
expression: { type: string }
lineweight: { type: string }
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
properties:
stylename: { type: string, example: "sfbd35705c" }
# ==========================================================
# 3. Query
# ==========================================================
/api/v1/map/cmd/queryFeatures/{mapid}/{version}:
post:
tags: [Query]
summary: 要素查询(点 / 矩形 / 条件 / 表达式)
parameters:
- $ref: "#/components/parameters/MapIdPath"
- $ref: "#/components/parameters/VersionPath"
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/QueryFeaturesRequest" }
examples:
rect:
summary: 按矩形查 10 条
value:
querytype: rect
x1: 587227463.27
y1: 3103509765.63
x2: 588006538.39
y2: 3104288840.75
limit: 10
fields: "name,objectid,layername"
responses:
"200":
description: OK
content:
application/json:
schema: { $ref: "#/components/schemas/QueryFeaturesResponse" }
/api/v1/map/cmd/coordtransform/_/_:
post:
tags: [Query]
summary: 坐标变换
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/CoordTransformRequest" }
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
properties:
points:
type: array
description: 与入参 points 顺序一一对应的 [x, y]
items: { type: array, items: { type: number } }
examples:
sample:
value:
points: [[12957588.73, 4851421.18]]
# ==========================================================
# 4. Analysis (pass-through 风格)
# ==========================================================
/api/v1/map/cmd/mapDiff/_null/v1:
post:
tags: [Analysis]
summary: 两张图差异分析
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
mapid1: { type: string }
version1: { type: string }
mapid2: { type: string }
version2: { type: string }
responses:
"200":
description: OK
content:
application/json:
schema: { $ref: "#/components/schemas/CmdBoolResult" }
/api/v1/map/cmd/extractTable/_null/v1:
post:
tags: [Analysis]
summary: 抽取 CAD 中的表格
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
mapid: { type: string }
version: { type: string }
responses:
"200":
description: OK
content:
application/json:
schema: { $ref: "#/components/schemas/CmdBoolResult" }
# ==========================================================
# 5. Compose & Export
# ==========================================================
/api/v1/map/cmd/exportPdf/{mapid}/{version}:
post:
tags: [Compose & Export]
summary: 导出 PDF
description: |
ODA PDF 导出选项,不支持 bounds/width/height/scale/outName。
cmd 路由对空 JSON body 的 POST 回 500 param error——无参数时用 GET。
parameters:
- $ref: "#/components/parameters/MapIdPath"
- $ref: "#/components/parameters/VersionPath"
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
pageWidth: { type: number, description: 纸张宽(mm),与 pageHeight 同时给才生效 }
pageHeight: { type: number, description: 纸张高(mm) }
pageLeftMargin: { type: number, default: 0 }
pageRightMargin: { type: number, default: 0 }
pageTopMargin: { type: number, default: 0 }
pageBottomMargin: { type: number, default: 0 }
bZoomToExtents: { type: boolean, default: true }
bActiveLayout: { type: boolean, default: true }
geomDPI: { type: integer, default: 600 }
colorImagesDPI: { type: integer, default: 400 }
bwImagesDPI: { type: integer, default: 400 }
isBlackWhiteMode: { type: boolean, default: false }
isGrayMode: { type: boolean, default: false }
bEmbededTTF: { type: boolean, default: false }
title: { type: string, default: "PDF File" }
author: { type: string, default: "vjmap.com" }
pdfPath: { type: string, description: 缺省写入 data/download、按参数 hash 命名 }
additionalProperties: true
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
properties:
path: { type: string, example: "download/7733d6c688.pdf" }
status: { type: boolean }
/api/v1/map/cmd/exportDxf/{mapid}/{version}:
post:
tags: [Compose & Export]
summary: 导出 DXF
description: |
整库导出,不支持裁剪/选层。
cmd 路由对空 JSON body 的 POST 回 500 param error——无参数时用 GET。
parameters:
- $ref: "#/components/parameters/MapIdPath"
- $ref: "#/components/parameters/VersionPath"
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
filename: { type: string, description: 输出名(自动补 .dxf);缺省 <源文件名>_.dxf }
cadVersion: { type: string, example: "2018", description: "2000/2004/2007/2010/2013/2018;* = 沿用源图版本" }
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
properties:
status: { type: boolean }
fileid: { type: string, example: "c177098c15d1_.dxf", description: 写入 mapfiles 目录的文件名 }
error: { type: string }
# ==========================================================
# 7. Workspace
# ==========================================================
/api/v1/service/getWorkspace:
get:
tags: [Workspace]
summary: 列出所有工作区
responses:
"200": { description: OK }
/api/v1/service/workspaceCreate:
post:
tags: [Workspace]
summary: 新建工作区
description: '默认 casbin 策略仅 root 可调(admin/guest 被 /api/v1/service/workspace* 拒,403 权限不足)。'
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [name]
properties:
name: { type: string }
alias: { type: string }
isPublic: { type: boolean }
workDir: { type: string }
disableFullSearch: { type: boolean }
# WsData 请求结构无 idleCloseTime/description/token/createUser
responses:
"200": { description: OK }
/api/v1/service/workspaceModify:
post:
tags: [Workspace]
summary: 修改工作区
description: |
服务端按 name 定位,只更新 alias/isPublic/disableFullSearch,
未给的这三项被重置为零值;workDir/idleCloseTime/createTime 传了也不改。仅 root 可调。
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [name]
properties:
# ModifyWorkSpace 绑定完整 MapWorkspace,但只更新 alias/isPublic/disableFullSearch
name: { type: string }
alias: { type: string }
isPublic: { type: boolean }
disableFullSearch: { type: boolean }
workDir: { type: string, description: 不会被修改 }
idleCloseTime: { type: integer, description: 不会被修改 }
responses:
"200": { description: OK }
/api/v1/service/workspaceDelete/{name}:
delete:
tags: [Workspace]
summary: 删除工作区
description: '不可逆——停进程、删全文索引并 os.RemoveAll 整个工作目录(全部图/瓦片)。仅 root 可调。'
parameters:
- name: name
in: path
required: true
schema: { type: string }
responses:
"200": { description: OK }
/api/v1/service/workspaceStatus:
get:
tags: [Workspace]
summary: 全部工作区状态
description: '返回所有命名工作区的 WsDataStatus 数组(未起进程的 ProcIsNull: true);一个都没有时为 null。仅 root 可调。'
responses:
"200": { description: OK }
# ==========================================================
# 8. Data Storage (KV)
# ==========================================================
/api/v1/service/data/{key}:
get:
tags: [Data Storage]
summary: 读单/多键
parameters:
- name: key
in: path
required: true
schema: { type: string, description: 多键用 `;;` 连接 }
- name: retDataType
in: query
schema: { type: string, enum: [value, prop, valueprop] }
responses:
"200":
description: OK
content:
application/json:
schema: { $ref: "#/components/schemas/ServiceOk" }
post:
tags: [Data Storage]
summary: 写单键
parameters:
- name: key
in: path
required: true
schema: { type: string }
- name: ttl
in: query
schema: { type: integer }
description: |
只用 JSON body(ShouldBindJSON)。raw body 分支不可用:body 已被 JSON 解码器读走,
小 body 存成 ""、大 body 被截断;value/prop 非字符串同样静默存成 ""。二进制请 base64 后放 value。
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/KvSaveRequest" }
responses:
"200": { description: OK }
delete:
tags: [Data Storage]
summary: 删除键
parameters:
- name: key
in: path
required: true
schema: { type: string }
- name: isPrefix
in: query
schema: { type: boolean }
responses:
"200": { description: OK }
/api/v1/service/datas:
post:
tags: [Data Storage]
summary: 批量写键
description: '四个字段都必须是字符串(含 ttl);绑定失败返回 HTTP 403 {code:7, msg:"json: cannot unmarshal ..."},不是权限问题。'
requestBody:
required: true
content:
application/json:
schema:
type: array
items: { $ref: "#/components/schemas/KvMultipleEntry" }
responses:
"200": { description: OK }
/api/v1/service/datakeys:
get:
tags: [Data Storage]
summary: 按前缀列出键
description: |
SQL `key like 'data_<prefix>%'`:`_`/`%` 为通配符、ASCII 不分大小写、`'` 会破坏 SQL。
parameters:
- name: prefix
in: query
schema: { type: string }
- name: retDataType
in: query
schema: { type: string, enum: [value, prop, valueprop] }
- name: isSys
in: query
description: 'true 时 prefix 不补 data_,返回整行对象 {keys:[{Key,Value,Prop,Ttl}]}'
schema: { type: string, enum: ["true"] }
responses:
"200": { description: OK }
# ==========================================================
# 9. Full-text Search
# ==========================================================
/api/v1/service/fullsearch/search:
get:
tags: [Full-text Search]
summary: 全文检索(GET,参数走 query,字段同 FullSearchQuery)
parameters:
- name: query
in: query
schema: { type: string }
- name: limit
in: query
schema: { type: integer, default: 10 }
- name: offset
in: query
schema: { type: integer, default: 0 }
- name: map_ver
in: query
schema: { type: string }
- name: type
in: query
schema: { type: string }
- name: workspace
in: query
schema: { type: string }
- name: fields
in: query
schema: { type: string }
- name: bounding_box
in: query
schema: { type: string }
- name: time_range
in: query
schema: { type: string }
responses:
"200": { description: OK }
post:
tags: [Full-text Search]
summary: 全文检索(POST,参数走 JSON)
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/FullSearchQuery" }
responses:
"200": { description: OK }
/api/v1/service/fullsearch/add:
post:
tags: [Full-text Search]
summary: 索引单条文档
description: 'body 必须包一层 `{document: {...}}`;document.id 不能为空。'
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [document]
properties:
document: { $ref: "#/components/schemas/FullSearchDocument" }
responses:
"200": { description: OK }
/api/v1/service/fullsearch/delete:
delete:
tags: [Full-text Search]
summary: 删除文档
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [id]
properties:
id: { type: string }
responses:
"200": { description: OK }
# ==========================================================
# 10. Symbols
# ==========================================================
/api/v1/service/symbol/categories:
get:
tags: [Symbols]
summary: 符号分类
responses:
"200":
description: OK
content:
application/json:
examples:
sample:
value:
status: ok
data:
- id: default
name: 默认分类
createTime: "2026-04-10 11:29:15"
/api/v1/service/symbol/list/{categoryId}:
get:
tags: [Symbols]
summary: 符号列表(可分类+分页)
parameters:
- name: categoryId
in: path
required: true
schema: { type: string }
- name: page
in: query
schema: { type: integer, default: 1 }
- name: pageSize
in: query
schema: { type: integer, default: 20 }
responses:
"200": { description: OK }
/api/v1/service/symbol/{id}:
get:
tags: [Symbols]
summary: 获取单个符号
parameters:
- name: id
in: path
required: true
schema: { type: string }
responses:
"200": { description: OK }
"404": { description: 符号不存在 }
# ==========================================================
# 11. System
# ==========================================================
/heart:
get:
tags: [System]
summary: 心跳(顶层路径,不走 /api/v1 前缀)
security: []
responses:
"200":
description: OK
content:
application/json:
examples:
sample: { value: { status: ok } }
/version:
get:
tags: [System]
summary: 版本信息(顶层路径)
security: []
responses:
"200": { description: OK }
/api/v1/map/cmd/runstatus/_/v1:
get:
tags: [System]
summary: 运行状态(图形服务命令)
parameters:
- name: detail
in: query
schema: { type: boolean, default: true }
responses:
"200": { description: OK }
/api/v1/map/cmd/viewlogs/_/v1:
get:
tags: [System]
summary: 查看日志(图形服务命令)
parameters:
- name: time
in: query
description: 最近 N 分钟的日志
schema: { type: integer, default: 60 }
- name: record
in: query
schema: { type: integer, default: 100 }
responses:
"200":
description: OK
content:
text/plain:
schema: { type: string }
# ==========================================================
# 12. Misc Services
# ==========================================================
/api/v1/service/qrcode:
get:
tags: [Misc Services]
summary: 生成二维码 PNG
parameters:
- name: content
in: query
required: true
schema: { type: string }
- name: size
in: query
schema: { type: integer, default: 256 }
responses:
"200":
description: PNG
content:
image/png:
schema: { type: string, format: binary }
/api/v1/service/fonts/{fontstack}/{range}.pbf:
get:
tags: [Misc Services]
summary: 字体 glyphs
parameters:
- name: fontstack
in: path
required: true
schema: { type: string, example: "Open Sans Regular" }
- name: range
in: path
required: true
schema: { type: string, example: "0-255" }
responses:
"200":
description: PBF
content:
application/x-protobuf:
schema: { type: string, format: binary }
/api/v1/service/uploadImg:
post:
tags: [Misc Services]
summary: 上传图片(JWT token + 固定 Basic Authorization)
description: |
路由在全局 JWT/casbin 之后注册,普通 token 照常需要;处理函数另外要求
`Authorization: Basic X3ZqbWFwQF8=`,并通过 `Uri` 头告知服务端存储目录。
响应 `{code:0, path: Uri+文件名, url: ImgHost 头+文件名}`。
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required: [upload]
properties:
# 注意:字段名是 upload(后端 c.FormFile("upload")),不是 file
upload: { type: string, format: binary }
watermark: { type: boolean }
responses:
"200": { description: OK }
# ==========================================================
# 13. AI
# ==========================================================
/api/v1/service/vectorSearch:
post:
tags: [AI]
summary: 相似性检索
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/VectorSearchRequest" }
responses:
"200": { description: OK }
"500":
description: embedding 模型未配置
content:
application/json:
examples:
missingModel:
value:
code: 8
data: {}
msg: "bge-large-zh-v1.5-f16.gguf is not exist"
/api/v1/service/chatFaq:
get:
tags: [AI]
summary: FAQ 知识库
responses:
"200": { description: OK }
/api/v1/service/vectorDocs:
get:
tags: [AI]
summary: 向量库文档元数据
responses:
"200": { description: OK }