Wujies 无界平台
平台功能(自研)应用市场

安装、升级、卸载与启停

四个动作都在宿主前端里做,全过程不需要重启宿主。这一页讲"在哪点、点完会发生什么"; 每个动作后端逐步做了什么见 在部署里使用应用。

入口与权限

想做的事页面路由前端源码
安装、市场内一键升级应用市场/appmarket/marketplus-ui/src/views/appstore/market/index.vue
升级、启用、停用、卸载我的应用 → 已安装应用/myapps/installedplus-ui/src/views/appstore/installed/index.vue
看进度、步骤、失败原因我的应用 → 应用任务/myapps/taskplus-ui/src/views/appstore/tasks/index.vue
从工作台进应用工作台「我的应用」卡片/indexplus-ui/src/views/workplace/index.vue

权限:安装 app:install:add(或 app:install:edit),升级 / 启停 / 卸载 / 同步菜单 app:install:edit, 看任务 app:install:list。

所有动作都是异步的

接口先返回一个 taskId,过程在后台跑,任务记录在动作执行之前就已落库。 所以排查任何生命周期问题,第一站都是「应用任务」,见 任务中心怎么用。

一、全程不需要重启宿主

部署、安装、升级、卸载、停用、启用都不重启。每个应用有自己的类加载器与 Spring 子上下文, 装卸就是建 / 关那个上下文,宿主进程一直活着。

两个例外要说清:

例外为什么
改了宿主自己的代码或配置(application.yml、签名公钥等)这些东西在启动期读入并打进 jar,必须重建宿主再启
改 app-market.plugin-runtime.enabled它由启动加载器读取,而加载器在 Spring 之前执行、读不到 yml —— 只能用 JVM 参数设置,改它必然要重启进程

二、安装

市场 → 选应用 → 安装 → 确认弹窗 → 装完自动启用(提示「安装成功,已自动启用」)。

确认弹窗会先说清三件事:会注册菜单并授权给本租户;过程与结果可在「我的应用 → 应用任务」里看; 带后端产物的应用需要它的插件已部署并被服务加载,否则会失败。

安装后端按固定顺序做四步:从市场拉包落位 → 执行迁移脚本 → 校验并加载后端产物 → 同步菜单与授权。 顺序是刻意的(先改表结构再切换代码),逐步细节见 在部署里使用应用。

安装失败也可能拿不到 taskId

某些失败会让接口直接抛异常,前端拿不到 taskId。但任务记录在动作执行之前就已落库, 所以日志一定在 —— 失败弹窗会直接把你送去「应用任务」。

依赖没装会怎样(这道闸在四步之前)

应用可以在清单里声明 dependencies(见 应用清单)。声明了就有三处表现:

位置表现
市场卡片必需依赖未满足时按钮是灰的,写着「依赖未满足」,悬停显示缺谁
详情页「简介」顶部列出每个依赖与状态:已安装(绿)/ 未安装或已停用(红)/ 可选未安装(灰)
安装 / 升级接口未满足 ⇒ 直接拒绝,而且不会产生安装任务记录

拒绝时给的是一句能照着做的话,而不是一个 Java 堆栈:

应用「商城管理」依赖「会员管理」「支付管理」「即时通讯」,请先安装并启用它们,才能安装。

依赖已装但被停用时会另说一句:停用会卸载它的插件后端(unload),依赖它的应用照样加载不了, 要去「我的应用」里先启用它。

怎么知道还缺谁

装之前先点开应用详情看「简介」标签页顶部的依赖列表;也可以直接照上面那句报错里的名字去装。 平台不会自动帮你把依赖一起装上 —— 一次点击装一个应用是刻意的(自动安装要动的代码位置见 应用市场架构)。

三、升级会强制重新落位

「我的应用」列表里版本旁出现「可升级 x.y.z」时才显示升级按钮;市场卡片上也能一键升级到最新版。

相对安装,升级的行为差异是:

差异说明
强制重新拉包落位只要目标版本与当前版本不同,本机现有产物(按定义是旧版本)一律不复用
菜单按新版本清单幂等 upsert同名 menu_key 复用既有 menu_id,租户已分配的权限不失效
保留原启停状态已停用的应用升级完仍是停用(状态迁移为 upgrading → disabled)

