Wujies 无界平台
平台功能(自研)能力开放

开放接口清单

本页收录全部 /open/** 端点:宿主提供的 4 个,加各应用自己开放出来的 46 个,共 50 个。

内容来自源码,逐条对着控制器里的 @RequestMapping / @GetMapping / @PostMapping 抄的, 不是从别处转述的:

来源文件
宿主(平台)wujies-platform/wujies-modules/wujies-system/.../controller/OpenWebsiteConfigController.java
宿主(平台)wujies-platform/wujies-modules/wujies-system/.../controller/OpenMessageController.java
hellowujies/wujies-plugins/wujies-hello/.../hello/open/HelloDemoOpenController.java
examwujies/wujies-plugins/wujies-exam/.../exam/open/OpenExamController.java
gallerywujies/wujies-plugins/wujies-gallery/.../gallery/open/ 下 3 个控制器
mallwujies/wujies-plugins/wujies-mall/.../mall/open/ 下 2 个控制器

通用约定

项说明
响应体统一 {code, msg, data},code=200 表示成功;分页端点直接返回分页结构(rows/total),没有信封
登录整段 /open/** 都免登录:控制器类上有 @SaIgnore,且 /open/** 在宿主 security.excludes 白名单里(双保险)
租户/open/** 在 open-api.tenant.path-patterns 默认值里,由宿主的 OpenApiTenantInterceptor 按请求头把租户设进上下文;不设租户会查不到数据
未安装端点只在该应用被装载时存在。没装的应用,它的 /open/<code>/** 就是 404 —— 不会留下"能路由、一调就报没装"的空壳
路径固定从宿主模块搬进插件的开放接口,路径一个字节都不变,C 端不用改调用地址
为什么插件能自己开放接口

插件侧只要写一个类前缀为 /open/<app>/** 的控制器、类上加 @SaIgnore 就行, 不需要注册路由清单、不需要改宿主一行代码。宿主的 AllUrlHandler 会同时收集 宿主与插件的 mapping,PluginRuntimeManager 在 load / unload 之后 refresh() —— 装了就进清单、卸了就出清单。完整机制见插件运行时。


平台(宿主)

站点配置

OpenWebsiteConfigController,类级 @SaIgnore。

路径方法说明是否匿名
/open/{code}/configGET读某个应用的站点配置。{code} = sys_config.config_category,如 mall / gallery。除 logo / favicon / name / nameEn / backgroundImage / description / copyright / icp 八个基础字段外,其余 <code>.* 配置去掉前缀后原样放进 settings 透传是

这是一个泛化端点:归档的 5 个子类(enterprise / exam / gallery / im / mall)逐字看下来只差一个 category 常量, 所以用一个模板覆盖,新应用接进来不用改这个类 —— 应用侧只提供 sys_config 行(config_category = 应用编码)即可。

公开公告

OpenMessageController,类级 @SaIgnore,前缀 /open/system/message。

路径方法说明是否匿名
/open/system/message/listGET公开公告分页是
/open/system/message/{messageId}GET公开公告详情是
/open/system/message/latestGET最新 N 条公开公告(首页滚动通知用)。limit 默认 3、上限 10,结果缓存 3 分钟是

hello(示例应用)

HelloDemoOpenController,类级 @SaIgnore,前缀 /open/hello。 范例应用刻意不加权限注解,好让沙箱里不带 token 也能验通。

路径方法说明是否匿名
/open/hello/greetGET公开打招呼,参数 name 可省。用来确认开放链路是
/open/hello/item/listGET公开读示例数据。与管理端 GET /hello/item/list 是两条路径、同一个 service是
/open/hello/config-via-pluginGET反面教材:演示"插件自己包一层读站点配置"。真实场景应直接调 /open/hello/config是

exam(考试)

OpenExamController,类级 @SaIgnore,前缀 /open/exam。考试实现就是这个插件的 bean,因此服务直接注入。

路径方法说明是否匿名
/open/exam/plan/listGET分页查询考试计划。不传状态时默认只出「已发布 + 已结束」是
/open/exam/plan/{planId}GET考试计划详情是
/open/exam/notice/listGET公开公告分页。走 SDK 的 PlatformMessageApi,宿主没提供该能力时返回空页而不是 500是
公告接口的响应结构换了键

它原先直接透出宿主 TableDataInfo(键是 rows / total),改走 SDK 契约后透出的是 PlatformMessagePage(键是 records / total)。调用方要按新键取值。


gallery(图床)

三个控制器都在 .../gallery/open/ 下,都是类级 @SaIgnore。

图片:/open/gallery/image

路径方法说明是否匿名
/open/gallery/image/guest/uploadPOST游客批量上传图片(multipart/form-data)。默认公开、不关联相册是
/open/gallery/image/listGET分页查询图片,只出「公开 + 启用」是
/open/gallery/image/listByCategory/{categoryId}GET按分类查图片是
/open/gallery/image/listByAlbum/{albumId}GET按相册查图片是
/open/gallery/image/listByTagsGET按标签查图片,tags 为逗号分隔的标签 ID是
/open/gallery/image/{imageId}GET图片详情。会异步增加浏览量并记一条访问日志;非公开或非启用返回失败是
/open/gallery/image/view/{imageId}POST增加浏览量(Redis 计数器 + 异步日志)是
/open/gallery/image/like/{imageId}POST增加点赞数是
/open/gallery/image/unlike/{imageId}POST取消点赞是
/open/gallery/image/download/{imageId}POST增加下载次数是
/open/gallery/image/hotGET热门图片(按浏览量),结果按查询条件缓存 3 分钟是
/open/gallery/image/latestGET最新图片(按创建时间)是
/open/gallery/image/recommendGET推荐图片(按点赞数)是
/open/gallery/image/searchGET关键词搜索图片,参数 keyword 必填是
/open/gallery/image/userGET某个用户的公开图片,参数 userId是
/open/gallery/image/followingGET当前登录用户所关注的人的图片。匿名调用不报错,返回 200 + 空列表见下方警告
/open/gallery/image/suggestionsGET搜索建议,参数 keyword 必填、limit 默认 10是
/open/gallery/image/hotTagsGET热门标签排行,limit 默认 10是
/open/gallery/image/guessTagsPOST猜你想搜。请求体 {limit, searchHistory}是
/open/gallery/image/statisticsGET图床统计信息是
/following 是"标着匿名、实际要登录"的一个例外

它的方法注释写「需要登录」(GalleryImageOpenController.listFollowingImages),而 类级 @SaIgnore(在 GalleryImageOpenController 类上,/open/gallery/image 的每个方法都被它覆盖) 让它绕过登录拦截;真正的约束在实现里 —— queryFollowingImages 要取 LoginHelper.getUserId()。

匿名调用得到的不是 401、也不抛异常:

  • LoginHelper.getUserId() → getExtra(USER_KEY) 吞掉 Sa-Token 抛的异常返回 null → Convert.toLong(null) = null;
  • 实现遇到 currentUserId == null 直接 return TableDataInfo.build(new Page<>()), 即 HTTP 200 + 空结果(rows: []、total: 0)。

所以这一行的实际语义是:谁都能调,但只有带登录态才有数据; 已登录但关注集为空(或宿主没提供 FollowRelationApi)拿到的也是同一个空结果, 两者在响应上无法区分。上面这一行不能按"匿名可用"来设计调用方,要按需要登录态处理。

⚠️ 代码里的 @SaIgnore 与实现不一致(注解声称匿名可用,实现却依赖登录态), 已记录待确认 —— 本页只记录事实,不改这个方法的行为(改注解或改逻辑属于产品行为决策)。

标签:/open/gallery/tag

GalleryImageTagOpenController。

路径方法说明是否匿名
/open/gallery/tag/listGET标签列表,只返回启用状态是
/open/gallery/tag/listByCategory/{categoryId}GET某分类下关联的标签是
/open/gallery/tag/{tagId}GET标签详情,只返回启用的;不存在或不可访问返回失败是
/open/gallery/tag/hotGET热门标签(按使用次数),limit 默认 20是

分类:/open/gallery/category

GalleryImageCategoryOpenController。

路径方法说明是否匿名
/open/gallery/category/treeGET分类树,只返回启用状态是
/open/gallery/category/listGET分类扁平列表,只返回启用状态是
/open/gallery/category/{categoryId}GET分类详情,只返回启用的是
/open/gallery/category/hotGET热门分类(按图片数量),limit 默认 10是

mall(商城)

两个控制器都在 .../mall/open/ 下,都是类级 @SaIgnore。 跨应用的东西照旧由宿主提供:租户上下文来自 OpenApiTenantInterceptor。

商品与商家:/open/mall

OpenMallProductController。查询条件一律强制「正常 + 在售 + 审核通过」。

路径方法说明是否匿名
/open/mall/category/listGET启用状态的商品分类列表是
/open/mall/brand/listGET启用状态的品牌列表是
/open/mall/merchant/listGET可用商家列表(启用 + 审核通过 + 营业中)是
/open/mall/product/listGET分页查询在售商品。可选 categoryId(含子分类)/ brandId / merchantId / productType / keywords / orderByColumn / isAsc是
/open/mall/product/{productId}GET商品详情,会异步记浏览量是
/open/mall/product/suggestionsGET商品搜索建议,参数 keyword 必填、limit 默认 10是
/open/mall/merchant/{merchantId}GET商家详情是
/open/mall/merchant/{merchantId}/productGET某商家的在售商品,可选 keywords是

营销活动:/open/mall/activity

OpenMallPromotionController。

路径方法说明是否匿名
/open/mall/activity/listGET进行中的活动商品列表,可选 activityType是
/open/mall/activity/history/listGET历史活动商品列表,可选 activityType是
/open/mall/activity/{activityId}GET活动详情,只返回已发布且审核通过的是
/open/mall/activity/product/{productId}GET某商品当前参与的活动,可选 skuId是

相关阅读

目录