SKILL.md 16 KB


name: kdshrpmsg description: >- Design and implement Kingdee EAS/SHR workflow todo and to-be-read message push to external portals or Weaver/Fanwei via MessageWebServiceDao. Use for 待办, 待阅, PORTAL-002/003/006/007/011/012/013, OAMessageWebServiceDao, WeaverMessageWebServiceDao, BMCMessage, assignReadRecord, receiveOAConfig, BaoYPro, Weaver, ReceiveTodoRequestByJson, weaverTodoConfig, pcurl entryPath, or ESB portal message integration on Kingdee SHR. BEFORE coding: ask intake questions in this skill (channel, API, identity, deep link, config file).

When user says 上线/切生产/go-live: follow Go-live section with kdshrsso; update weaverTodoConfig host/credentials/shrServerName/sso.appId.

Kingdee SHR Portal Message Push (待办 / 待阅)

Reusable pattern from YHPro (玉湖,已测通) and BaoYPro (报业 / 泛微统一待办). Do not copy secrets; adapt per customer.

Related SSO deep-link entry: skill kdshrsso (BaoYPro: Option B-qy /qy/auth/weaver/app.do).

Coding discipline (do not guess platform getters / uncertain fields): skill kdshr-dev.


Agent intake — ask before coding (mandatory)

When implementing 待办 / 待阅 for a new project or new channel, do not start coding until goals are confirmed. Ask in one batch. If SSO is in the same delivery, run kdshrsso intake first (or together).

Must confirm (block if unanswered)

  1. 渠道: 泛微统一待办 / YH 门户 PORTAL-* / 钉钉 / 飞书 / 其他?接口文档是否已提供?
  2. 范围: 只要待办,还是待办+待阅(BMC)?是否只要推送、SSO 已另做?
  3. 鉴权: OpenAPI token / HTTP Basic / 其他?凭证放哪份 properties(勿与无关渠道混文件)?
  4. 人员: 推送接收人字段 = 工号 / 手机 / 对方 userid?与 sHR 哪一列对齐?
  5. 幂等键: 对方如何判重(如 Weaver:syscode+flowid+workflow+receiver;YH:taskId)?flowid 是否用 procInstId
  6. 深链: 绝对 URL 还是相对路径?SSO 入口(须与 kdshrsso 一致,如 /qy/auth/weaver/app.do)?审批页 path?
  7. SPI: 新建独立 *MessageWebServiceDao,还是 Router fan-out 多渠道?默认 独立 Dao + enabled 开关,少动已上线渠道。

Should confirm (sensible defaults)

  1. 配置命名:泛微继续 weaverTodoConfig.properties;钉钉/飞书用 dingtalkTodoConfig / feishuTodoConfig不要改名合并成一个大文件。
  2. 状态机:待办/已办/删除/办结/待阅 与对方字段映射(Weaver isremark 等)——无文档则先按 weaver-baoy-plan 草案请用户改。
  3. CallLog / 失败补推是否要做;WF 延迟(如 wf.delayMs)经验值。
  4. 与 SSO 是否同期:深链入口必须已存在或同期交付(否则只推链接无法点开登录)。
  5. 配置文件是否齐:对照下方「配置文件清单」——set-server-envintegration-configweaverTodoConfigWSConfig.xml、login/logout JS、DDL/jar;缺哪项就问「本项目要不要配」。

Output before coding

给出 目标确认表:渠道、配置文件名(含清单勾选)、SPI 策略、深链模板、人员字段、状态映射来源。用户确认后再改代码。用户说「按报业/按 BaoYPro」时可复述默认假设请一次确认。


配置文件清单(必配 / 防漏)— 新项目与切环境通用

待办/待阅(尤其 Weaver + SSO)时,Agent 必须对照下表逐项核对;其他项目若漏配,要主动列出并问用户「是否需要配置」,不得默认跳过。

与 SSO 重叠项同时对照 skill kdshrsso Go-live。总清单见项目 docs/integration/go-live-prod.html

A. 服务端配置(按环境区分 test/prod)