「文件存在就跳过」只在同版本重装时成立。升级时若沿用旧产物,会同时踩两个静默坑: 前端还是旧版,包内 migrations/*.sql 根本不落位。

同版本不能"升级"

后端会直接拒绝:「当前已是该版本,无需升级」。想重装请走重新安装或控制台部署。

回到旧版本

从市场选一个更低的版本安装或升级即可,菜单会按旧版本清单同步回去。

但表结构不会回滚 —— 迁移脚本只做 up。回退前请自己确认旧代码能不能吃新表结构, 规则见 数据库迁移。

四、卸载:两种模式怎么选

卸载弹窗只给两个选项,默认落在可恢复的那条路:打开弹窗时就是「保留数据」, 「彻底删除」要把应用名完整敲一遍才亮确认按钮。

保留数据(默认)彻底删除
本租户菜单授权回收回收(所有角色的,不只本租户)
后端插件unloadunload
菜单行(sys_menu)保留(重装即恢复可见)删除(含后代,如按钮)
数据表全部保留DROP TABLE,表名取自包内迁移脚本的建表语句
迁移记录保留删除(所以重装会重新建表)
字典与站点配置保留删除
本机产物(后端 jar、前端目录、active-plugins.txt 记录)保留删除(Windows 上 jar 被 JVM 占用时会如实报出删不掉)
安装记录保留,状态 uninstalled物理删除
防手滑确认即可要把应用名完整敲一遍

怎么选:

  • 「暂时不用了」「以后可能还要装回来」「只是不想让人看到入口」→ 保留数据;
  • 「确定不要了,而且要把表结构一起腾出来」→ 彻底删除(不可恢复)。
彻底删除时有两道闸,看到"跳过了"不是 bug
  1. 别人还在用就不动全局的东西。 菜单行、数据表、迁移记录、本机产物、字典与站点配置在一个部署内是 所有租户共享的。只要还有别的租户装着同一个应用,这些删除一律跳过,只在任务日志里说清楚。 判据会排除自己那条记录。
  2. 平台表前缀受保护。 只删迁移脚本声明过的表,表名命中 sys_ / app_ / gen_ / flow_ / act_ / qrtz_ / snailjob_ / undo_log 前缀时一律跳过并告警。

这两道闸的取舍见 多租户下的应用。

刻意不删的两样:任务记录(它是审计线索,代价是彻底删除后那些历史行显示「(应用已删除)」)、 对象存储里的文件(平台不知道它们属于谁,需要时自行清理)。

谁会被这次卸载影响

应用可以在清单里声明 dependencies。卸载 A 时,如果本租户还有已装应用依赖 A, 任务日志里会多一条提示(⚠️ 只是提示,不拦卸载):

注意:「商城管理」(mall) 依赖本应用。卸载后它们的相关功能会跟着不可用
(接口会回「应用不可用」);如需继续使用,请先安装回本应用,或先一并卸载它们。

为什么只提示:卸载是用户明确要做的事,拦死会让"卸载顺序与依赖相反"这种正常操作做不了; 而且默认卸载保留数据,装回来即可恢复。依赖关系见 应用清单。

五、停用与启用

动作后端真实行为状态可迁移自
停用只做 unload(关子 Spring 上下文与类加载器、注销接口),不动菜单行与授权enabled
启用先 load(把插件后端装回来)再补授权、放出菜单installed / disabled

按钮的可用性刻意与后端的合法状态迁移表对齐:只有 installed / disabled 才显示「启用」按钮, failed / uninstalled 的行不会出现它。

停用不是"撤授权"

停用后菜单入口消失,是因为菜单过滤器按安装状态隐藏了它们,而不是授权被回收。 所以重新启用能立刻恢复,也不会破坏管理员此前的手工分配。

想彻底让入口和数据都消失,请用「卸载 → 彻底删除」。停用只适合"临时收起来"。

启用失败必须让启用失败

如果加载失败却"看起来启用了",就是一个「菜单在、点进去打不开」的坏状态。 这也是停用只隐藏入口、不删菜单的原因之一。

六、装完要刷新菜单才能看到

前端那份菜单树只在登录时生成一次。 安装 / 升级 / 启用 / 停用 / 卸载改的都是后端数据, 同一会话里那份旧树会继续生效 —— 表现就是「装完回工作台没有这个应用」「升级后页面还按旧路径解析」。

前端为此提供了重建入口 plus-ui/src/plugins/appmarket/menuRefresh.ts 的 refreshMenus() (重新拉菜单并重建路由,幂等;失败不抛给调用方,只打 console.warn):

动作成功后自动重建菜单的地方说明
应用市场页安装成功、市场内一键升级成功后各调一次
已安装应用页升级 / 启用 / 停用 / 卸载走同一个动作封装,任务成功即调一次
工作台自愈:发现已装应用在旧树里找不到入口,先重建再判定

还是没出现时按顺序试:

  1. 手动刷新页面(等价于重新走一遍登录后的菜单生成);
  2. 去「应用任务」确认那次动作真的成功了 —— 失败时前端不会重建菜单;
  3. 菜单行本身漂移了(挂到了已不存在的菜单 ID 上),用 POST /app/install/{installId}/sync-menus(权限 app:install:edit)重新同步,它是幂等的; 自愈逻辑丢弃死映射时会在任务日志里 WARN 出被丢弃的 menu_key。

七、失败时先去哪儿

先看「应用任务」,不要去翻服务端日志。 顺序是:current_step(卡在哪一步)→ error_msg(服务端异常文本)→ 日志尾部(失败现场)。见 任务中心怎么用。

界面报错但任务日志里没线索,才是框架级原因(类加载、Spring 上下文、MyBatis 映射冲突), 去服务端日志,见 故障排查。

相关阅读

界面截图

我的应用 · 安装实例(截图占位)

我的应用 · 安装实例(截图占位)

/images/docs/my-apps.png

建议 1920 × 1080,能看到版本、启停与卸载。

目录