Skip to content

组件运行时上下文

在 Neo 页面中,自定义组件运行时会注入页面级数据用户数据环境对象工具函数等,自定义组件中可直接使用这些环境变量和工具函数。

props 上的位置作用
data(及下文 __Neo* 字段)当前页注入的用户、系统、页面元信息等
env.ctx平台对象 CTX,系统 / 用户 / UI / 工具 / api
keyIdentifier$schema$com当前组件实例标识;设计时属性区另见 $com
  • 类组件:通过 this.props.datathis.props.env.ctx 等访问。
  • 函数组件:通过入参 props 或解构 const { data, env } = props 使用;若使用 Hooks,在依赖中传入完整 envenv?.ctx 时需注意引用稳定性。

页面数据与用户、租户信息

以下字段均在 this.props.data 上:

用途路径说明
当前用户this.props.data.__NeoCurrentUser用户信息
系统信息this.props.data.__NeoSystemInfo租户相关系统信息
页面信息this.props.data.__NeoPageInfo含页面 ID 等页面级元数据

使用示例(当前用户、系统与页面):

js
// 当前用户(页面注入的用户对象,字段以实际平台为准,常见含 id、name 等)
const currentUser = this.props.data?.__NeoCurrentUser;
if (currentUser) {
  console.log(currentUser.id, currentUser.name);
}

// 租户与系统信息
const systemInfo = this.props.data?.__NeoSystemInfo;

// 页面元数据(含页面 ID 等,字段以平台实际返回为准)
const pageInfo = this.props.data?.__NeoPageInfo;

组件 ID(keyIdentifier)

使用场景取值位置
运行时设计时画布区this.props 上的 keyIdentifier;也可从 this.props.$schema 中解析
设计时属性面板this.props.$com.keyIdentifier

使用示例:

js
// 运行时 / 画布:组件实例唯一标识
const curCmpKey = this.props.keyIdentifier;

// 设计时属性面板
const curCmpKey = this.props.$com?.keyIdentifier;

