组件上下文:环境变量与工具函数
在 Neo 页面中,自定义组件运行时会注入页面级数据、用户数据、环境对象与工具函数等,自定义组件中可直接使用这些环境变量和工具函数。
在 props 上的位置 | 作用 |
|---|---|
data(及下文 __Neo* 字段) | 当前页注入的用户、系统、页面元信息等 |
env.ctx | 平台对象 CTX,系统 / 用户 / UI / 工具 / api 等 |
keyIdentifier、$schema、$com | 当前组件实例标识;设计时属性区另见 $com |
- 类组件:通过
this.props.data、this.props.env.ctx等访问。 - 函数组件:通过入参
props或解构const { data, env } = props使用;若使用 Hooks,在依赖中传入完整env或env?.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 | 属性 | 业务系统类型,例如 crm、prm | 只读 |
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?) | 函数 | 轻提示。 type:success | warning | error;msg 为文案;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 对话框方法 | — |
使用示例(urlParams、isEmpty):
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)
下文示例中的 ctx 即 this.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:
objectApiKey、busiType:同上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.ctx(CTX)访问。
