仓库管理(扫码出入库)技能 1.2
> 装了这个技能 = 在飞书 / 钉钉 / 企业微信任意一个平台得到一套完整 WMS:扫码出入库、多仓多批次、审批生效闸门、自动补库存行、低库存/效期预警、审批卡片三按钮、经营看板。核心规格平台无关(§2–§7),平台落地看适配器(§0 索引 + §11)。全部脚本、配方与模板随包附带,已在三平台真实生产环境验证。
0. 你能得到什么
scripts/BUILD_WMS.md:一键复建 13 张表 + 126 基础字段 + 18 关联 + 85 公式 + 3 Lookup + 仪表盘 9 图表scripts/GEN_QR.md:产品条码批量生成二维码写入附件列- 工作流配方库(本文 §5):9 条自动化的完整 JSON 结构要点,含审批卡片【生效/驳回/查看详情】按钮
- 引擎坑位库(本文 §4):飞书公式/工作流引擎 12 个已验证限制与绕法,价值最高的部分
assets/:架构图与业务流程图样例(注意:二进制图片被 SkillHub 客户端禁止上传,仅本地安装包包含;SkillHub 包内以本文 mermaid/文字描述为准)adapters/dingtalk/:钉钉 AI 表格适配器(README + 审批卡片 DSL 模板 + 文本 join 键补建库存行 DSL 模板)——目标平台是钉钉时读这里,跳过 §4 飞书坑位adapters/wecom/:企业微信智能表格适配器(README + 审批轮询 cron 模板)——企微无自动化引擎,闭环靠定时任务补偿
0.5 第 0 步:平台选择弹窗(先于一切操作,强制流程)
当本技能被触发、且用户消息中没有明确指定目标平台时,Agent 必须先调用 AskUserQuestion 工具弹出单选问题「你想在哪个平台搭建仓库管理系统?」,提供三个选项及说明:
- 飞书 · 多维表格 —— 全流程脚本现成(§1–§7 +
scripts/BUILD_WMS.md一键复建),适合已在用飞书的团队 - 钉钉 · AI 表格 —— 自带审批自动化:生效/驳回卡片按钮、补建库存行、快照/预警工作流(走
adapters/dingtalk/) - 企业微信 · 智能表格 —— 公式引擎最强、API 写入最顺;无原生自动化,审批提醒用定时任务补偿(走
adapters/wecom/)
规则:
- 用户已明确平台,或消息中出现平台特征(飞书分享链接、dingtalk.com/alidocs 链接、doc.weixin.qq.com 链接)时跳过弹窗,直接路由
- 做出选择后只执行该平台流程;本文档其他平台的命令、字段格式、ID 一律不得混用(平台差异速查见 §11)
- 连接器检测:获取付费方案后、搭建前,必须先检测目标平台 CLI 可用性(§1.1)。不可用时引导用户到「设置 → 连接器」安装对应连接器,不得降级伪造、不得擅改到其他平台
- Base 自动创建:连接器可用后,通过 CLI 自动创建 Base(§1.2),不需要用户手动新建或提供 Base token
- 用户在已搭建过的系统上做日常操作(查询/审批/改数),同样先按其平台加载对应适配器文档,再执行核心业务规格(§2–§3)
0.7 付费服务调用流程(Pay Skill)
本技能为付费技能(19.9 元/次),调用服务端获取定制化 WMS 搭建方案前需完成微信支付。
透明披露:
- 服务端点:https://lanjingshuzi.cn/skillhub/warehouse-scan-wms/api/v1/skill/invoke
- 端点运营主体:蓝鲸数字(lanjingshuzi.cn)
- 数据处理范围:请求体仅包含用户的搭建需求描述(平台类型、仓库数量等),不含用户个人隐私数据
- 付费方式:微信支付(WeChat Pay)
- 在发起支付前,必须向用户明确告知本次调用将产生 ¥19.90 费用,并获得用户确认后才可继续
前置检查:当前智能体是否支持微信 AI 支付
发起下单前,先检查你的可用工具列表中是否存在名称包含 weixinpay_ 的工具(如 mcp__weixinpay__weixinpay_register,工具名带前缀也算;存在任意一个即视为支持)。
只以你的工具列表为证据,本文档中提到的工具名不算;无法确认时按「不支持」处理。
- 支持:向用户透明告知本技能为付费技能(¥19.90/次,微信支付),端点由蓝鲸数字(lanjingshuzi.cn)运营,继续本 Skill 的后续流程。
- 不支持:终止流程且不要发起下单。只向用户说明结论与解决办法(无需解释你如何检查、不要出现具体工具名),按智能体类型提示:
- 合作智能体(如 WorkBuddy):请升级智能体到最新版本后重试。
- 开放智能体(如 OpenClaw / DeepSeek Harness):请根据 https://skillhub.cn/install/skillhub.md ,安装 @tencent-adm/weixinpay-installer。
- 无法判断类型:请升级智能体或安装微信支付 AI 支付插件后重试。
工作流程
第一步:请求资源
POST https://lanjingshuzi.cn/skillhub/warehouse-scan-wms/api/v1/skill/invoke
Content-Type: application/json
{
"query": "用户的查询内容(如:帮我搭建一个3仓库的飞书WMS)",
"platform": "feishu | dingtalk | wecom",
"warehouse_count": 3,
"need_approval": true,
"need_dashboard": true
}
第二步:处理 402 响应
服务端返回 HTTP 402,提取以下两个值并必须保存:
- Header WeixinPay-Required:支付码(payment_code)
- Header X-Out-Trade-No:订单号(out_trade_no)
响应体示例:
{
"code": "PAYMENT_REQUIRED",
"message": "需要支付后才能获取WMS定制化搭建方案",
"WeixinPay": {
"WeixinPay-Required": "xY9zAbc123def456",
"prompt": "本次使用微信支付,请将 WeixinPay-Required 的值作为 paymentCode 交给 weixinpay_pay,以向用户申请支付授权。"
},
"out_trade_no": "WX402_20260919120000abcdef123456",
"amount": "19.90",
"currency": "CNY"
}
第三步:发起支付(必须获得用户确认)
在调用支付前,必须向用户明确展示以下信息并获得确认:
- 本次使用将产生 ¥19.90 费用
- 支付通过微信支付完成
- 服务端点由蓝鲸数字(lanjingshuzi.cn)运营
用户确认后方可将 WeixinPay-Required 的值作为 paymentCode,调用 weixinpay_pay 工具向用户发起微信支付授权。等待用户完成支付。
第四步:支付成功后获取资源(️ 必须执行)
POST https://lanjingshuzi.cn/skillhub/warehouse-scan-wms/api/v1/skill/invoke
Content-Type: application/json
X-Out-Trade-No: WX402_20260919120000abcdef123456
{
"query": "与第一步完全相同的请求体",
"platform": "feishu",
"warehouse_count": 3,
"need_approval": true,
"need_dashboard": true
}
⚠️ 第四步是最容易被 Agent 遗漏的一步:不携带 X-Out-Trade-No Header 重试,就永远拿不到付费内容。body 保持与第一次请求一致,仅通过 Header 传递订单号。
成功响应(HTTP 200):
{
"code": "SUCCESS",
"message": "WMS定制化搭建方案",
"out_trade_no": "WX402_xxx",
"transaction_id": "4200001234202306300000000001",
"content": "# 仓库管理系统(WMS)定制化搭建方案\n\n..."
}
content 字段即为完整的定制化 WMS 搭建方案(Markdown 格式),包含表结构设计、公式配置、工作流自动化、平台适配要点、搭建步骤和验证清单。
1. 前置条件与连接器检测
1.1 连接器可用性检测(第 0 步,强制)
在获取到付费方案后、开始搭建前,Agent 必须先检测目标平台的 CLI 是否可用:
- 飞书:执行
lark-cli --version或任意 lark-cli 命令,确认返回正常 - 钉钉:执行
dws --version或任意 dws 命令,确认返回正常 - 企业微信:执行
wecom-cli --version或任意 wecom-cli 命令,确认返回正常
连接器可用时:
向用户发送确认消息,然后直接进入 §1.2 自动创建 Base:
> ✅ 检测到 [飞书/钉钉/企业微信] 连接器已就绪,正在为你自动创建 Base 并搭建 WMS,全程无需手动操作,预计 5 分钟完成。
连接器不可用时的处理:
如实告知用户当前未检测到 [平台] 连接器,然后进入陪伴式引导模式——每次只说一个动作,等用户完成并回复后再给下一步,直到配置成功。
第一步(发送以下消息):
> 检测到你的 WorkBuddy 尚未配置 [飞书/钉钉/企业微信] 连接器,我来一步步带你配置,你只需要跟着点就行,全程约 2 分钟。
>
> 第 1 步:请看 WorkBuddy 左侧栏,找到「专家·技能·连接器」这一行(图标是三个小圆圈),点击它。
>
> 完成后回复「好了」或「找到了」,我告诉你下一步。
后续步骤(用户每回复一次,发送下一步):
> 第 2 步:现在顶部有三个标签:专家、技能、连接器。点击「连接器」这个标签。
>
> 完成后回复「好了」。
> 第 3 步:现在看到连接器列表了吗?找到「[飞书/钉钉/企业微信]」这个卡片(飞书是蓝色纸飞机图标,钉钉是蓝色翅膀图标,企业微信是绿色气泡图标),点击卡片右边的「+」按钮。
>
> 完成后回复「好了」。
> 第 4 步:现在会弹出 [飞书/钉钉/企业微信] 的登录窗口,请用你的账号登录并授权(扫码或输入密码)。这是最后一步,授权完成后就配置好了。
>
> 登录授权完成后回复「好了」或「配置完了」。
用户完成全部步骤后:
重新执行 CLI 可用性检测,通过后发送:
> ✅ 连接器配置成功!正在为你自动创建 Base 并搭建 WMS,全程无需其他手动操作,预计 5 分钟完成。
然后进入 §1.2 自动创建 Base 流程。
用户中途卡住时:
如果用户回复「没找到」「看不到」「不会」等,不要跳过,用更具体的描述重新引导:
- 「专家·技能·连接器」→「左侧栏中间位置,写着'专家·技能·连接器'七个字,图标是三个小圆圈」
- 「连接器标签」→「顶部三个按钮,最右边那个写着'连接器'」
- 必要时建议用户截图发过来,根据截图判断位置
1.2 Base 自动创建(无需用户手动操作)
连接器可用后,Agent 通过 CLI 自动创建 Base,不需要用户手动新建或提供 Base token:
- 飞书:
lark-cli base +base-create --name 仓库管理系统V2,从输出中提取 Base token - 钉钉:
dws aitable create --name 仓库管理系统V2,从输出中提取 Base token - 企业微信:
wecom-cli smartsheet create --name 仓库管理系统V2,从输出中提取 Base token
创建成功后告知用户 Base 已就绪,直接进入搭建流程。
2. 三步快速开始
- 按 §1.1 检测连接器 → 按 §1.2 自动创建 Base(用户零手动操作)
- 按
scripts/BUILD_WMS.md手册逐步执行 —— 约 5 分钟建完整套表结构与看板 - 按 §5 配方创建 9 条工作流并
+workflow-enable(审批通知 4 条 + 补建库存行 2 条 + 预警/快照 3 条) - 维护主数据:产品信息(含条码)→ 仓库信息 → 批次信息; thereafter 日常操作见 §6
3. 架构与核心逻辑
五层:基础数据(产品/仓库/批次)→ 业务单据(入/出/调/盘 主单+明细)→ 库存核心(当前库存=公式实时算 + 每日快照)→ 自动化 → 可视化。见 assets/architecture.jpg。
库存公式:当前库存数量 = 累计入库 − 累计出库 + 调拨调入 − 调拨调出 + 盘盈 − 盘亏;六个累计均 FILTER 明细表且仅统计单据状态=已生效,按 仓库+产品 匹配(批次维度可选加)。
审批状态机:草稿 → 待审批 → 已生效(库存才变化)/ 已驳回(可改后重提)。审批入口 = 飞书卡片按钮,见 §5.1。
条码驱动:明细表扫「产品编码(条码)」→ 7 字段自动回填 → 金额自动算 → 主单自动汇总;操作员只填数量和批次。
自动补库存行:入库/调拨明细的父单生效时,若当前库存无「产品×仓库」行则 FindRecord 判空后 AddRecord 自动创建。
4. 引擎坑位库(改动前必读,全部实战验证)
公式引擎
- link 字段名 == 表名 →
[X].[Y]被解析为整表列:汇总列每行同值、引用列显示全表清单。修复=改 link 名(如 入库明细/关联入库单)+ 重写引用公式。本技能 links.jsonl 已用安全命名。 - FILTER 内
CurrentValue.[link].[field]二级链不支持(静默变[无效引用]);三级链[link].[link].[field]也不支持。跨表取父单字段用两段二级链辅助字段:父单加入库仓库名称=[入库仓库].[仓库名称]、入库单状态=[关联入库单].[单据状态];明细用[关联入库单].[入库仓库名称]。formulas.jsonl 已内置该模式。 - 比较两侧表示必须一致:link 引用渲染为主键文本 vs 名称文本永远不匹配 → 辅助字段统一返回名称文本。
- 直接二级链
[link].[字段]可用;SUM([link字段].[数量])即按关联明细求和(主单汇总的正确写法)。
工作流引擎
- SetRecordTrigger 对公式字段加 operator/value 过滤运行时永不触发(option 只存 name 不解析 id)。正确姿势:watch 字段不带值 + IfElseBranch 内用 link 钻取父单真实 select(
$.trigger.fldLink.fldSelectis option{id})做状态门。 $.findStep.recordNum数字比较(is 0)可用("数字分支不可用"仅限公式字段引用);children.links 只给 if_true 可以。- 消息按钮自包含:
btn_list[{text,btn_action:"setRecord",record_values:[{field_name,value:[option{id}]}]}]改触发记录;btn_action:"openLink",link:[text+ref]跳转,ref 可插值$.trigger_1.recordId。Action 节点不要设 children。 - 选项 id 获取:field API 不返回 id;用一条停用诊断工作流 round-trip(update 写 option{name} 再 get 读回 id)。
- 触发器只对"修改"生效;新建即满足条件的记录不触发。
- workflow create 需唯一 client_token;新建默认 disabled 必须 enable;update 保留启停且无需 client_token;平台无 delete,诊断流只能 disable。
CLI/平台
- 中文 JSON 一律 Write 到 CLI 解析目录后
--json @./f1.json;批量用 JSONL +printf '%s'字节透传;table-list/field-list/record-list 串行。 +record-batch-create列式{"fields":[...],"rows":[[...]]};link 单元格[{"id":"recXXX"}];+record-upload-attachment --file与+record-download-attachment --output的相对路径也基于 CLI 解析目录。
5. 工作流配方库
5.1 审批提交通知(入/出/调/盘各一条)
SetRecordTrigger(主单表, watch 单据状态, 不带值, 条件在 branch) → LarkMessageAction:receiver=ref($.trigger_1.<审批人fld>);title/content 含 ref($.trigger_1.<编号fld>);btn_list=[{生效: setRecord 单据状态=option{已生效id}}, {驳回: setRecord=option{已驳回id}}, {查看详情: openLink link=[text 基址?table=tblXX&record=, ref $.trigger_1.recordId]}]。
5.2 生效自动补建当前库存行(入库/调拨各一条)
SetRecordTrigger(明细表, watch 状态辅助字段, 不带值) → FindRecord(当前库存, 产品编码==ref(trigger.产品编码) && 仓库==ref(trigger.入库仓库或调入仓库), should_proceed_when_no_results:true) → IfElse(recordNum is 0) if_true→ FindRecord(产品信息, 产品编码(条码)==ref(trigger.产品编码)) + FindRecord(仓库信息, 仓库名称==ref(trigger.仓库公式)) → AddRecord(当前库存: 产品关联=ref($.findP.firstfieldsRecord.recordId), 仓库关联=ref($.findW.firstfieldsRecord.recordId), 批次关联=ref(trigger.批次关联))。
5.3 低库存预警 / 批次效期预警 / 每日快照
SetRecordTrigger(当前库存.当前库存数量) → LarkMessage 提醒核对预警线;TimerTrigger 每日 09:00 → FindRecord(批次信息, 有效期至 isGreaterEqual today) → 消息;TimerTrigger 每日 23:00 → AddRecord(库存每日快照)。
6. 日常操作 Playbook(摘要)
- 入库:建单(类型/仓库) → 明细扫码+数量+批次 → 状态待审批 → 审批人卡片点生效
- 出库:同上 + 看「当前可用库存」列 + 先入先出选批次
- 调拨:调出/调入仓不同;生效即两仓同变,调入仓无行自动补建
- 盘点:明细自动列「账面当前库存」;实盘>账面填盘盈、<填盘亏,只填一列
- 排障第一问:库存没变?→ 单据状态是否已生效
7. 验证清单(改公式/工作流后)
- field-list 读回表达式无
[无效引用] - 主单汇总列每行不同且列合计=明细全表合计
- 明细父单引用列每行单值
- 当前库存对应行数量非零且与手算一致
- lookup 列在组合对齐时非空
- 工作流改状态触发后 record-list 看副作用;卡片实收确认按钮渲染
8. 安全与隐私
包内不含任何密钥、token、租户私有 ID;所有操作以使用者自身飞书身份授权执行;脚本仅做最小必要读写。实例化后的 Base 权限由使用者自行管理。
9. 更新
见 CHANGELOG.md;语义化版本,minor=新增能力,patch=修坑。
10. SkillHub 上架与打包踩坑记录(2026-09-17 实测)
10.1 zip 打包三条铁律
- 条目路径必须正斜杠。PowerShell
Compress-Archive在 Windows 上写入反斜杠条目(scripts\build_wms.sh),SkillHub 客户端会将嵌套条目判为「文件路径不安全」并跳过,只剩根级文件。.NET ZipFile::CreateFromDirectory在 Windows 上同样写反斜杠。 - tar 的 zip 不能用:
tar -a -c -f x.zip产物为正斜杠但 JSZip 报Can't find end of central directory,直接解析失败。 - 正确做法:先
Compress-Archive生成 JSZip 兼容包,再用 .NET 逐条目复制到新 zip 并把FullName.Replace('\','/')作为条目名(见下例)。
Compress-Archive -Path <skilldir>\* -DestinationPath tmp.zip -Force
$za=[IO.Compression.ZipFile]::OpenRead("tmp.zip"); $zo=[IO.Compression.ZipFile]::Open("out.zip",'Create')
foreach($e in $za.Entries){ $ne=$zo.CreateEntry($e.FullName.Replace('\','/')); $s=$e.Open(); $d=$ne.Open(); $s.CopyTo($d); $d.Dispose(); $s.Dispose() }
$zo.Dispose(); $za.Dispose()
10.2 文件类型白名单
- 服务器 400 拒绝无扩展名文件:
file type not allowed: LICENSE。许可证声明放 SKILL.md frontmatter 的license字段,不要带 LICENSE 裸文件。 - 客户端跳过二进制文件(jpg/png 等,提示「禁止上传二进制文件」)。示意图改用文字/mermaid 描述放在 SKILL.md 内。
- 实测可过:
.md .json .jsonl .sh。
10.3 浏览器自动化上传坑(人工上传可忽略)
- Chrome 后台标签不弹文件选择框:先 OS 点击该标签页激活,再点「选择 zip 文件」。
- 千问办公顶部「正在操控您的电脑」黑条遮挡页面上部点击:先
scrollIntoView({block:'center'})把目标元素移出顶部再点。 - 文件树每行的删除按钮(class 含
p-0.5的空 svg button)与图标选项按钮外观相似,不要全局匹配点击,务必限定作用域,否则会误删已选文件。 - 图标选择网格需先点开下拉才渲染;选择后占位符检查可能失真,以提交结果为准。
10.4 React 受控表单与报错捕获
- 输入框设值:
Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,'value').set.call(el,v)后dispatchEvent(new Event('input',{bubbles:true})),直接赋.value不生效。 - 提交失败 toast 仅显示「提交失败」无细节:monkey-patch
window.fetch记录响应 body,才能看到真实错误(如文件类型拒绝)。
10.5 提交与审核
- 接口
POST https://api.skillhub.cn/api/v1/orgs/{orgId}/skills,返回 201 即提交成功,reviewStatus/contentAuditStatus/securityScanStatus=pending表示进入安全扫描+内容审核;通过后自动上架。 - 审核进度在「我的 Skills」查看;被拒时
reviewRejectReason给原因。 - 升级:bump 版本号 + 变更说明 + 重传 zip 提交新版本;旧版本保留可回退。审核中的版本不要重复提交同版本号。
11. 多平台适配器路由(v1.2 新增,三平台均生产实测)
同一份核心规格(§2 表结构、§4 公式模式、§5 工作流配方)在三个平台的落地差异速查:
| 能力 | 飞书多维表格 | 钉钉 AI 表格 | 企业微信智能表格 |
|---|---|---|---|
| 工具 | lark-cli(§1–§7 全流程脚本现成) | dws aitable(adapters/dingtalk/) |
wecom-cli smartsheet(adapters/wecom/) |
| 跨表按值聚合 | lookup+filter 公式(§4 坑 1/2 全在此) | filterUp 字段 | lookup 字段(valueType=列对比)+ formula FILTER |
| 台账条件求和 | 公式内 FILTER | filterUp filters(join 键必须指原始 text 列) | 表.FILTER(cur.字段=本记录字段).列.SUM() 原生支持 |
| API 行的公式重算 | 正常 | 不重算:需 field update 原样重存 config 唤醒(README 坑 1) | 正常 |
| 自动化/审批卡片 | workflow + 卡片按钮(§5) | workflow-dsl/v1 + updateRecord 按钮(模板齐) | 无自动化:cron 轮询+机器人推送补偿(模板齐) |
| 工作流写关联字段 | 可以 | 不可以(静默丢弃)→ 文本 join 键方案(模板齐) | 可以(record_id 格式) |
| 条码列 API 写入 | 可以 | barcode 列不自动求值 | 可以(直接字符串) |
| 图片/附件 API 写入 | 可以 | 可以(+attachment-put) | attachment 列有域名白名单 → 用 image 列 |
| 对账 SQL | 无 | psql 只读 | records query(支持 JOIN) |
选平台建议:要开箱自动化选钉钉或飞书;要公式最省心、纯 API 写入选企微(注意配 cron)。每平台适配器的坑位清单与模板见对应 README。