@qfei-design/make-app-observability

中文文档
0.1.11发布于 2026/11/02TypeScriptESM + CJS零依赖

Shared Make App error presentation and Trace ID display contracts.

原始使用文档
文档目录6 节
  1. 包负责什么
  2. 宿主负责什么
  3. 安装
  4. 使用
  5. Toast 自动关闭(当前源码改动,尚未发布)
  6. 权限拒绝提示(本分支新增,尚未发布)

@qfei-design/make-app-observability

Make App 统一错误展示与 Trace ID 呈现组件。它将错误卡片的布局、无障碍语义、复制反馈和 Trace ID 展示规则收敛到同一 npm 包,避免业务页面各自拼装 Toast 或 Alert。

包负责什么

  • 提供无 React 依赖的错误呈现模型:normalizeMakeAppErrorNotice。
  • 为所有真实请求失败展示格式正确的 Trace ID,包括 HTTP 非 2xx、网络异常和 HTTP 2xx 的业务码错误。
  • 提供与 Make App 设计一致的 MakeAppErrorNotice:错误图标、关闭按钮、Trace ID 区、复制和“已复制”状态。
  • 提供响应式、作用域限定的样式,不覆盖宿主全局 button、body 或弹层样式。
  • 在当前源码版本中统一管理全局 Toast 的生命周期:默认三秒关闭,支持 duration 秒数与 0 常驻;页面内提示保持常驻。

宿主负责什么

  • 在统一请求适配器中生成/保存 Trace ID,并把 HTTP 状态和错误类别转换为安全的用户文案。
  • 页面不得直接使用 message.error、Alert 或裸 fetch 来呈现 Make 业务请求错误;应统一交给应用的错误出口渲染本组件。
  • 在应用根节点或全局错误 Provider 中导入样式一次,并维护错误队列、业务重试和错误日志;包负责关闭计时,通过 onClose 通知宿主清理队列。
  • 继续确保 Service 返回 X-Log-ID、日志带 Trace ID,且不向浏览器暴露 token 或原始内部错误。

包不发起请求、不保存 Trace ID、不记录错误日志,也不自动探测宿主 UI 框架;这些运行时边界仍由 Make App 负责。

安装

pnpm add @qfei-design/make-app-observability

在 Make App UI 入口导入一次样式:

import "@qfei-design/make-app-observability/styles.css";

使用

import {
  MakeAppErrorNotice,
  MakeAppErrorNoticeViewport,
  type MakeAppErrorKind,
} from "@qfei-design/make-app-observability/react";

type Props = {
  kind: MakeAppErrorKind;
  status?: number;
  traceId?: string;
  visible: boolean;
  onClose: () => void;
};

export function GlobalMakeAppError(props: Props) {
  if (!props.visible) return null;

  return (
    <MakeAppErrorNoticeViewport>
      <MakeAppErrorNotice
        kind={props.kind}
        status={props.status}
        title="process/start 网络异常,请刷新后重试或更换网络后重试"
        traceId={props.traceId}
        onClose={props.onClose}
      />
    </MakeAppErrorNoticeViewport>
  );
}

MakeAppErrorNoticeViewport 在桌面和手机视口均将整个错误队列 portal 到 document.body,统一处理居中偏上、安全区、队列间距和超长内容滚动,避免单张卡片受宿主 transform containing block 影响或多张卡片相互覆盖。两端均水平居中;桌面队列默认从顶部 24px 开始向下排列,手机保持垂直居中偏上。 桌面采用顶部 Toast 定位,距顶部至少 24px 并避让安全区;手机队列中心相对可用视口中心向上偏移 clamp(24px, 5vh, 48px)。四边保留至少 12px 和安全区;长队列从安全区顶部开始并允许滚动。 宿主可通过容器的 --make-app-error-center-offset 调整手机向上偏移量(0px 为手机垂直居中),不需要额外的全屏定位 wrapper。 桌面卡片最大宽度 440px;桌面使用白底、红色左边线和紧凑标题/Trace ID 两行布局,右侧为关闭及复制图标。 手机(640px 及以下)沿用桌面的白底、灰色细边框、红色左边线、8px 圆角和普通等宽 Trace ID,仅增加底部双按钮:左侧「关闭」、右侧「复制」。手机卡片最大宽度 380px,两侧保留至少 12px 和安全区;按钮高度 32px,复制成功显示「已复制」与勾选。标题 14px,卡片留白略增,窄屏 Trace ID 自然换行。 viewport 内的卡片可带宿主 DOM wrapper,居中和卡片交互保持有效;首次服务端渲染和 hydration 保持一致,挂载后 portal 到 body。 宿主负责错误队列状态,并且一个全局错误出口只应渲染一个 viewport 容器;页面内嵌错误无需使用该容器。 viewport 默认使用 z-index: 2000;如果宿主的抽屉、预览或其他 overlay 层级更高,可通过 <MakeAppErrorNoticeViewport zIndex={2400}> 显式对齐宿主层级。portal 会脱离原宿主元素的 stacking context。

