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_%'`:`_`/`%` 为通配符、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 }