root
|
68e0c261d8
|
feat: 完善业务审批消息链路
修改内容:
1. TestController - 添加 real 参数支持发送真实业务通知
2. BusinessTripService.sendApprovalNotification() - 传递 order_id
业务流程:
1. 用户创建申请 → 审批人收到带按钮的通知
2. 点击"通过"/"拒绝"按钮 → 跳转到审批详情页
3. 自动弹出确认框 → 完成审批
4. 通知下一节点审批人/申请人
按钮链接:
- 通过/拒绝:/approval/detail/{order_id}?action=approve|reject
- 查看详情:/business-trip/detail/{business_id}
测试命令:
- 测试消息: /api/v1/test/notification?user_id=1&order_id=64
- 真实业务: /api/v1/test/notification?user_id=1&order_id=64&real=1
相关文件:
- backend/app/controller/TestController.php
- backend/app/service/BusinessTripService.php
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 19:10:51 +08:00 |
|
root
|
7ee92d68fe
|
fix: 修复系统通知卡片 Markdown 渲染问题
问题:
- buildSystemCard 使用 plain_text 格式
- 内容中包含 Markdown 语法 **加粗** 无法渲染
- 显示为 **申请人**:陈兰 而不是 加粗的申请人
修复:
- 将 text.tag 从 plain_text 改为 lark_md
- 现在可以正确渲染 Markdown 格式
相关文件:
- backend/app/service/FeishuNotificationService.php
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 19:00:32 +08:00 |
|
root
|
df0d592ee4
|
feat: 飞书审批消息添加操作按钮
功能:
1. 审批通知卡片添加"通过"和"拒绝"按钮
2. 点击按钮跳转到审批详情页,自动弹出审批确认框
3. 保留"查看详情"按钮
实现:
- FeishuNotificationService.buildApprovalCard() - 添加审批操作按钮
- ApprovalService.notifyNextApprovers() - 传递 order_id 参数
- approval/detail.tsx - 处理 URL 中的 action 参数
按钮样式:
- 通过按钮:绿色 (primary)
- 拒绝按钮:红色 (danger)
- 查看详情:默认样式
相关文件:
- backend/app/service/FeishuNotificationService.php
- backend/app/service/ApprovalService.php
- frontend/src/pages/approval/detail.tsx
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 18:57:59 +08:00 |
|
root
|
32d19d56ee
|
fix: 修复审批消息推送问题
问题1:BusinessTripService 数据格式兼容性
- 后端期望对象数组 [{id:1, name:'...'}],前端传纯 ID 数组 [1,2,3]
- 修复:兼容两种格式,自动提取 id
问题2:ApprovalService 没有消息推送
- 添加 FeishuNotificationService 集成
- approve() 方法:节点完成后通知下一节点审批人,流程完成后通知申请人
- reject() 方法:审批拒绝时通知申请人
问题3:修复重复类定义导致的语法错误
相关文件:
- backend/app/service/BusinessTripService.php
- backend/app/service/ApprovalService.php
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 18:53:56 +08:00 |
|
root
|
ee5f7791de
|
docs: 更新 PROJECT_ISSUES.md 记录审批相关问题
添加问题记录:
- 问题25:Tab 状态持久化问题
- 问题26:我已审批列表不显示(ApprovalService 数据源错误)
- 问题27:审批流程不自动跳过通知节点
- 问题28:架构问题总结 - 数据模型混淆
- 问题29:数据库完整性建议
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 18:47:15 +08:00 |
|
root
|
e904d5cd97
|
fix: 修复 ApprovalService 使用 form_data.approvers
问题:ApprovalService 还在使用 approval_node.approvers 字段
解决:改用 form_data.approvers 作为运行时审批人数据
修改内容:
1. approve() - 添加跳过 notify 节点逻辑
2. isNodeCompleted() - 从 form_data 获取审批人
3. getPendingOrderIds() - 从 form_data 获取审批人
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 18:42:30 +08:00 |
|
root
|
8ce070bd77
|
fix: 使用 sessionStorage 保持 tab 状态
问题:navigate(-1) 浏览器后退不会传递 location.state
解决方案:
- 切换 tab 时保存到 sessionStorage
- 页面加载时优先从 sessionStorage 恢复 tab
修改文件:
- frontend/src/pages/business-trip/list.tsx
- frontend/src/pages/approval/list.tsx
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 18:38:42 +08:00 |
|
root
|
f3a9e442e9
|
fix: 返回列表时保持之前的 tab 状态
问题:从详情页返回时,列表总是重置到"我发起的" tab
解决方案:
1. 导航到详情页时传递 state: { fromTab: activeTab }
2. 列表页从 location.state.fromTab 恢复 tab 状态
修改文件:
- frontend/src/pages/approval/list.tsx
- frontend/src/pages/business-trip/list.tsx
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 18:36:41 +08:00 |
|
root
|
ea7f0f8820
|
feat: 添加"抄送我的"审批列表选项
后端修改:
- ApprovalService::getList 添加 'cc' 类型查询
- 从 form_data.cc_users 中查找包含当前用户的订单
- 兼容两种数据格式:[{id:29}] 或 [29]
前端修改:
- 添加"抄送我的"标签页
- 更新类型定义支持 'cc' 类型
- approvalListParams 类型添加 'cc' 选项
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 18:33:53 +08:00 |
|
root
|
0942cb1af0
|
fix: 修复旧审批记录状态并添加前端调试日志
1. 手动修复旧审批记录的状态(在代码修复之前审批的)
2. 添加前端 console.log 调试输出
3. 验证后端API返回正确的 approved 状态数据
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 18:25:56 +08:00 |
|
root
|
61d1c70ba8
|
fix: 完善审批流程错误处理和调试日志
主要修改:
1. 添加完整的 try-catch 错误处理
2. 添加 Transaction 开始/成功日志
3. 添加保存前后的状态日志
4. 捕获并记录任何异常
测试验证:
- 审批流程正常执行
- 状态正确更新为 approved
- 跳过 notify 节点直接完成
- "我已审批"列表正确返回数据
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 18:23:02 +08:00 |
|
root
|
8b37d6313e
|
fix: 完善审批流程调试日志
添加详细的调试日志来追踪审批流程:
1. approve() 方法开始时的参数日志
2. 节点类型和完成状态的日志
3. 下一节点查询和跳过逻辑的日志
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 18:19:51 +08:00 |
|
root
|
f36fc69b8d
|
fix: 修复审批流程完成后状态更新问题
主要修改:
1. 修复下一节点查询逻辑,使用 order > currentOrder 替代 order > 0
2. 在 submit 和 approve 方法中跳过 notify 节点直接完成流程
3. 添加详细的调试日志
4. 兼容两种数据格式:[1,2,3] 或 [{id:1},{id:2},{id:3}]
修复问题:
- 审批完成后流程移到 notify 节点而不是完成
- business_trip status 没有更新为 approved
- "我已审批"列表为空
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 18:14:49 +08:00 |
|
root
|
cc3c599c90
|
fix: 使用 form_data 存储运行时审批人,不修改 approval_node 模板
主要修改:
1. submit() 方法不再修改 approval_node 表,节点仅作为流程模板
2. getList() 的 pending 查询从 form_data.approvers 获取审批人列表
3. approve() 方法从 form_data.approvers 检查用户是否有权限
4. 兼容两种数据格式:[1,2,3] 或 [{id:1},{id:2},{id:3}]
修复问题:
- 之前每次提交申请都会修改 approval_node 表的 approvers 字段
- 这导致流程模板被污染,不同的申请共享同一个节点配置
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 18:01:40 +08:00 |
|
root
|
5095f556c8
|
fix: 修复单人审批完成后的流程流转逻辑
问题:
1. 审批完成后直接移动到下一节点,没有检查节点类型
2. 抄送节点应该跳过并完成流程,而不是进入抄送节点
3. 审批完成后的申请应该进入"审批完成"状态
修复:
- 检查节点完成条件:单人审批/或签一人通过即完成
- 检查下一节点类型:抄送节点则跳过并完成
- 没有后续节点则完成流程
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 17:39:59 +08:00 |
|
root
|
dc763d874a
|
fix: 修复待审批列表查询逻辑
- 检查用户是否在当前节点的审批人列表中
- 排除已经审批过的申请
- 同时修复数据库节点7的审批人配置
问题:待审批列表没有验证用户是否为当前节点审批人
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 17:34:56 +08:00 |
|
root
|
a1176b1042
|
fix: 移除硬编码,使用数据库配置审批流程
- 数据库已配置审批节点:陈兰 (id=27)
- 数据库已配置抄送节点:陈标 (id=29)
- 移除硬编码的 getDefaultApproversFromConfig() 方法
- 代码从数据库读取配置
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 17:30:25 +08:00 |
|
root
|
a6e4a7fbc4
|
feat: 设置默认审批人为陈兰,抄送人为陈标
- 当没有配置审批流程时返回默认值
- 新增 getDefaultApproversFromConfig() 方法
- 默认审批人:陈兰 (id=27)
- 默认抄送人:陈标 (id=29)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 17:24:45 +08:00 |
|
root
|
c1016c740d
|
feat: 接入飞书消息通知到出差审批功能
- 提交申请后通知审批人和抄送人
- 审批通过/拒绝后通知申请人
- 取消申请后通知审批人和抄送人
- 新增 sendApprovalNotification() 方法
- 新增 sendApprovalResultNotification() 方法
- 新增 sendCancelNotification() 方法
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 17:16:23 +08:00 |
|
root
|
a88944b5e1
|
refactor: 删除 users 表中未使用的字段
- 删除 report_to(上级ID)字段
- 删除 position(职位)字段
- 更新 User 模型移除相关关联和类型转换
- 更新 BusinessTripService 移除 position 返回
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 16:56:51 +08:00 |
|
root
|
fdbe2e837a
|
refactor: 删除 users 表中的冗余飞书字段
- 删除 feishu_user_id, feishu_open_id, tenant_key 字段
- JWT token 改用 feishu_app_id 代替 feishu_user_id
- 删除废弃的 FeishuService::sendApprovalMessage() 方法
- 更新 User 模型移除废弃字段和 scope 方法
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 16:33:58 +08:00 |
|
root
|
0489da5e40
|
refactor: 重构多飞书应用绑定架构和数据库清理
- 新增 user_feishu_apps 表支持用户绑定多个飞书应用
- users 表添加唯一约束(公司内邮箱/手机唯一)
- 迁移现有飞书数据到 user_feishu_apps 表
- 清理冗余表(users_bak, user_feishu_binding)
- 废弃 users 表中的 feishu_user_id/feishu_open_id/tenant_key 字段
- 更新 FeishuNotificationService 使用新的数据获取方式
- User 模型新增 getFeishuUserId() 等便捷方法
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 16:27:33 +08:00 |
|
root
|
04947ae52d
|
fix: 修复飞书通知模块API路径和卡片格式
- 修改API路径为 /open-apis/im/v1/messages (message/v4已废弃)
- 添加卡片config配置
- 修复content格式(直接传卡片对象,不需要包裹)
- 添加测试接口 /api/v1/test/notification
测试结果: 成功发送通知到李佳博(feishu_user_id: 481g947d)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 15:27:54 +08:00 |
|
root
|
2e5f570b40
|
feat: 完善鉴权和密码功能,添加飞书通知模块
- 完善Token过期/不存在时跳转登录重新认证
- 实现正常的账号密码登录验证(邮箱/手机号+密码)
- 用户初始化密码设为工号(sn)
- 添加修改密码功能(API+前端页面)
- 修复扫码登录后跳转问题(zustand persist格式)
- 创建飞书通知服务 FeishuNotificationService
- 设置页面添加修改密码入口
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 15:19:37 +08:00 |
|
root
|
ba555a59b7
|
debug: 添加轮询和跳转的详细日志
|
2026-02-26 12:00:56 +08:00 |
|
root
|
826989d6bf
|
style: 只保留带 emoji 的提示,移除状态文字
|
2026-02-26 11:59:46 +08:00 |
|
root
|
716d39f0b6
|
style: 恢复带 emoji 的飞书扫码提示文字
|
2026-02-26 11:58:33 +08:00 |
|
root
|
32a0ba57cb
|
style: 移除冗余的飞书扫码提示文字
|
2026-02-26 11:58:02 +08:00 |
|
root
|
6b9addf35d
|
style: 调整弹框左右留白为 10px
|
2026-02-26 11:57:28 +08:00 |
|
root
|
40d4d88f98
|
style: 继续减少弹框留白为 8px 20px
|
2026-02-26 11:57:02 +08:00 |
|
root
|
49f8e30839
|
style: 继续减少弹框留白为 12px 20px
|
2026-02-26 11:56:48 +08:00 |
|
root
|
947cbdd571
|
style: 继续减少弹框留白为 16px 20px
|
2026-02-26 11:56:38 +08:00 |
|
root
|
e82e6988a1
|
style: 减少弹框留白为 24px 20px
|
2026-02-26 11:56:22 +08:00 |
|
root
|
88a25e21c2
|
style: 调整二维码弹框的四周留白为 40px 30px
|
2026-02-26 11:56:08 +08:00 |
|
root
|
b12842a338
|
style: 更新 QR SDK 配置参数,添加 style 属性
- width/height: 250x250
- style: width:300px;height:270px;border:none
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 11:55:07 +08:00 |
|
root
|
9836525c81
|
style: 进一步增大二维码尺寸到 280x280
|
2026-02-26 11:49:40 +08:00 |
|
root
|
a691675411
|
style: 调整二维码尺寸为 240x240,增加容器高度
|
2026-02-26 11:47:30 +08:00 |
|
root
|
79cef9ac91
|
fix: 修复 QRLogin SDK 二维码不显示的问题
1. 使用 getElementById 获取容器,避免清空容器本身
2. 确保 DOM 渲染完成后再调用 SDK
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 11:36:46 +08:00 |
|
root
|
d76ee80ecc
|
fix: 修正飞书 SDK 全局变量名为 QRLogin
SDK 的全局变量是 window.QRLogin 而不是 window.QR
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 11:30:35 +08:00 |
|
root
|
983f58ee98
|
fix: 增加 SDK 加载等待时间,确保 window.QR 已初始化
|
2026-02-26 11:23:47 +08:00 |
|
root
|
6eb621cd95
|
fix: 在 HTML 中直接引入飞书 QR SDK
根据官方文档,SDK 应该在 HTML 中通过 script 标签引入,
而不是动态加载。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 11:19:46 +08:00 |
|
root
|
429a8605fc
|
fix: 添加 QR SDK 加载失败的降级方案
1. 优先尝试加载飞书官方 QR SDK
2. 如果 SDK 加载超时(5秒)或失败,自动降级到普通二维码
3. 添加详细的加载日志,方便调试
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 11:16:40 +08:00 |
|
root
|
474c532666
|
fix: 使用飞书官方 QR SDK,扫码后不打开浏览器
使用飞书官方 LarkSSOSDKWebQRCode-1.0.3.js 生成二维码,
飞书APP会识别为登录二维码并在APP内直接处理,
不会打开任何浏览器窗口。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 11:13:43 +08:00 |
|
root
|
457b1d75f0
|
fix: 返回完全空白的响应页面
正常飞书APP内扫码流程:
1. 用户扫码确认授权
2. 飞书APP直接返回主界面(不会打开任何页面)
3. 电脑端通过轮询检测登录成功并自动跳转
redirect_uri 是OAuth协议要求的配置,但飞书APP内扫码时不会真正访问此URL。
只有在浏览器扫码时才会真正跳转,此时返回空白页面。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 11:10:51 +08:00 |
|
root
|
ad6984d22a
|
fix: 扫码登录成功后返回空页面并自动关闭
手机端扫码成功后直接关闭并返回飞书,不显示任何页面内容。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 11:08:10 +08:00 |
|
root
|
fd364be4b6
|
fix: 扫码登录成功后返回简单页面,不重定向
移动端扫码完成后显示登录成功页面,用户可直接关闭,
不再重定向到前端页面。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 11:04:31 +08:00 |
|
root
|
cd1499cd0f
|
fix: 修正飞书登录回调重定向方法
使用 Webman 全局 redirect() 函数,而不是 Response::redirect()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 11:02:41 +08:00 |
|
root
|
a1b395b147
|
fix: 移除 HttpClient 中的 curl_close() 调用
PHP 8.0+ 中 curl 资源会自动关闭,curl_close() 已被弃用。
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 10:45:22 +08:00 |
|
root
|
6899bad529
|
refactor: 重构飞书授权代码,提取公共工具类
1. 创建 app/util/HttpClient.php
- 公共 HTTP 请求类
- httpGet() 和 httpPost() 方法
- 支持自定义 headers 和 timeout
- 统一错误处理和日志
2. 创建 app/util/FeishuUtil.php
- 飞书授权工具类,可被其他业务模块复用
- getAppAccessToken() - 获取应用访问令牌(带缓存)
- getUserAccessToken() - 获取用户访问令牌
- getUserInfo() - 获取用户信息
- getCompleteUserInfo() - 一步获取完整用户信息
- clearTokenCache() - 清除 token 缓存
3. 重构 app/service/FeishuService.php
- 使用新的工具类
- 移除重复的 HTTP 请求方法
- 保持向后兼容
飞书授权流程:
1. app_access_token (应用级令牌)
2. user_access_token (用户级令牌,需要 app_access_token)
3. 用户信息 (需要 user_access_token)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 10:43:29 +08:00 |
|
root
|
b1d58ece61
|
fix: 使用飞书官方 passport 授权端点
后端修改:
- 授权 URL 从 open-apis 改为 passport.feishu.cn
- 使用 passport 端点获取 user_access_token
- 添加 httpGet 方法
前端修改:
- 使用官方 tt.requestAuthCode() API(飞书内免登)
- 保留轮询方式实现扫码登录
参考文档: https://open.feishu.cn/document/sso/web-application-sso/qr-sdk-documentation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
2026-02-26 10:20:48 +08:00 |
|