# 文件(相对 EAS_HOME 用途 关键须改的关键项 新项目是否要
1 server/bin/set-server-env.sh(或 Windows 等价) 选读哪份 integration JSON ENV=test\|prodINTEGRATION_CONFIG_PATH (有 SSO/qy 时)
2 server/properties/integration-config-{env}.json SSO OAuth、SHR、泛微 ecology shrServerNamedataCenterallowedPrefixesappId/appSecretcallbackUrlweaver.ecologyUrl (有 SSO 时)
3 server/properties/{客户}/weaverTodoConfig.properties 待办 OpenAPI + 待阅 sendMsg openapi.host、凭证、syscodeshrServerNamesso.appIdnotify.moduleId/eventId/tenantKey (有 Weaver 待办/待阅时)
4 server/profiles/server1/config/portalConfig/WSConfig.xml 平台消息 SPI 注册 <path>=Dao 全类名;<dataCenter>=账套(与 json 一致 (走 MessageWebServiceDao 时)
5 server/properties/{客户}/weaverTodo-ddl.sql CallLog / assignReadRecord 生产库是否已建表 首次上线要执行

报业示例目录名 baoye/;其他客户换自己的 properties 子目录,不要把多渠道揉进一个文件。

B. 前端 / 门户静态脚本(有 SSO 联邦登录/退出时)

# 文件 用途 关键项
6 server/deploy/eas.ear/sso_web.war/common/js/login_withForm.js 门户进 SHR SSO ENV_CONFIG.prod.*getCurrentEnv() 识别生产 Host
7 server/deploy/easweb.ear/shr_web.war/scripts/gui/logoutHR.js 退出转泛微 currentEnv / 生产 ecologyUrl(或按 host)

C. 部署物(非 properties,但常漏)

# 说明
8 二开 jar(如 weaverTodo / qy 相关) 放入 lib/sp 等,仅改配置不部署代码无效
9 qy.war context=/qy SSO 入口与 callback 依赖
10 泛微后台 callback 注册、退出白名单、异构 syscode/IP、消息中心 module/event 规则

Agent 防漏话术(强制)

  • 新项目 intake:在确认表里列出上表 A+B,标「本项目需要 / 不需要 / 待确认」。用户未表态的,先问再写代码
  • 切生产 / 覆盖包:逐文件核对是否仍为测试值(常见漏项:WSConfig.xmldataCenternotify.moduleId/eventIdENV=prodlogoutHR currentEnv)。
  • 只做待办不做 SSO:仍要问 WSConfig + weaverTodoConfig;可标 login/logout/integration-config 为「本期不做」。
  • 只做 SSO 不做待办:转 kdshrsso;仍提醒若后续接待办需补 3、4、5。

报业(BaoYPro)正式环境快照(参考,勿照抄到别的客户)

SHR https://hr.szpgm.com/shr
泛微 OpenAPI http://172.16.37.23:20600
dataCenter SNG(json WSConfig 一致)
notify tenant=t6srq5l4vh module=100011 event=241221
覆盖包 D:\workcode\baoye\patch\正式单点部署(测试包:...\test单点部署

Go-live / 切生产 (with kdshrsso)

When user says 上线 / 切生产, coordinate with kdshrsso Go-live, and walk the 配置文件清单 above (do not only edit weaverTodoConfig).

Key production fields for Weaver todo/notify (weaverTodoConfig.properties):

Key Set to production
weaver.openapi.host 生产 OpenAPI/ecology
weaver.corpid / app_key / app_secret 生产开放平台
weaver.syscode 生产已注册标识
weaver.shrServerName 生产 SHR(redirect)
weaver.sso.appId integration-config-prod.json 中 appId 一致
weaver.sso.entryPath 通常仍 /qy/auth/weaver/app.do
weaver.notify.tenantKey 按客户(报业 t6srq5l4vh
weaver.notify.moduleId / eventId 按环境(报业生产 100011 / 241221;测试 139141 / 287602

Also must set: ENV=prodintegration-config-prod.jsonWSConfig.xml <dataCenter>、login/logout JS。
Full checklist: project docs/integration/go-live-prod.html
报业生产 SHR:https://hr.szpgm.com/shr


When to use

Scenario Fit
Push workflow 待办 to enterprise portal / OA Yes
Push BMC 通知/待阅 to portal Yes
Portal APIs match YH PORTAL-* REST + HTTP Basic + ESB envelope Yes
Weaver/Fanwei/统一待办中心 (BaoYPro) via ReceiveTodo API Yes — see weaver-baoy-plan.md
Only DingTalk/Feishu, no portal Partial — separate channel + config file; skip PORTAL-* / Weaver receive
Replace product message center entirely No

Quick decision

Need portal sync for SHR workflow/messages?
  │
  ├─ Implement MessageWebServiceDao (platform SPI) — NEVER invent a parallel push framework
  │     ├─ Todo: addMessage / addCompletedMessage / removeMessage
  │     └─ ToBeRead: updateMessages(id, MsgStatus, ctx)
  │
  ├─ Downstream?
  │     ├─ YH-style ESB PORTAL-* → TodoMessageServer + receiveOAConfig
  │     └─ Weaver E10:
  │           ├─ 待办 → receiveRequestInfo(weaverTodo + weaverTodoConfig)
  │           └─ BMC 通知/待阅 → 消息中心 sendMsg(勿再用 isremark=8)
  │
  ├─ Deep link back to SHR?
  │     ├─ Weaver: relative /qy/auth/weaver/app.do?appId&redirect=approveAbs (kdshrsso B-qy)
  │     ├─ Future DingTalk/Feishu: that platform SSO entry + same approveAbs
  │     └─ Never rely on Unified /auth/app + UA for PC Weaver todos
  │
  └─ Config naming
        ├─ Keep weaverTodoConfig.properties for Weaver only (do not mega-rename for BY)
        └─ Later: dingtalkTodoConfig.properties / feishuTodoConfig.properties

Adapter targets (YH vs BaoY)

Project Downstream API style
YHPro Enterprise portal ESB Multiple PORTAL-* URLs
BaoYPro Weaver / Fanwei / eteams One receiveRequestInfo (+ OpenAPI oauth)

Reuse YHPro SPI/hooks idea; replace HTTP payload and status fields. Detail: weaver-baoy-plan.md

BaoYPro:BMC 通知 / 待阅 → 消息中心 sendMsg(测试已通过

不再走统一待办 receiveRequestInfo / isremark=8。实现类:WeaverToBeReadMessageServer + WeaverSendMsgClient

约定
接口 /papi/openapi/api/mc/msg/sendMsgweaver.openapi.sendMsgPath
人员 只要 workCode,不传 employeeId
发送人 BMCMessageInfo.getSenderId()getUserByIdUserInfo.getNumber() / getName()
接收人 getReceiver()resolveReceiverWorkcode
title getTitle()
text getBody();空则回退 title
todo false;已读不回写泛微
entity.pcUrl 有 BMC url 才传(SSO 相对入口)
channels 默认 [1](IM)
配置 weaver.notify.tenantKey / moduleId / eventId / channels
环境固定参数 测试:tenant=t6srq5l4vh module=139141 event=287602;生产:tenant=t6srq5l4vh module=100011 event=241221(切环境只改 properties,勿混用)
配置热加载 WeaverTodoConfig 按文件 mtime 重载,改 notify 参数一般不用重启
日志前缀 待办 [WEAVER-TODO];待阅 [WEAVER-TOREAD](含 WeaverSendMsgClient
CallLog OAMsgCallLogOperType=通知发送RequestUrl=host+path(不含 token);ResponseResult=对方完整 JSON
OpenAPI token JVM 级缓存(跨多次 new Dao);authorize 遇 Sentinel/-10 有限次退避重试

SPI:updateMessages(UNREADED) → sendMsg;addMessagetype 含「通知」→ 跳过(避免再推 isremark=0)。

BaoYPro:新增待办与 wf.delayMs 执行顺序(勿颠倒

旧错法:先 sleep(wf.delayMs) 再查 AssignmentId —— sleep 期间若任务撤回,AssignRead 已空,会误报 assignId 为空。

正确顺序(WeaverTodoMessageServer.addMessage):

  1. 短轮询拿 AssignmentId(waitAssignIdByMsgId,预算约 wf.delayMs,步进 500ms)
  2. assignId / procInstId 为空则直接放弃并打 CallLog
  3. 解析人、标题、拼 pcurl
  4. saveAssignRecord 先落本地关联
  5. delayForWf()(整段 wf.delayMs),让「待办转已办」等并发先落定
  6. 最后 receiveRequestInfo 推 isremark=0

已办/删除路径可先 delayForWf() 再查库(与新增不同)。配置项:weaver.wf.delayMs(报业常用 8000)。

Coding discipline:skill kdshr-dev


Architecture (reference layout)

YHPro

platform workflow / BMC
  → XxxMessageWebServiceDao
  → Todo / ToBeRead servers → PORTAL-*
  → MessageCommonUtil (Basic + JSON)

BaoYPro (Weaver)

platform workflow
  → WeaverMessageWebServiceDao
  → WeaverTodoMessageServer
  → WeaverReceiveTodoClient (OpenAPI token + receiveRequestInfo)
  → pcurl from WeaverTodoSupport (entryPath + appId + redirect)

platform BMC 通知
  → WeaverMessageWebServiceDao.updateMessages(UNREADED)
  → WeaverToBeReadMessageServer
  → WeaverSendMsgClient (同 OpenAPI token + sendMsg)

Config: {EAS_HOME}/server/properties/baoye/weaverTodoConfig.properties
Key: weaver.sso.entryPath (default /qy/auth/weaver/app.do) + weaver.sso.appId;通知另见 weaver.notify.*


Platform SPI map (MessageWebServiceDao)

Method YH PORTAL Weaver 待办 isremark BaoYPro BMC 通知
addMessage 002 0(type 含「通知」则跳过)
addCompletedMessage 006 then 003 2; flow end → 4
removeMessage 007 -1
updateMessages 011 / 012 (历史方案 isremark=8,BaoY 不用 sendMsg(未读);已读不回写

Implementation checklist (new project)

- [ ] 1. Downstream API doc + env + auth
- [ ] 2. Person mapping field (工号 / cfidmusercode / …)
- [ ] 3. MessageWebServiceDao facade + servers
- [ ] 4. Per-channel properties (weaverTodoConfig / receiveOAConfig / …)
- [ ] 5. assignReadRecord / CallLog
- [ ] 6. Register SPI in product
- [ ] 7. BMC hook if 待阅 needed
- [ ] 8. PC URL: SSO wrap (kdshrsso) + approve page
- [ ] 9. Mobile URL if required
- [ ] 10. E2E create → approve → complete/delete

Thinking patterns

  1. SPI first — Extend MessageWebServiceDao.
  2. Idempotency keys — Decide before coding (YH taskId vs Weaver flowid+receiver).
  3. Order — Complete/delete tasks before terminal flow update.
  4. Identity — Same code across SSO + push + SHR person.
  5. Deep link + SSO — Always SSO entry then target (kdshrsso); platform-specific entry URL.
  6. Latency — WF DB lag; delay/retry.
  7. Observability — CallLog; empty requestparams often = exception before body write.
  8. Channels — Separate configs/clients per IdP; fan-out later; don’t block one channel on another.
  9. Config externalization — No secrets in git; hot-reload when possible.
  10. Weaver links — Relative path only; configurable sso.entryPath.

Anti-patterns

Avoid Why
Bypass MessageWebServiceDao Missed callbacks
Absolute pcurl to Weaver API rejects / 外链规则不符
Unified /auth/app for Weaver PC todo UA → unsupported_client
Rename weaverTodoConfig to “todoConfig” mid-project Risk / little gain
One config file for Weaver OpenAPI + DingTalk push Secrets and APIs differ
Soft-fail empty person mapping Wrong assignee

Search terms

MessageWebServiceDao WeaverMessageWebServiceDao
WeaverTodoMessageServer WeaverTodoSupport WeaverTodoConfig
weaver.sso.entryPath receiveRequestInfo syscode s-HRCloud
assignReadRecord OAMsgCallLog receiveOAConfig PORTAL-002

References

Doc Content
yhpro-reference.md YHPro package + field mapping
portal-api-map.md PORTAL field quick map
weaver-baoy-plan.md BaoYPro Weaver todo (implemented notes)
weaver-receive-todo-api.md Weaver E10 field extract
kdshrsso Option B-qy SSO entry / logout / AttackFilter