diff --git a/.env.example b/.env.example index 72bff36..0745dc3 100644 --- a/.env.example +++ b/.env.example @@ -11,33 +11,36 @@ FEISHU_APP_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # 事件订阅的 Verification Token 和 Encrypt Key FEISHU_VERIFICATION_TOKEN=xxxxxxxxxxxxxxxx FEISHU_ENCRYPT_KEY= -# 飞书审批定义code(在飞书管理后台查看) -FEISHU_APPROVAL_FILE_IN=approval-code-file-in -FEISHU_APPROVAL_FILE_OUT=approval-code-file-out -FEISHU_APPROVAL_GROUP_PERM=approval-code-group-perm +# 办理人的 open_id(程序以此身份完成办理任务) +# 获取方式:飞书开放平台 API调试台 → 搜索"获取用户信息" → 用手机号查自己的 open_id +FEISHU_HANDLER_USER_ID=ou_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +# 飞书审批定义code(飞书管理后台 → 审批管理 → 打开对应表单 → URL中的 approvalCode 参数) +FEISHU_APPROVAL_FILE_IN=你的文件传入审批code +FEISHU_APPROVAL_FILE_OUT=你的文件传出审批code +FEISHU_APPROVAL_GROUP_PERM=你的红区组权限审批code # 告警通知群 webhook(群机器人) FEISHU_ALERT_WEBHOOK=https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxx # ===== 群晖 NAS 配置 ===== -SYNOLOGY_HOST=https://10.2.3.40:5001 -SYNOLOGY_USERNAME=qwq -SYNOLOGY_PASSWORD=:e7P6ZaxwU9Uv8R +SYNOLOGY_HOST=https://你的NAS_IP:5001 +SYNOLOGY_USERNAME=你的NAS账号 +SYNOLOGY_PASSWORD=你的NAS密码 # 是否跳过TLS证书验证(自签证书时设为true) SYNOLOGY_SKIP_TLS=true # ===== JumpServer 配置 ===== -JUMPSERVER_HOST=http://10.2.3.41 -JUMPSERVER_KEY_ID=912c725a-145b-4ee9-8eb8-4dc33913349b -JUMPSERVER_KEY_SECRET=O4XnRa6ustUV7A4sU6KWaH8yAs3TXtxzLcTa -# ic1 资产的 asset_id(在JumpServer控制台查看) -JUMPSERVER_ASSET_IC1=c37d2b6d-3c4f-4d24-8792-40f3db2be54e +JUMPSERVER_HOST=http://你的JumpServer地址 +JUMPSERVER_KEY_ID=你的API-Key-ID +JUMPSERVER_KEY_SECRET=你的API-Key-Secret +# ic1 资产的 asset_id(在JumpServer控制台 → 资产管理 → 点击ic1 → URL中的UUID) +JUMPSERVER_ASSET_IC1=你的ic1资产UUID # 系统用户(用于连接ic1的账号) JUMPSERVER_SYSTEM_USER=root # ===== Nextcloud 配置 ===== -NEXTCLOUD_HOST=http://10.2.3.137:28080 -NEXTCLOUD_USERNAME=qwq -NEXTCLOUD_PASSWORD=03451420 +NEXTCLOUD_HOST=http://你的Nextcloud地址 +NEXTCLOUD_USERNAME=你的Nextcloud账号 +NEXTCLOUD_PASSWORD=你的Nextcloud密码 # 共享默认权限(1=读, 15=读写删, 17=读+分享) NEXTCLOUD_SHARE_PERMISSIONS=1 diff --git a/src/config.js b/src/config.js index 3b82a27..678548e 100644 --- a/src/config.js +++ b/src/config.js @@ -10,6 +10,8 @@ const config = { appSecret: process.env.FEISHU_APP_SECRET, verificationToken: process.env.FEISHU_VERIFICATION_TOKEN, encryptKey: process.env.FEISHU_ENCRYPT_KEY || '', + // 办理人的 open_id(程序以此身份完成办理任务) + handlerUserId: process.env.FEISHU_HANDLER_USER_ID || '', approvalCodes: { fileIn: process.env.FEISHU_APPROVAL_FILE_IN, fileOut: process.env.FEISHU_APPROVAL_FILE_OUT, diff --git a/src/routes/feishu-event.js b/src/routes/feishu-event.js index 978f728..18924cb 100644 --- a/src/routes/feishu-event.js +++ b/src/routes/feishu-event.js @@ -57,9 +57,8 @@ async function processEvent(body) { const approvalCode = event.approval_code; const status = event.status; // APPROVED / REJECTED / PENDING - // 只处理"已通过"的审批(即审批人同意后触发自动化) - // 根据你的流程设计,也可能是 PENDING 时触发(机器人自动审批) - if (status !== 'APPROVED' && status !== 'PENDING') return; + // 只处理进行中的审批(办理任务到达时 instance 仍为 PENDING) + if (status !== 'PENDING' && status !== 'APPROVED') return; // 防重复处理 if (isApprovalProcessed(instanceCode)) { @@ -67,7 +66,23 @@ async function processEvent(body) { return; } - logger.info(`[飞书事件] 收到审批事件: code=${approvalCode}, instance=${instanceCode}, status=${status}`); + // 检查当前 PENDING 任务是否分配给办理人(过滤掉上级审批阶段) + const handlerId = config.feishu.handlerUserId; + if (handlerId) { + try { + const instance = await feishu.getApprovalInstance(approvalCode, instanceCode); + const taskList = instance.task_list || []; + const pendingTask = taskList.find(t => t.status === 'PENDING'); + if (!pendingTask || pendingTask.user_id !== handlerId) { + logger.info(`[飞书事件] 当前待办非本程序办理任务,跳过: instance=${instanceCode}`); + return; + } + } catch (e) { + logger.warn(`[飞书事件] 获取实例详情失败,继续处理: ${e.message}`); + } + } + + logger.info(`[飞书事件] 办理任务到达: code=${approvalCode}, instance=${instanceCode}`); // 根据审批定义 code 路由到不同工作流 if (approvalCode === config.feishu.approvalCodes.fileIn) { @@ -113,7 +128,7 @@ async function processFileIn(approvalCode, instanceId) { const result = await handleFileIn(approvalData, logId); updateLog(logId, 'success'); - // 提交审批意见 + // 以办理人身份完成办理任务 await feishu.approveInstance(approvalCode, instanceId, result.message); logger.info(`[文件传入] 完成: ${result.detail}`); } catch (err) { diff --git a/src/services/feishu.js b/src/services/feishu.js index 10475d1..55c9619 100644 --- a/src/services/feishu.js +++ b/src/services/feishu.js @@ -95,19 +95,22 @@ function parseApprovalForm(formJson) { * @param {string} comment - 审批意见 */ async function approveInstance(approvalCode, instanceId, comment) { - // 先获取审批实例中的当前审批节点 task_id + // 获取审批实例中的当前审批节点 task_id const instance = await getApprovalInstance(approvalCode, instanceId); const taskList = instance.task_list || []; - // 找到 PENDING 状态的 task + // 找到 PENDING 状态的 task(即当前待办理任务) const pendingTask = taskList.find(t => t.status === 'PENDING'); if (!pendingTask) { throw new Error(`审批实例 ${instanceId} 无待处理任务`); } + // 使用配置的办理人身份,或任务本身的 user_id + const userId = config.feishu.handlerUserId || pendingTask.user_id; + return feishuRequest('POST', '/approval/v4/instances/approve', { approval_code: approvalCode, instance_code: instanceId, - user_id: pendingTask.user_id, + user_id: userId, task_id: pendingTask.task_id, comment: comment, });