关于 add-pen-input
用于在 Power Apps 移动项目中添加或检查原生笔输入封装的内部技能。它通过 React Native API 捕获手绘内容或签名并返回 PNG 数据 URI,并提供可选的 Dataverse 保存指引。
主要功能
- 01捕获手绘内容和签名
- 02返回 PNG 数据 URI
- 03去除数据 URI 前缀
- 04将取消作为正常结果处理
- 05支持保存到 Dataverse Image 或 File
适用场景
- 01在移动界面采集签名
- 02收集手写证据
- 03显示捕获的 PNG 图像
- 04将签名数据保存到 Dataverse
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ microsoft/ power-platform-skills --skill add-pen-input安装后在 Claude Code 中输入/add-pen-input确认已加载。
详细介绍
📋 共享说明:shared-instructions.md — 请先阅读。
工作目录: 在读取任何项目内容或执行任何命令之前,先执行
native-artifact-compatibility.md Step 0。
继承 /add-native 解析得到的绝对 working_dir;将每次 Shell 调用和文件工具绑定到该目录,即使此辅助程序从其他目录启动也一样。
添加手写笔输入
内部辅助程序。 用户应调用 /add-native pen-input、/add-native signature 或 /add-native @microsoft/power-apps-native-pen-input;/add-native 会在解析能力后路由到此处。
生成或验证原生手写笔输入封装,并展示如何调用其原生 React Native API。不要使用软件包 README 中的 HostingSDK / PCF 路径;那是用于其他场景的。
步骤
1. 验证应用
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
test -f app.config.js && test -f power.config.json && test -f package.json && test -d src || { echo "BLOCKED: working_dir is not an initialized app" >&2; exit 1; }
如果失败,请告知用户先运行 /create-mobile-app,然后停止。
2. 验证软件包是否已存在
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node -e "const p=require('./package.json'); const m='@microsoft/power-apps-native-pen-input'; if (!p.dependencies?.[m]) { console.error('MISSING: ' + m + ' is not in package.json. The template/app must already ship this native extension. This skill will not install it or edit native config.'); process.exit(1); } console.log('OK: pen input package present');"
如果检查失败,则停止。不要运行 npm install、npx expo install、pod install,也不要编辑 app.config.js。此软件包包含原生 iOS/Android 代码,必须已包含在应用的原生构建中。
2a. 协调请求的产物
在写入或复用之前,针对手写笔输入行阅读并执行 native-artifact-compatibility.md
中的步骤 1–3。继承 /add-native 当前的审批/模式;不要重复请求有效的限定范围审批。
检查 src/native/penInput.ts 是否包含 captureSignature、stripDataUriPrefix、
PenInputResult、请求的选项、PNG 数据 URI 输出,以及非错误的
USER_CANCELLED。除捕获功能外,也要检查已审批的 Image/File 负载要求:
缺少标准化器或未知的必需生成服务签名都不能忽略。缺少必需存储,或审批范围之外存在不兼容产物时,应向负责人返回 NEEDS_CONTEXT;独立运行时则应询问用户。
3. 编写或验证 src/native/penInput.ts
按照步骤 2a 对 src/native/penInput.ts 的判定处理:在请求创建且文件缺失时创建;仅在兼容时原样复用;或仅进行已审批的限定范围更新。
保留自定义代码、导出项和调用方;不要从示例覆盖现有内容。
封装必须:
- 返回判别联合类型,且绝不抛出异常。
- 用户取消时返回
{ ok: false, reason: 'USER_CANCELLED' };这属于非错误路径。 - 如果扩展已安装在 JS 中,但在原生构建中不可用,则返回
NATIVE_MODULE_MISSING。 - 成功时返回 PNG 数据 URI(
data:image/png;base64,...)。
// src/native/penInput.ts
import {
PenInputNative,
PenInputStatus,
PenInputErrorCode,
} from '@microsoft/power-apps-native-pen-input';
export type PenInputResult =
| { ok: true; dataUri: string }
| { ok: false; reason: 'USER_CANCELLED' | 'NATIVE_MODULE_MISSING' | 'CAPTURE_FAILED'; message?: string };
export async function captureSignature(options?: {
backgroundColor?: string;
strokeColor?: string;
strokeWidth?: number;
}): Promise<PenInputResult> {
if (!PenInputNative?.capturePenInput) {
return { ok: false, reason: 'NATIVE_MODULE_MISSING', message: 'Pen input module is not available in this build.' };
}
try {
const result = await PenInputNative.capturePenInput({
backgroundColor: '#ffffff',
strokeColor: '#0078d4',
strokeWidth: 2,
...options,
});
if (result.status === PenInputStatus.Ok && result.result) {
return { ok: true, dataUri: result.result };
}
if (result.error === PenInputErrorCode.UserCancelled) {
return { ok: false, reason: 'USER_CANCELLED' };
}
return { ok: false, reason: 'CAPTURE_FAILED', message: result.error };
} catch (error: any) {
return { ok: false, reason: 'CAPTURE_FAILED', message: error?.message ?? String(error) };
}
}
export function stripDataUriPrefix(dataUri: string): string {
return dataUri.replace(/^data:image\/png;base64,/, '');
}
4. 使用封装
供负责人参考的集成指南;此辅助程序不得编辑屏幕。
屏幕应导入封装,而不是直接导入原生软件包:
import { captureSignature } from '@/native/penInput';
const result = await captureSignature({
backgroundColor: "#ffffff",
strokeColor: "#0078d4",
strokeWidth: 2,
});
if (result.ok) {
setSignatureUri(result.dataUri);
} else if (result.reason === 'USER_CANCELLED') {
// User cancelled; do not show this as an app error.
} else {
console.warn("Failed to capture pen input:", result.reason, result.message);
}
使用标准 React Native 图像显示捕获的 PNG:
{signatureUri ? (
<Image
source={{ uri: signatureUri }}
style={{ width: "100%", height: 160 }}
resizeMode="contain"
/>
) : null}
备注:
- 结果是 PNG 数据 URI:
data:image/png;base64,...。 - 颜色输入支持
#RGB和#RRGGBB。 - 取消属于正常情况,会返回
USER_CANCELLED;屏幕应保持当前状态不变,并避免显示失败横幅。 - 仅将
@microsoft/power-apps-native-pen-input用于原生徒手绘图、墨迹、手写和签名捕获。对于无关的原生使用场景,请使用相关的 Expo 模块或package.json中已有的其他依赖。
5. 可选的 Dataverse 保存
可选指的是未被请求,而不是已批准保留后可以跳过。第 2a 步
会验证包装器的载荷支持和生成的签名;所有者需提供以下屏幕端的保存/
上传逻辑。若缺少由辅助函数负责的支持,或必需的存储方式未知,请返回
NEEDS_CONTEXT,而非仅捕获成功。
如果用户希望将签名保存到 Dataverse Image/File 列,请仅使用生成的服务。不要编写直接调用 Dataverse Web API 的代码。
Image 列模式:将数据 URI 标准化为生成的服务所需的图像载荷。如果需要原始 base64,请去掉前缀。
import { stripDataUriPrefix } from '@/native/penInput';
const signatureBase64 = stripDataUriPrefix(result.dataUri);
const update = await Cr123_evidenceService.update(id, {
cr123_signatureimage: signatureBase64,
cr123_signedat: new Date().toISOString(),
});
if (!update.success) {
showError(update.error?.message ?? 'Signature was not saved.');
}
File 列模式:先保存或更新父行,然后通过生成的服务辅助函数上传 PNG 字节/File。切勿将 File 列的字节放入 create/update JSON 请求体。
6. 类型检查
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
npx --no-install tsc --noEmit
仅修复范围内的辅助函数错误,然后执行共享兼容性契约的 第 4 步。重新检查请求的捕获/标准化/存储行为,包括用户 取消、缺少原生模块、捕获失败,以及 Image 与 File 载荷。 仅类型检查成功还不够;不要修改屏幕/生成的文件。
7. 原生重建说明
此技能不会安装原生代码。如果刚刚在技能流程之外添加了该包,应用需要在此工作流之外进行原生重建。如果该包已在构建中,则对包装器的修改使用 Metro 热重载即可。
8. 不要使用 HostingSDK / PCF
不要导入或注册:
import { PenInputExtension } from "@microsoft/power-apps-native-pen-input";
不要接入 Companion PCF 或 PenInputExtension。在 Power Apps 原生代码应用中,请使用上文的原生 React Native API。
9. 总结
在此总结之前,返回共享兼容性结果以及实际创建/更新/复用的路径。 分别报告所有者端的保存/集成情况;仅在成功后更新 memory-bank,并在编排场景中将最终更新留给所有者。
告知用户:
Pen input added
Package present : @microsoft/power-apps-native-pen-input
Wrapper : src/native/penInput.ts
Output : PNG data URI
Type-check : PASS
Native rebuild : not performed by this skill
Usage : captureSignature(...)
HostingSDK / PCF : not used
在 Controls 下更新 memory-bank.md:
- Pen input added — @microsoft/power-apps-native-pen-input (<ISO date>)