docs/integration/app.md 自动同步生成。- 日期:2026-09-21
- 适用:新建业务 App,以及
g2rain-member-app、g2rain-manager-app、g2rain-department-app - 工具:
create-g2rain-app(源码仓库g2rain-app-cli) - 模板:CLI 项目内的
template/。create复制这一份;g2rain-app-template只在维护 CLI、执行npm run sync:template时同步进来 - 运行时入口:
@g2rain/platform/sub
# 1. 安装
Registry 安装尚未提供。@g2rain/* 和 create-g2rain-app 发版后的安装命令待补充。g2rain-app-template 不单独安装。
下面是现在能用的装法。Node.js 需要 >=22。
# 1.1 公共包
在 g2rain-appkit 目录打包当前制品:
npm ci
npm run build --workspace @g2rain/theme
npm run build --workspace @g2rain/ui
npm run build --workspace @g2rain/http
npm run build --workspace @g2rain/platform
npm pack --workspace @g2rain/theme
npm pack --workspace @g2rain/ui
npm pack --workspace @g2rain/http
npm pack --workspace @g2rain/platform
当前文件名:
| 文件 | 包 |
|---|---|
g2rain-theme-0.1.0.tgz | @g2rain/theme |
g2rain-ui-0.1.1.tgz | @g2rain/ui |
g2rain-http-0.1.0.tgz | @g2rain/http |
g2rain-platform-0.1.0.tgz | @g2rain/platform |
把这四个文件放到业务 App 的 kits/,然后:
npm install ./kits/g2rain-theme-0.1.0.tgz ./kits/g2rain-ui-0.1.1.tgz ./kits/g2rain-http-0.1.0.tgz ./kits/g2rain-platform-0.1.0.tgz
package.json 使用 file:kits/...,不要写成仓外的 file:../g2rain-appkit/...。Docker 构建上下文里没有那个目录。
样式在应用入口引入:
import '@g2rain/theme/styles.css'
import '@g2rain/ui/style.css'
# 1.2 CLI
创建项目、生成页面和生成资源配置都用 create-g2rain-app / g2rain-app。步骤、参数和当前本地安装见 CLI 使用手册 (opens new window)。
当前没有 Registry 版本。在 g2rain-app-cli 目录执行 npm ci、npm run build、npm link 之后,可以使用这两个命令。已有 App 也可以把 CLI 装成开发依赖:
{
"devDependencies": {
"create-g2rain-app": "file:../g2rain-app-cli"
}
}
然后在 App 根目录用 npx g2rain-app。
# 1.3 模板
create-g2rain-app 复制的是 CLI 项目里的 template/,不要再克隆 g2rain-app-template。模板里的 和 由这次复制时替换。
当前模板 package.json 仍引用 file:../g2rain-appkit/ 下的压缩包,并且包含已经不存在的 @g2rain/runtime。生成后的项目不要沿用这些依赖,改成第 1.1 节的 kits/ 安装,再执行 npm install。模板不复制 lockfile,第一次安装不要用 npm ci。
# 2. 新建后的命令
在生成出的项目根目录:
| 命令 | 作用 |
|---|---|
npm run dev | 启动 Vite |
npm run build | vue-tsc 后构建 dist |
npm run preview | 预览构建结果 |
g2rain-app generate --tables=<表名> | 按 scripts/database.sql 生成页面骨架 |
g2rain-app build-config | 写出页面和页面元素资源 JSON |
g2rain-app generate --tables=dict
g2rain-app generate --tables=dict,medicine_users
g2rain-app generate --tables=dict --no-mock --no-route
g2rain-app build-config
generate 会覆盖 src/views/<表名>/ 下的 index.vue、api.ts、type.ts、mock.ts,并更新 src/views/route-map.ts。执行前先看 Git 状态。
build-config 写出:
src/shared/config-util/config/resources.jsonsrc/shared/config-util/config/pages.jsonsrc/shared/config-util/config/page-elements.json
它不生成 api-endpoints.json,resources.json 里的 API 端点为空。改了路由或静态 v-permission 之后要重新执行。
# 3. 本地运行
独立运行。PowerShell:
$env:VITE_RUN_MODE = 'alone'
$env:VITE_SERVER_PORT = '3001'
$env:VITE_BACKEND_ORIGIN = 'http://localhost:8080'
npm run dev
Bash:
VITE_RUN_MODE=alone VITE_SERVER_PORT=3001 VITE_BACKEND_ORIGIN=http://localhost:8080 npm run dev
也可以打开 http://localhost:3001/?mode=alone。未设置 mode=alone 时,直接访问开发地址会跳到 VITE_MAIN_SHELL_ORIGIN + VITE_MAIN_SHELL_REDIRECT_PREFIX。
和主应用联调时由主应用加载,子应用只启动开发服务器:
$env:VITE_MAIN_SHELL_ORIGIN = 'http://localhost:3000'
$env:VITE_MAIN_SHELL_REDIRECT_PREFIX = '/main/redirect'
npm run dev
VITE_APPLICATION_CODE 填平台里的应用编码。VITE_CONTEXT_PATH 与部署时的 CONTEXT_PATH 使用同一个路径,例如 /order。
# 4. 入口
qiankun 的 mount、update、unmount 仍由应用导出。createStandardSubPlatform 在模块里调用一次。Pinia 和 HTTP Client 也在模块里创建一次,不要放进 createApplication。
import { createStandardSubPlatform, resolveSubHostProps } from '@g2rain/platform/sub'
const definition = createStandardSubPlatform({
applicationCode,
createApplication(context) {
const app = createApp(App)
const router = createRouter(context)
app.use(pinia)
app.use(router)
return {
mount: container => app.mount(container),
update: next => router.replace(next.initialRoute ?? '/'),
unmount: () => app.unmount(),
}
},
i18n: { engine, uiLocale },
error: { presenter, actions, unknownMessage: '未知错误' },
})
export async function mount(props) {
const resolved = resolveSubHostProps(props, {
applicationCode,
contextPath,
})
await definition.mount({
instanceId: resolved.instanceId,
context: resolved.context,
container: props.container,
})
}
export async function update(props) {
const resolved = resolveSubHostProps(props, { applicationCode, contextPath })
await definition.update(resolved.instanceId, resolved.patch)
}
export async function unmount(props) {
const resolved = resolveSubHostProps(props, { applicationCode, contextPath })
await definition.unmount(resolved.instanceId)
}
resolveSubHostProps 要求宿主下发 applicationCode、viewId、instanceId,且 appKey === instanceId。Token 不经公开 props;集成模式通过应用侧 Auth Bridge(定向消息)写入 Token Store,不要把认证载荷拷进 definition.mount 的 context。
独立模式在 main.ts 里调用同一个 definition。容器用 #app,mode 为 standalone:
await definition.mount({
instanceId: 'standalone',
context: {
applicationCode,
viewId: 'standalone',
instanceId: 'standalone',
mode: 'standalone',
contextPath,
theme: 'light',
},
container,
})
应用卸载时调用 definition.unmount('standalone')。不要再写一套独立启动流程。