kind 必须明确传入:

  • http:存在合法 Trace ID 时显示。
  • network:存在合法 Trace ID 时显示,即使没有 HTTP 状态。
  • business:HTTP 2xx 的业务码异常同样显示合法 Trace ID,便于定位服务端校验失败。

包只消费宿主已经归一化的错误,不读取业务响应体,也不定义哪些业务 code 代表成功。 宿主请求层必须先判断 HTTP 状态,再在 HTTP 2xx 时继续判断业务 code:业务成功才返回数据, 非成功业务码应归类为 kind: "business",并优先提取公共非空字符串 msg,按接口兼容 message,连同 本次请求的 Trace ID 传入组件。不得因为 HTTP 状态为 200 就直接认定业务成功。HTTP 4xx/5xx 也保留有效公共原因; 不能按错误码或固定文案白名单覆盖具体原因和联系人,缺失公共原因时才兜底。禁止的是内部堆栈、凭据、原始 Error 和完整响应对象, 不是已确认的用户可见 msg。详细边界与宿主验收见 公共业务原因。

稳定入口和完整契约见 PUBLIC_API.md。

Toast 自动关闭(当前源码改动,尚未发布)

MakeAppErrorNoticeViewport 默认 duration={3},单位为秒。内部的全局错误卡片和权限 Toast 会在三秒后隐藏,并调用各自的 onClose 一次,供宿主清理对应队列项。 单条卡片的 duration 优先于 viewport;duration={0} 关闭自动计时,支持小数秒。 负数、NaN、Infinity 回退到有效的默认值。

<MakeAppErrorNoticeViewport duration={3}>
  <MakeAppErrorNotice kind="network" title="网络异常" onClose={removeError} />
  <MakeAppPermissionNotice variant="toast" duration={5} onClose={removePermissionToast} />
</MakeAppErrorNoticeViewport>

无 viewport 的错误卡片默认常驻,可显式指定 duration;权限 toast 即使独立渲染也默认三秒。 权限 inline/page 始终常驻并忽略 duration。手动关闭会取消计时器;卸载不会触发关闭回调。 包自身控制隐藏,即使未提供 onClose 也会按时关闭;宿主应提供回调清理队列,不再另建关闭计时器。 回调只用于清理提示,不能自动保存、删除或重试请求。

每次重新触发提示,都从该次触发重新计算完整显示时长。推荐给每个事件传 noticeKey(字符串或数字); 即使文案、Trace ID、关闭回调都相同,只要 noticeKey 改变就会重新显示并重新计时。React key 也可用于独立通知。

<MakeAppPermissionNotice noticeKey={eventId} variant="toast" onClose={removePermissionToast} />

兼容未传 noticeKey 的宿主:包把新的 onClose 函数引用视为重新触发信号,因此现有每次通知 更换关闭回调的接入方式无需改业务代码。若宿主每次普通重渲染也创建新的回调,计时同样会重置; 需要避免这种延长时,应使用显式 noticeKey。显式标识不变时,管理员加载或回调更新均不会重置计时。 如果相同文案、React key、noticeKey 与关闭回调都没有变化,包无法区分新事件与普通重渲染,宿主必须改变事件标识。 回调及计时信号只在 React 提交后更新,暂停或放弃的渲染不会影响当前提示。 需要长时间阅读或复制 Trace ID 时,宿主可以配置更长时长或 duration={0}。 以上默认行为仅存在于当前本地源码产物,接入前应核对实际安装包,不能根据相同的版本号推断。

权限拒绝提示(本分支新增,尚未发布)

