Skip to content

GenuiRenderer 组件

GenuiRenderer 是 GenUI SDK 的核心渲染组件(Renderer),用于将大模型返回的结构化 JSON Schema 渲染为可交互的 UI 界面。

物料配置

GenuiRenderer 本身不包含 UI 物料,需配合 GenuiConfigProvidermaterials 使用,详见 安装与配置

若需保持旧版「开箱即用」行为,请改用 GenuiLegacyRenderer,Input 与内容投影与 GenuiRenderer 完全一致。

兼容组件 GenuiLegacyRenderer

GenuiLegacyRenderer 内置 OpenTiny NG 默认物料,适用于未配置 GenuiConfigProvider 的旧项目迁移,无需额外安装物料包。

ts
import { Component } from '@angular/core';
import { GenuiLegacyRenderer } from '@opentiny/genui-sdk-angular';

@Component({
  imports: [GenuiLegacyRenderer],
  template: `
    <genui-legacy-renderer [content]="schemaContent"></genui-legacy-renderer>
  `,
})
export class GenuiExample {
  schemaContent = {
    componentName: 'Page',
    children: [
      {
        componentName: 'TiButton',
        props: { color: 'primary' },
        children: [{ componentName: 'Text', props: { text: '提交' } }],
      },
    ],
  };
}

Input

content

  • 类型: string | object
  • 必填: 是
  • 说明: Schema 内容,可以是字符串或对象。当传入字符串时,组件会尝试解析"部分 JSON"并自动补全,支持流式更新。
ts
import { Component } from '@angular/core';
import { GenuiRenderer } from '@opentiny/genui-sdk-angular';

@Component({
  imports: [GenuiRenderer],
  template: `
    <genui-renderer [content]="schemaContent"> </genui-renderer>
  `,
})
export class GenuiExample {
  schemaContent = {
    componentName: 'Page',
    children: [
      {
        componentName: 'Text',
        props: {
          text: 'Hello World',
        },
      },
    ],
  };
}

isJsonComplete

  • 类型: boolean
  • 必填: 否
  • 说明: 仅当content类型为json对象时生效,标记当前json是否完整,用于辅助缓冲判断是否值完整。
ts
import { Component } from '@angular/core';
import { GenuiRenderer } from '@opentiny/genui-sdk-angular';

@Component({
  imports: [GenuiRenderer],
  template: `
    <genui-renderer [content]="schemaContent" [isJsonComplete]="isJsonComplete"> </genui-renderer>
  `,
})
export class GenuiExample {
  schemaContent = {
    componentName: 'Page',
    children: [
      {
        componentName: 'Text',
        props: {
          text: 'Hello World',
          style: 'color:'
        },
      },
    ],
  };
  isJsonComplete = false;
}

generating

  • 类型: boolean
  • 必填: 否
  • 说明: 标记当前对话是否正在生成中。用于控制 UI 的加载状态。
ts

import { Component } from '@angular/core';
import { GenuiRenderer } from '@opentiny/genui-sdk-angular';

@Component({
  imports: [GenuiRenderer],
  template: `
    <genui-renderer [content]="content" [generating]="isGenerating"> </genui-renderer>
  `,
})
export class GenuiExample {
  schemaContent = {
    componentName: 'Page',
    children: [
      {
        componentName: 'Text',
        props: {
          text: 'Hello World',
        },
      },
    ],
  };
  isGenerating = true;
}

customComponents

  • 类型: Record<string, Type<any>>
  • 必填: 否
  • 说明: 自定义组件映射表,用于扩展可用的组件列表。
ts
import { Component } from '@angular/core';
import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
import { MyCustomComponent } from './my-custom-component';

@Component({
  imports: [GenuiRenderer],
  template: `
    <genui-renderer [content]="schemaContent" [customComponents]="customComponents"> </genui-renderer>
  `,
})
export class GenuiExample {
  schemaContent = {
    componentName: 'Page',
    children: [
      {
        componentName: 'MyCustomComponent',
        props: {
          foo: 'bar',
        },
      },
    ],
  };
  customComponents = {
    MyCustomComponent: MyCustomComponent,
    // 。。。
  };
}

说明

  • 如果使用非standalone组件需要搭配customComponentsModule使用.
  • 组件相关描述信息需要调用接口时候传给后台服务,大模型能配套僧成该组件的协议JSON数据
  • ⚠️ 限制:动态渲染技术目前不支持使用@ContentChild@ContentChildren查询的组件

customComponentsModule

  • 类型: Record<string, Type<any>>
  • 必填: 否
  • 说明: 自定义组件归属模块映射表,用于扩展非standalone组件需要配置模块映射列表。
ts
import { Component } from '@angular/core';
import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
import { MyCustomModule, MyCustomComponent } from './my-custom-module';

@Component({
  imports: [GenuiRenderer],
  template: `
    <genui-renderer [content]="schemaContent" [customComponents]="customComponents" [customComponentsModule]="customComponentsModule"> </genui-renderer>
  `,
})
export class GenuiExample {
  schemaContent = {
    componentName: 'Page',
    children: [
      {
        componentName: 'MyCustomComponent',
        props: {
          foo: 'bar',
        },
      },
    ],
  };
  customComponents = {
    MyCustomComponent: MyCustomComponent,
    // 。。。
  };
  customComponentsModule = {
    MyCustomComponent: MyCustomModule,
    // 。。。
  }
}

customDirectives

  • 类型: Record<string, Type<any>>
  • 必填: 否
  • 说明: 自定义指令归属模块映射表,用于扩展指令列表。
