跳到主要内容

应用

应用

应用是 src/app/ 下的一个文件夹:+app.ts 声明它,旁边的每个 +<page>.page.svelte 是一个页面。文件夹也可以改为包含 +group.ts——一个导航分组,其中的应用或下级分组都放在它内部。应用的名称就是它的文件夹路径。

src/app/
├── field_ops_controller/
│   ├── +app.ts
│   ├── +dispatch.page.svelte
│   └── +sites.page.svelte
├── field_ops_contractor/
│   ├── +app.ts
│   └── +jobs.page.svelte
└── <group>/
    ├── +group.ts
    └── <app>/+app.ts …

声明应用

// src/app/field_ops_controller/+app.ts (templates/field-operations)
import { app } from '@norbital-ai/bolt';

export default app('field_ops_controller', {
  title: 'app.field_ops_controller.title',
  description: 'Schedule site jobs and dispatch contractors',
  icon: 'lucide:building-2',
  banner: 'app-media/field_ops_controller-banner.webp',
  pages: {
    dispatch: { title: 'app.field_ops_controller.tab_dispatch', icon: 'lucide:kanban' },
    sites: { title: 'app.field_ops_controller.tab_sites', icon: 'lucide:map-pinned' }
  }
});

app('<name>', { … }) 接收应用卡片的 title、description 与 icon,可选的 banner,audience,以及 pages——以页面文件名为键、按导航顺序排列,每项带 title、可选的 icon、用于分组的 section,以及全屏页面的 kiosk: true。没有条目的页面文件是构建错误。一旦工作区有了 src/i18n/,标题就是消息目录键。

受众

'members'(默认)向员工显示应用,'external' 向外部成员(如客户与供应商门户用户)显示,'all' 向两者显示。{ public: [policies], challenge?: 'turnstile' } 把页面提供给未登录的访客,访客只持有这些策略,只能提交表单与读取已发布的行。

只有当成员的某个策略在 capabilities.apps 中列出该应用(或包含它的分组)时,成员才能看到它。+workspace.ts 中的 apps 设定应用在启动器中的顺序。

页面

<!-- src/app/field_ops_controller/+sites.page.svelte (templates/field-operations, excerpt) -->
<script lang="ts">
  import { bolt } from '$bolt';
  import { AppShell } from '@norbital-ai/ui/layout';
  import { Table } from '@norbital-ai/ui';

  const t = bolt.t;
</script>

<AppShell
  icon="lucide:map-pinned"
  title={t('app.field_ops_controller.tab_sites')}
  description={t('app.field_ops_controller.sites_description')}
>
  <Table
    of="sites"
    orderBy={{ name: 'asc' }}
    columns={['name', { field: 'client_name', label: t('component.client_tenant') }, 'address']}
  />
</AppShell>

页面是一个 Svelte 5 组件。它从 $bolt 导入 bolt 进行读写,从 @norbital-ai/ui 导入视图,从 @norbital-ai/ui/layout 导入布局。每个页面都是一个 AppShell,其 title、description 与 icon 渲染页面的头图区域。页面从不导入角色模块:它通过 RecordShell 与记录面板打开记录。

分组

src/app/<group>/+group.ts 为 group('<group>', { label, description?, icon, defaultChild })。一个文件夹要么是应用,要么是分组,不能两者兼有;在策略中指定一个分组即可打开其中所有应用。