新增 MakeAppPermissionNotice,在同一包内统一 Toast、表单/内容区、页面居中三种权限提示。 已发布的 0.1.8 不含此 API;接入前必须确认实际安装产物导出,版本由后续发布流程确定。 原 MakeAppErrorNotice、Trace ID 展示/复制与 viewport 默认行为保持不变。

import { MakeAppPermissionNotice, MakeAppErrorNoticeViewport } from "@qfei-design/make-app-observability/react";
import "@qfei-design/make-app-observability/styles.css";

// 内容区或表单内:放在原容器中,保留导航、标题和允许保留的输入。
<MakeAppPermissionNotice
  variant="inline"
  scope="resource"
  administrators={administrators}
  administratorStatus={administratorStatus}
  retryStatus={retryStatus}
  onRetry={refreshAccess}
/>

// 整个 App 无授权入口时,由宿主选择原入口的挂载位置与高度。
<MakeAppPermissionNotice variant="page" scope="app" administrators={administrators} onRetry={refreshAccess} />

// 全局 Toast 放到宿主已有的同一个错误出口,避免每个 Toast 创建 viewport。
<MakeAppErrorNoticeViewport>
  <MakeAppPermissionNotice variant="toast" operationName="导出" administrators={administrators} />
</MakeAppErrorNoticeViewport>

administrators 只接收当前 App 的直接授权人员 { userId, name, avatarUrl? },不传部门、Agent 或展开部门成员。Toast 显示姓名文字,inline/page 显示头像+姓名标签。空列表保留通用授权提示; 加载/查询失败不会展示旧联系人。姓名按文本渲染,头像允许 HTTPS 或安全站内绝对路径,加载失败用姓名首字。

宿主必须先确认是权限拒绝:401、未知403、租户不匹配和服务故障沿原错误出口处理,不能仅凭HTTP状态 使用此组件。包不请求管理员、不推断授权、不自动刷新或重试;包统一管理 Toast 关闭计时,宿主拥有队列状态。 onRetry 只由用户点击触发;retryStatus 支持 idle/checking/denied/error/restored,checking 禁用重复检查,denied 保留原授权引导而不追加重复提示, restored 只展示恢复结果,不重放导出/保存/删除。宿主刷新权限和授权后 Schema,再决定是否读取数据或允许用户重新操作。 只撤销记录读取权限时,由宿主清空旧行数据并把 inline 提示放在数据区,保留已授权表头和导航。

新增样式都同时限定在 .make-app-error-notice.make-app-error-notice--permission,不会改变原错误卡片。 可在新组件根节点通过 style/className 设置 --make-app-permission-primary、 --make-app-permission-primary-hover、--make-app-permission-text 和 --make-app-permission-muted。

本地视觉示例:先 pnpm build,再 pnpm dev,打开 /examples/permission-notice/。 示例通过公开包入口加载构建产物,用夹具演示三种样式、管理员和刷新状态,可与原错误卡片共同展示;不请求真实 IAM。

版本与发布记录

@qfei-design/make-app-observability 共发布 9 个版本,首次发布于 2026/09/10;过去 12 个月发布了 9 个版本。

版本发布日期距今
0.1.11latest2026/11/021 天前
0.1.102026/10/268 天前
0.1.92026/10/2014 天前
0.1.82026/10/1222 天前
0.1.72026/10/1024 天前
0.1.62026/09/301 个月前

关于 @qfei-design/make-app-observability 的常见问题

@qfei-design/make-app-observability 是什么?

共享Make App错误显示和Trace ID显示合约。

如何安装 @qfei-design/make-app-observability?

在项目目录运行 npm install @qfei-design/make-app-observability,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(^18.2.0 || ^19.0.0)、react-dom(^18.2.0 || ^19.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@qfei-design/make-app-observability 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@qfei-design/make-app-observability 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@qfei-design/make-app-observability 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.12.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@qfei-design/make-app-observability 可以商用吗?

@qfei-design/make-app-observability 使用 未声明 许可。package.json 没有声明许可证。没有许可证的代码默认保留全部权利,商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括,不构成法律意见,请以许可原文为准。

@qfei-design/make-app-observability 还在维护吗?

最新版本 0.1.11 发布于 2026/11/02(1 天前);至今共发布 9 个版本,其中过去 12 个月发布了 9 个;首次发布于 2026/09/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。