全局对象 CTX(props.env.ctx

平台已将 CTX 注入到 props.env.ctx。下文按分类列出可用能力;标注为「只读」的均为属性访问,其余为函数调用。

系统(system)

名称 / API类型说明读写
language属性当前用户使用的系统语言只读
timeZone属性当前用户使用的时区只读
clientType属性访问端类型:Web(网页)、App(移动)、WeCom(企微)、DingTalk(钉钉)只读
tenantId属性当前租户 ID只读
tenantName属性当前租户名称只读
currencies属性当前租户已启用的货币类型只读
systemType属性业务系统类型,例如 crmprm只读
logout()函数登出并回到登录页
getCurrentDate(format?)函数获取当前系统时间;可通过 format 指定返回格式,默认包含年月日时分

使用示例(语言、租户、logout):

js
const ctx = this.props.env?.ctx;
if (!ctx) return;

const { language, tenantId, tenantName } = ctx.system;
// 登出并回到登录页(常用于自定义「退出」按钮)
ctx.system.logout();

当前用户(user)

名称 / API类型说明读写
name属性用户姓名只读
currency属性用户货币类型只读
id属性用户 ID只读
primaryFunctionalId属性主职能 ID只读
functionals属性已分配职能列表,元素形如 { id, name, isMain }只读
departmentId属性部门 ID只读
departmentName属性部门名称只读
email属性邮箱只读
phoneNumber属性手机号只读

使用示例:

js
const user = this.props.env?.ctx?.user;
if (!user) return;

const { id, name, email, departmentName } = user;
// 按业务需要读取职能、部门等
const mainFunctional = user.functionals?.find((f) => f.isMain);

界面(ui)

名称 / API类型说明读写
showToast(type, msg, time?)函数轻提示。typesuccess | warning | errormsg 为文案;time 为停留秒数,默认 1
confirm(options)函数确认弹窗,参数见下方
openIframe(options)函数以弹层形式打开 iframe,可拖动;参数见下方
showLoading()函数当前页显示遮罩与 loading
hideLoading()函数关闭当前页遮罩与 loading
openPickerList(options)函数打开实体 Picker(查找)页;参数见下方
navigatePageTo({ url, isNewWindow? })函数打开指定页面;可在当前页跳转或新标签打开,默认新标签

confirm 参数:

ts
confirm({
  title: string;       // 标题
  msg: string;         // 正文
  width?: string;      // 宽度,默认约 400px
  onOk: () => void;    // 确认
  onCancel: () => void; // 取消
});

openIframe 参数:

ts
openIframe({
  devPageKey?: string;           // 内部开发页:入口页 apiKey;外部页配合 url
  url: string;                   // 自定义页 URL
  title: string;                 // 弹窗标题
  height?: string | number;      // 高度,默认 300px
  width?: string | number;       // 宽度,默认 400px
  showFooter?: boolean;          // 是否显示 footer,默认 false
  onOk?: Function;
  onCancel?: Function;           // 取消与右上角关闭
  showCloseButton?: boolean;     // 是否显示右上角关闭,默认 true
});

openPickerList 参数:

ts
openPickerList({
  objectApiKey: string;                    // 实体 ApiKey
  listView: string;                        // 列表视图 apiKey,如 "customEntity2c_view_2"
  selectionMode?: "single" | "multiple"; // 单选 / 多选
  conditions?: {
    apiKey: string;
    type: FilterOperator;
    value: any; // 多值用逗号分隔表示 OR
  }[];
  orderBy?: {
    field: string;
    order?: "asc" | "desc";
  };
  title?: string; // Picker 标题
});

典型场景:在销售机会上为关联字段打开客户的 Picker 页。

使用示例:

js
const ui = this.props.env?.ctx?.ui;
if (!ui) return;

ui.showToast('success', '保存成功', 2);

ui.confirm({
  title: '确认删除',
  msg: '删除后不可恢复,是否继续?',
  onOk: () => {
    // 执行删除
  },
  onCancel: () => {},
});

工具函数(util)

名称 / API类型说明读写
log(any)函数控制台 log
warn(any)函数控制台 warn
info(any)函数控制台 info
error(any)函数控制台 error
setTimeout(fn, time)函数与标准 setTimeout 类似
setInterval(fn, time)函数与标准 setInterval 类似
isEmpty(any)函数判空;支持基本类型、数组、对象;{}[] 视为空
urlParams属性当前页 URL 的查询参数(如 ?a=1&b=2 对应可解析的键值),用于按入参控组件行为、与深度链接等场景配合
openAIChat(any)函数打开 AI 对话框方法

使用示例(urlParamsisEmpty):

js
const util = this.props.env?.ctx?.util;
if (!util) return;

// 读取当前页 URL 查询参数,例如 ?orderId=123
const orderId = util.urlParams?.orderId;

if (!util.isEmpty(orderId)) {
  util.log('orderId', orderId);
}

示例

使用 openAIChat 增加 打开 AI 对话框的按钮:

import * as React from 'react';
// @ts-ignore
import { BaseCmp } from 'neo-ui-common';

export default class openChatPageBtn extends BaseCmp<
  openChatPageBtnProps,
  chatPageStates
> {
  constructor(props: openChatPageBtnProps) {
    super(props);
  }

  openChatPage() {
    const { env, aiQuery, agentApiKey } = this.props;
    const openAIChat = env?.ctx?.util?.openAIChat;
    if (!openAIChat) {
      return;
    }
    // 打开AI对话页
    openAIChat({
      query: aiQuery || '请总结一下本周数据变化',
      agentApiKey: agentApiKey || 'sales_assistant_agent',
    });
  }

  render() {
    const { className, placeholder } = this.props;

    return (
      <div className={`openChatPageBtn__c-container ${className || ''}`}>
        <button
          className="openChatPageBtn-button"
          onClick={() => this.openChatPage()}
        >
          <span className="openChatPageBtn-icon"></span>
          <span className="openChatPageBtn-text">
            {placeholder || '打开AI对话页'}
          </span>
        </button>
      </div>
    );
  }
}

接口(api)

下文示例中的 ctxthis.props.env.ctx(与上文的 CTX 为同一对象)。

使用示例(request):

js
const ctx = this.props.env?.ctx;
if (!ctx?.api?.request) return;

ctx.api
  .request({
    url: '/your/open/or/custom/api',
    method: 'POST',
    headers: {},
    data: { foo: 1 },
  })
  .then((res) => {
    ctx.util?.log(res);
  });
名称 / API类型说明读写
ctx.api.openCreateForm({ ... })函数打开新建表单,参数见下方
ctx.api.openEditForm({ ... })函数打开编辑表单
ctx.api.openCloneForm({ ... })函数打开复制表单
ctx.api.openListPage({ ... })函数打开对象列表页
request({ url, headers, method, data })函数调用服务端接口(仅开放接口或自定义接口)

新建表单 openCreateForm

  • objectApiKey:对象 API 名称
  • busiType:业务类型 API 名称
  • defaultValues:字段默认值(仅支持布局上出现的字段)。关联字段需传入 { id, name } 形式的对象。

示例:

js
ctx.api.openCreateForm({
  objectApiKey: 'xxx',
  busiType: 'defaultBusiType',
  defaultValues: {
    name: 'AME',
    parent__c: { id: '记录ID', name: '显示名称' },
  },
});

编辑表单 openEditForm

  • objectApiKeybusiType:同上
  • recordId:记录 ID
js
ctx.api.openEditForm({
  objectApiKey: 'zhu__c',
  busiType: 'defaultBusiType',
  recordId: 3710606526529990,
});

复制表单 openCloneForm 参数与 openEditForm 相同,用于基于已有记录复制一条数据。

js
ctx.api.openCloneForm({
  objectApiKey: 'zhu__c',
  busiType: 'defaultBusiType',
  recordId: 3710606526529990,
});

列表页 openListPage

  • objectApiKey:对象 API 名称
  • listView:视图 API 名称
  • config.isNewTab:是否在新页签打开
js
ctx.api.openListPage({
  objectApiKey: 'customEntity111__c',
  listView: 'customEntity111__c_view_all',
  config: { isNewTab: true },
});

小结

  • 组件上下文:业务 props 之外,由平台注入的页面数据(data)、运行环境能力(env.ctx / CTX)与组件标识(keyIdentifier / $schema / $com)等,共同构成运行时的使用环境;与构建工具里的「环境变量」含义不同。
  • 页面级数据从 this.props.data__NeoCurrentUser__NeoSystemInfo__NeoPageInfo 读取。
  • 组件标识 keyIdentifier 在运行/画布侧看 this.props$schema,设计时属性区看 this.props.$com.keyIdentifier
  • 系统 UI、用户态、工具方法与业务 API 统一通过 props.env.ctxCTX)访问。