ts
import { Component } from '@angular/core';
import { GenuiRenderer } from '@opentiny/genui-sdk-angular';
import { MyCustomDirective } from './my-custom-directive';

@Component({
  imports: [GenuiRenderer],
  template: `
    <genui-renderer [content]="schemaContent" [customDirectives]="customDirectives"> </genui-renderer>
  `,
})
export class GenuiExample {
  schemaContent = {
    componentName: 'Page',
    children: [
      {
        componentName: 'div',
        directives: [
          {
            directiveName: 'MyCustomDirective'
          }
        ]
      },
    ],
  };
  customDirectives = {
    MyCustomDirective: MyCustomDirective,
    // 。。。
  };
}

⚠️ 限制说明: 受限于 ViewContainerRef.createComponent API,目前只支持 standalone 的指令

customActions

  • 类型: Record<string, { execute: (params: any, context: any) => void }>
  • 必填: 否
  • 说明: 自定义动作映射表,用于定义可在组件中调用的动作。
ts
import { Component } from '@angular/core';
import { GenuiRenderer } from '@opentiny/genui-sdk-angular';

@Component({
  imports: [GenuiRenderer],
  template: `
    <genui-renderer [content]="schemaContent" [customActions]="customActions"> </genui-renderer>
  `,
})
export class GenuiExample {
  schemaContent = {
    componentName: 'Page',
    children: [
      {
        componentName: 'Text',
        props: {
          text: 'Hello World',
          onClick: {
            type: 'JSFunction',
            value: 'function() { this.callAction(\'showNotification\', { message: \'用户点击了 HelloWorld\'})}'
          }
        },
      },
    ],
  };
  customActions = {
    openPage: {
      execute: (params, context) => {
        window.open(params.url, params.target || '_self');
      },
    },
    showNotification: {
      execute: (params, context) => {
        console.log('通知:', params.message);
      },
    },
  };
}

查看 Renderer 自定义 Actions 了解详细用法

requiredCompleteFieldSelectors

  • 类型: string[]
  • 必填: 否
  • 说明: 指定哪些字段路径需要完整后才能更新。用于控制流式更新时的缓冲策略。
ts
import { Component } from '@angular/core';
import { GenuiRenderer } from '@opentiny/genui-sdk-angular';

@Component({
  imports: [GenuiRenderer],
  template: `
    <genui-renderer [content]="schemaContent" [requiredCompleteFieldSelectors]="requiredCompleteFieldSelectors"> </genui-renderer>
  `,
})
export class GenuiExample {
  schemaContent = {
    componentName: 'Page',
    children: [
      {
        componentName: 'Text',
        props: {
          text: 'Hello World',
          onClick: {
            type: 'JSFunction',
            value: 'function() { this.callAction(\'showNotification\', { message: \'用户点击了 HelloWorld\'})}'
          }
        },
      },
    ],
  };

  requiredCompleteFieldSelectors = [
    '[componentName=Text] > props > onClick'
  ];
}

查看 Renderer 配置缓冲字段 了解详细用法

state

  • 类型: Record<string, any>
  • 必填: 否
  • 说明: 传递给渲染器的全局状态,可以在组件中通过上下文访问。
ts
import { Component } from '@angular/core';
import { GenuiRenderer } from '@opentiny/genui-sdk-angular';

@Component({
  imports: [GenuiRenderer],
  template: `
    <genui-renderer [content]="schemaContent" [state]="state"> </genui-renderer>
  `,
})
export class GenuiExample {
  schemaContent = {
    componentName: 'Page',
    state: {
      userId: null,
      userName: ''
    },
    children: [
      {
        componentName: 'Text',
        props: {
          text: {
            type: 'JSExpression',
            value: 'this.state.userName'
          }
        },
      },
    ],
  };

  // 从某种历史记录恢复
  state = this.getFromCache();
  getFromCache() {
    return {
      userId: 123,
      userName: 'John'
    }
  }
}

查看 Renderer 传递合并 State 了解详细用法

Template

  • 上下文: { schema: CardSchema, isError: boolean, isFinished: boolean }
  • 说明: 自定义渲染器头部内容
ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common'
import { GenuiRenderer } from '@opentiny/genui-sdk-angular';

@Component({
  imports: [
    CommonModule,
    GenuiRenderer
  ],
  template: `
    <genui-renderer [content]="schemaContent">
      <ng-template #header let-schema="schema" let-isError="isError" let-isFinished="isFinished">
        <span *ngIf="!isFinished"> 生成中 …… </span>
        <span *ngIf="isError"> 出错了!</span>
        <span>卡片标题:{{ schema.componentName }}</span>
      </ng-template>
    </genui-renderer>
  `,
})
export class GenuiExample {
  schemaContent = {
    componentName: 'Page',
    children: [
      {
        componentName: 'Text',
        props: {
          text: 'Hello World',
        },
      },
    ],
  };
}
  • 参数: { schema: CardSchema, isError: boolean, isFinished: boolean }
  • 说明: 自定义渲染器底部内容
ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common'
import { GenuiRenderer } from '@opentiny/genui-sdk-angular';

@Component({
  imports: [
    CommonModule,
    GenuiRenderer
  ],
  template: `
    <genui-renderer [content]="schemaContent">
      <ng-template #footer let-schema="schema">
        <button (click)="handlePrint(schema)">打印schema</button>
      </ng-template>
    </genui-renderer>
  `,
})
export class GenuiExample {
  schemaContent = {
    componentName: 'Page',
    children: [
      {
        componentName: 'Text',
        props: {
          text: 'Hello World',
        },
      },
    ],
  };
  handlePrint(schema: any) {
    console.log(schema);
  }
}