主题
17 · 组件包开发规范
面向第三方 / 内部团队交付可安装组件包(zip + manifest.yaml),经门户组件商店上架,由超管安装到本环境并以旁路进程托管。
工程说明:55 · 组件商店
能力声明规格:2026-09-28-component-capability-declaration.md
产品边界:商店只卖可安装包。纯外链 / 内嵌入口走「门户应用管理」。
1. 交付物与原则
| 交付 | 说明 |
|---|---|
| zip | 命名 sp-app-{appCode}-{version}.zip,根目录含 manifest.yaml |
| 运行时 | Java fat jar 常驻;start.sh(Linux 必带)+ 建议 start.bat |
| 能力声明 | manifest.capabilities(portal / admin);安装不会自动挂门户入口 |
| 原则 | 含义 |
|---|---|
| 宿主不变 | 不改 sp-boot / 主站静态发版路径 |
| 契约优先 | 对外只认包根 manifest.yaml |
| 声明与选用分离 | 能力在包内声明;是否挂门户 / 管理菜单由管理员选用 |
| 一组件一系统 | 安装按 systemCode(默认 = appCode)创建或复用业务系统 |
2. 包结构
text
manifest.yaml
backend/
start.sh # Linux/容器必带
start.bat # Windows 可选
your-app.jar # fat jar
web/ # 可选静态;也可由 jar 一并提供
hooks/ # 可选 install/uninstall(幂等)打包(PowerShell,保证根上就是 manifest):
powershell
Compress-Archive -Path manifest.yaml,backend,web -DestinationPath sp-app-survey-1.0.0.zip -ForceappCode:字母开头,仅字母数字下划线。version:同商品不可重复上传。
3. 启动脚本与端口
3.1 必须常驻
平台只认常驻进程。start.sh / start.bat 最终须落到类似:
bash
exec java -jar your-app.jar仅 echo listen / 后台 nohup 后又退出,会被判定为启动失败。
3.2 端口与 PUBLIC_BASE
| 变量 | 含义 |
|---|---|
COMPONENT_HTTP_PORT | 实际监听端口(平台分配;勿写死) |
INSTALL_ROOT / WORK_DIR | 安装根 / 工作目录 |
PUBLIC_BASE / COMPONENT_PUBLIC_BASE | 对外前缀,形如 /api/portal/components/runtime/{appCode} |
前端静态资源与 API 请求必须挂在该前缀下(或用相对路径),禁止写死站点根 /api/...,否则反代下必 404。
3.3 Shell 编码
start.sh 使用 UTF-8 无 BOM、LF。平台会对 .sh 做 BOM/CRLF 清洗,仍建议源文件本身正确。
不要依赖宿主机 Python;交付 Java fat jar。
4. manifest 与 capabilities
4.1 基础字段
| 字段 | 必填 | 说明 |
|---|---|---|
appCode / version / title | 是 | 编码、版本、显示名 |
processWorkDir | 建议 | 如 backend |
processStartCommand | 否 | 可写 cmd /c start.bat;Linux 自动换 sh |
processPort | 否 | 偏好端口,可被改派 |
openVia | 否 | 默认 PATH(runtime 反代);DIRECT_PORT 仅调试 |
systemCode | 否 | 默认 = appCode |
createSystemIfAbsent | 否 | 默认 true |
uiModeDefault | 否 | PLATFORM / STANDALONE |
capabilities | 强烈建议 | 见下;无则能力目录为空,无法绑定入口 |
4.2 capabilities(门户 / 管理)
yaml
appCode: survey
version: "1.0.0"
title: 问卷组件
systemCode: survey
createSystemIfAbsent: true
uiModeDefault: PLATFORM
processWorkDir: backend
processStartCommand: "cmd /c start.bat"
processPort: 19090
autoStart: true
capabilities:
portal:
- id: home
title: 问卷首页
path: /
openMode: IFRAME # IFRAME | EXTERNAL
uiMode: PLATFORM # PLATFORM | STANDALONE
default: true # 仅「推荐」标记,不自动注册
requireGrant: true # 是否要求用户先开通
- id: fill
title: 填写问卷
path: /fill
openMode: IFRAME
uiMode: PLATFORM
requireGrant: true
admin:
- id: design
title: 问卷设计
path: /admin/design
permCode: component:survey:design
uiMode: PLATFORM规则:
id唯一,仅[a-z0-9_];path以/开头、不含..。- portal 至多一个
default: true。 EXTERNAL+PLATFORM允许,但整页打开时平台壳包不住,组件应自觉控制顶栏。- 绑定后
portalAppCode:default 项 →{appCode};其它 →{appCode}__{id}。 - admin 导入为 PLATFORM 外链菜单(
PAGE);父菜单由导入时自选(不强制门户运营);打开方式可选内嵌页签 / 新窗口 / 全屏。 - 管理入口 = 平台菜单 perm 且 组件侧鉴权;直链不算授权。
- 导入后操作者 PLATFORM 角色会带上该入口权限。
4.3 安装之后管理员做什么
- 商店上传版本 → 发布 → 环境安装(拉起 jar,不自动建门户应用)。
- 选用 portal 能力(二选一):组件商店 → 能力 → 绑定,或 门户应用管理 → 从组件能力选用;admin 能力在商店点导入菜单。
- 用户侧按
requireGrant开通:开通 ≠ RBAC,但requireGrant: true时未开通则工作台看不见该入口。 - 换版本再安装:同 app 升级会自动刷新已绑定 URL;卸载会级联停用绑定入口(停进程不级联)。
5. 交付检查清单
- [ ] zip 根有
manifest.yaml,appCode/version/title齐全 - [ ]
backend/*.jar+start.sh:exec java -jar,读COMPONENT_HTTP_PORT,进程常驻 - [ ]
start.shUTF-8 无 BOM、LF - [ ]
processWorkDir相对安全 - [ ] 声明
capabilities.portal/admin(需要入口时);入口 path 用列表/首页,业务子页走组件内路由 - [ ] 前端 API / 资源 base =
COMPONENT_PUBLIC_BASE或相对路径 - [ ] admin 路径组件内自行鉴权
- [ ] 版本号未占用;验收用绑定后的 runtime URL,无需手贴 Nginx
6. FAQ
| 问题 | 处理 |
|---|---|
| 安装后没有门户入口 | 正常。须在管理端绑定 portal 能力(商店能力页或门户应用中心) |
| 进程启动后立即退出,log 只有 starting/listen | 没有常驻 java -jar 或 jar 秒退 |
need python3 | 不要依赖宿主机 Python;用 fat jar |
BOM / pipefail invalid | 编码问题;平台会洗 .sh,仍建议 LF 无 BOM |
| 页面能开、接口 404 | 前端打了站点根 /api/...;改挂 COMPONENT_PUBLIC_BASE |
| 版本已存在 | 改 manifest.version 再传 |
| 已绑定有 perm 仍看不见 | 查 release 是否 READY;requireGrant: true 时用户是否已开通 |
| 开通了仍进不去业务页 | 开通/绑定只解决入口;业务鉴权在组件内 |
| 反代 Connection refused | 平台/容器重启后旁路进程未自动拉起;管理端环境安装里点启动 |
| 点安装后平台宕机 / exit 137 | 组件与 Boot 同容器抢内存。平台已剥离子进程 JAVA_TOOL_OPTIONS 并默认注入较小 COMPONENT_JAVA_OPTS;容器内存仍须够 Boot+组件。也可在 start.sh 显式设小堆:java $COMPONENT_JAVA_OPTS -jar ... |
7. 样例与非目标
| 样例 | 位置 |
|---|---|
| 目录骨架 | 仓库旁 component-hello-sample/(自备 jar) |
| 无 HTTP 对照 | component-hello-process-only/ |
非目标:热加载进 Boot、微前端、自动执行包内 db/、自动写 Nginx conf、商店卖纯外链、旧包无 capabilities 的隐式自动入口兼容。