271 Комити 8567ad642e ... 6278f197a1

Аутор SHA1 Порука Датум
  hanzhengyi 6278f197a1 Merge branch 'fhs' of uskycloud/usky-cloud into master пре 1 дан
  fanghuisheng 3959660c53 Merge branch 'develop' of http://47.111.81.118:3000/uskycloud/usky-cloud into fhs пре 1 недеља
  fanghuisheng 86c81e3013 人员管理逻辑代码完善 пре 1 недеља
  hanzhengyi e0f72ff43e Merge branch 'han' of uskycloud/usky-cloud into master пре 3 недеља
  hanzhengyi 50c94a8efc 去除私包 пре 3 недеља
  james 0279a505b6 解决冲突 пре 1 месец
  hanzhengyi 314676ec83 Merge branch 'master' of http://47.111.81.118:3000/uskycloud/usky-cloud пре 1 месец
  gez 72fe261703 Merge branch 'fhs' of uskycloud/usky-cloud into master пре 1 месец
  hanzhengyi 069761d151 调整优化菜单查询逻辑 пре 1 месец
  fanghuisheng 657ac7d79e 人员管理新增部门名称回显功能 пре 1 месец
  fanghuisheng b67990b2fd 人员管理增删改查功能完成 пре 1 месец
  hanzhengyi bcc529ff6a 去除私包配置 пре 1 месец
  hanzhengyi aa8020ff55 Merge branch 'han' пре 1 месец
  hanzhengyi 46f98515ac 2026筑境计划-V3版本上线 пре 1 месец
  hanzhengyi 81deaa4ce3 应用、菜单增加类型字段 пре 3 месеци
  gez 795687733a Merge branch 'system-zjy' of uskycloud/usky-cloud into master пре 4 месеци
  zhaojinyu 636b7239a1 修改阿里云短信至yaml文件 пре 4 месеци
  gez e774b0b2e0 Merge branch 'han' of uskycloud/usky-cloud into master пре 7 месеци
  hanzhengyi cdf36ccd11 调整切换默认租户及登录验证 пре 7 месеци
  hanzhengyi 4d3f8c2895 Merge branch 'han' of uskycloud/usky-cloud into master пре 7 месеци
  hanzhengyi 0621e28b49 修改用户默认租户 пре 7 месеци
  hanzhengyi 6f7ea29122 Merge branch 'system-zjy' of uskycloud/usky-cloud into master пре 8 месеци
  zhaojinyu efc1bdcf72 解决线上工作报告记录操作日志是异常问题 пре 8 месеци
  zhaojinyu 9d03bb7a8b 去除maven文件中冗余 пре 8 месеци
  zhaojinyu df59a8b80c Admin控制台添加服务状态变更告警功能 пре 9 месеци
  hanzhengyi dd6a24ca5d Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 9 месеци
  fuyuchuan 2f2cfcc078 修复工作报告、通知公告微信公众号消息推送显示账号非用户名问题 пре 9 месеци
  hanzhengyi 149ef97591 Merge branch 'system-zjy' of uskycloud/usky-cloud into master пре 9 месеци
  zhaojinyu f73f5dfbbc 调整注解 пре 9 месеци
  zhaojinyu 171ebb7060 优化为相同操作系统只能存在最新一条token пре 9 месеци
  gez 5aee9d5ee7 Merge branch 'han' of uskycloud/usky-cloud into master пре 10 месеци
  hanzhengyi 9995b37fc7 调整移动端租户切换 пре 10 месеци
  zhaojinyu 3676562dbc Merge branch 'system-zjy' of uskycloud/usky-cloud into master пре 10 месеци
  hanzhengyi e7377f51b9 Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 10 месеци
  fuyuchuan f302ead6af H5消息中心登录通知异常显示问题 пре 10 месеци
  zhaojinyu 6c3ee6e670 调整删除历史token方法,解决删除失败报错问题 пре 10 месеци
  gez 7fe68c11ee Merge branch 'system-zjy' of uskycloud/usky-cloud into master пре 10 месеци
  zhaojinyu bb645c76a2 优化去除代码中无效引用 пре 10 месеци
  zhaojinyu 5a8766be8f 添加保留用户相同OS和Browser的最新两条token方法 пре 10 месеци
  zhaojinyu 113af5ba72 Merge branch 'master' of http://47.111.81.118:3000/uskycloud/usky-cloud into system-zjy пре 10 месеци
  hanzhengyi 9bb5414a04 Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 10 месеци
  fuyuchuan e7a33e8706 修复登录通知控制针导致发送微信消失失败、成功后重复发送消息问题 пре 10 месеци
  hanzhengyi f972dd66b7 Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 10 месеци
  fuyuchuan a6a4cb7f75 修复告警推送微公众号通知信息不全问题 пре 10 месеци
  fuyuchuan 66fc043321 修复告警推送微公众号通知信息不全问题 пре 10 месеци
  gez 02d9877423 Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 10 месеци
  fuyuchuan 24706e496d 修复接口异常 пре 10 месеци
  fuyuchuan 21b63f0e40 修复接口潜在异常 пре 10 месеци
  fuyuchuan 72c3804906 新增登录通知开关接口 пре 10 месеци
  fuyuchuan d78049975b 修复接口数据类型转换报错 пре 10 месеци
  fuyuchuan 6deff85c06 修复接口数据类型转换报错 пре 10 месеци
  fuyuchuan 18e8824a99 修复接口数据类型转换报错 пре 10 месеци
  fuyuchuan a9497b7d11 修复接口数据类型转换报错 пре 10 месеци
  fuyuchuan d942c2f444 添加返回参数 пре 10 месеци
  fuyuchuan dfe22420e7 修复个人信息中角色与职位未进行租户隔离问题 пре 10 месеци
  fuyuchuan 3c5d2f57be 微信登录通知添加查询前置条件 пре 10 месеци
  fuyuchuan 8338ff725b 配合告警通知修改消息中心代并优化 пре 10 месеци
  fuyuchuan b1354dce37 新增登录通知开关设置 пре 10 месеци
  fuyuchuan 17e8d3ee94 新增登录通知开关设置 пре 10 месеци
  fuyuchuan 54fad1b003 恢复代码 пре 10 месеци
  fuyuchuan 5778c675f3 Merge branch 'system-165' into fu-dev пре 10 месеци
  fuyuchuan c47026d608 优化下拉树部门人员接口显示离职人员问题 пре 10 месеци
  fuyuchuan 559ec945d0 Merge branch 'master' of http://47.111.81.118:3000/uskycloud/usky-cloud into system-165 пре 10 месеци
  fuyuchuan e5a8b90bcf Merge branch 'master' of http://47.111.81.118:3000/uskycloud/usky-cloud into fu-dev пре 10 месеци
  hanzhengyi 8e788114f0 Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 10 месеци
  fuyuchuan 47e228fff6 Merge branch 'master' of http://47.111.81.118:3000/uskycloud/usky-cloud into fu-dev пре 10 месеци
  fuyuchuan 679a94bd5c 消息分页接口新增消息id查询 пре 10 месеци
  gez f932e62942 Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 10 месеци
  fuyuchuan 6aabe34636 修复OA微信推送消息回调地址跳转类型为空问题 пре 10 месеци
  gez 3833a8efe9 Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 10 месеци
  fuyuchuan 8720bfdc13 修复登录通知异常,修复跳转url参数异常问题 пре 10 месеци
  zhaojinyu 7918e6d9b8 操作日志优化获取操作地址,token令牌添加操作系统、浏览器类型字段并优化在线用户接口 пре 10 месеци
  hanzhengyi 8cad02b3ec Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 11 месеци
  fuyuchuan 21a68f69cf 新增微信公众号OA审批回调地址 пре 11 месеци
  fuyuchuan d580cd901d 修复登录通知异常;优化消息通知代码 пре 11 месеци
  gez 33c3b1ee79 Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 11 месеци
  fuyuchuan 0bbd7d22b4 问题代码修复 пре 11 месеци
  fuyuchuan fd47a57ea1 Merge branch 'master' of http://47.111.81.118:3000/uskycloud/usky-cloud into fu-dev пре 11 месеци
  fuyuchuan 7efb63ebcf OA消息模版添加字段 пре 11 месеци
  fuyuchuan ae96a7683a 微信消息模板代码优化调整 пре 11 месеци
  gez 7dcda75bb0 Merge branch 'system-zjy' of uskycloud/usky-cloud into master пре 11 месеци
  zhaojinyu 9192ee55e7 修改登录ip获取方式,处理出现空指针问题 пре 11 месеци
  fuyuchuan 9876bcc5c8 修复登录消息发送失败问题 пре 11 месеци
  gez c8592ecc0d Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 11 месеци
  fuyuchuan e2c56a4952 Merge branch 'master' of http://47.111.81.118:3000/uskycloud/usky-cloud into fu-dev пре 11 месеци
  fuyuchuan a07e84e5d4 消息中心新增OA模板以;通知公告和工作报告模板更换 пре 11 месеци
  gez 9bf5704b4c Merge branch 'system-zjy' of uskycloud/usky-cloud into master пре 11 месеци
  fuyuchuan d3593c4442 Merge branch 'master' of http://47.111.81.118:3000/uskycloud/usky-cloud into fu-dev пре 11 месеци
  fuyuchuan 23d4f354a7 修复发布人为空问题&优化开放无token调用消息中心接口代码 пре 11 месеци
  hanzhengyi c910b854c6 Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 11 месеци
  fuyuchuan 16b4388cd9 Merge branch 'master' of http://47.111.81.118:3000/uskycloud/usky-cloud into fu-dev пре 11 месеци
  fuyuchuan 90d9bd1834 Merge branch 'master' of http://47.111.81.118:3000/uskycloud/usky-cloud into system-165 пре 11 месеци
  hanzhengyi 30f2802d72 Merge branch 'system-zyj' of uskycloud/usky-cloud into master пре 11 месеци
  fuyuchuan 5b2a60afb7 消息中心新增无token接口给OA服务定时同步消息调用 пре 11 месеци
  fuyuchuan 640f2f0b56 消息中心新增无token接口给OA服务定时同步消息调用 пре 11 месеци
  james 3b9017c0c3 Merge branch 'system-zyj' into system-165 пре 11 месеци
  fuyuchuan f8b1c812ce 消息类型大类代码删除 пре 11 месеци
  zhaojinyu 8d97d9448f 添加使用oshi与jna监控服务器资源状态插件 пре 11 месеци
  gez ff28eebcec Merge branch 'han' of uskycloud/usky-cloud into master пре 11 месеци
  gez 2a16aa5f93 Merge branch 'system-zyj' of uskycloud/usky-cloud into master пре 11 месеци
  gez 5df87e3a94 Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 11 месеци
  james 28a14cf93b Merge branch 'system-zyj' into system-165 пре 11 месеци
  james a8837338bd Merge branch 'system-zyj' into system-165 пре 11 месеци
  fuyuchuan affc62119d 消息中心代码回退,修复消息中心租户未隔离问题 пре 11 месеци
  fuyuchuan db4f9d6cb6 Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 11 месеци
  fuyuchuan 27f6ca2b97 Merge branch 'system-165' into fu-dev пре 11 месеци
  fuyuchuan 7701adca8b Merge branch 'master' of http://47.111.81.118:3000/uskycloud/usky-cloud into system-165 пре 11 месеци
  fuyuchuan d96fbbddcb 小铃铛添加消息大类字段返回 пре 11 месеци
  james 66618d223d Merge branch 'system-zyj' into system-165 пре 11 месеци
  james 58f359f88a Merge branch 'system-zyj' into system-165 пре 11 месеци
  fuyuchuan 52f5ccceb2 Merge branch 'master' of http://47.111.81.118:3000/uskycloud/usky-cloud into fu-dev пре 11 месеци
  fuyuchuan 498a80478f Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 11 месеци
  fuyuchuan 89bc586bd0 消息中心修复租户隔离、消息分类大类 пре 11 месеци
  hanzhengyi cfff83b7fc Merge branch 'han' пре 11 месеци
  gez 926edd7563 Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 11 месеци
  gez 6646e463d9 Merge branch 'system-zyj' of uskycloud/usky-cloud into master пре 11 месеци
  zhaojinyu 0a17529001 回退代码移除使用脚本获取服务器资源监控信息到数据库 пре 11 месеци
  fuyuchuan 5941f5ffcc Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 11 месеци
  fuyuchuan 4b35df00a3 Merge branch 'system-165' into fu-dev пре 11 месеци
  fuyuchuan 3874765a81 修复切换租户后分配角色后菜单接口数据异常问题 пре 11 месеци
  zhaojinyu df011b34e3 添加服务器资源监控相关功能增删查 пре 11 месеци
  fuyuchuan 0132a9aa0f Merge branch 'master' of http://47.111.81.118:3000/uskycloud/usky-cloud into fu-dev пре 1 година
  hanzhengyi 5064a80aed Merge branch 'han' of uskycloud/usky-cloud into system-165 пре 1 година
  hanzhengyi bd53c4f363 解决冲突 пре 1 година
  hanzhengyi 868377a9de 应用管理增加排序字段,应用菜单增加排序返回值 пре 1 година
  james 536d39b517 Merge branch 'system-zyj' into system-165 пре 1 година
  james 390b0ad0a0 Merge branch 'system-zyj' into system-165 пре 1 година
  james 5e3413d250 Merge branch 'system-zyj' into system-165 пре 1 година
  zhaojinyu e73755ff70 修改上传文件实现类,上传文件默认使用原名称如果重复添加序列号 пре 1 година
  james 8452a2e849 Merge branch 'system-zyj' into system-165 пре 1 година
  james 18a609f7e0 Merge branch 'system-zyj' into system-165 пре 1 година
  james ee06abc80a Merge branch 'system-zyj' into system-165 пре 1 година
  gez ae0cd217c5 Merge branch 'system-zjy' of uskycloud/usky-cloud into master пре 1 година
  zhaojinyu f5171a03e3 将获取到的用户ID转换为Long类型 пре 1 година
  zhaojinyu 2f9625cd5b 附件管理搜索接口添加创建者名称查询 пре 1 година
  zhaojinyu 22e8c5694f 整理代码,移除多余代码 пре 1 година
  zhaojinyu 14cc6d1155 整理代码,移除多余代码 пре 1 година
  zhaojinyu e9a4381e24 优化调整上传文件代码,解决无法获取用户信息问题并增加获取引用路径 пре 1 година
  fuyuchuan 3582cd3ba3 Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 1 година
  fuyuchuan cf4b57af69 巡检人员下拉选择异常修复 пре 1 година
  zhaojinyu aaad4dafc3 优化操作异常时返回报错内容 пре 1 година
  gez 04bd8fe3da Merge branch 'system-zjy' of uskycloud/usky-cloud into master пре 1 година
  zhaojinyu bc63e33e22 调用更新服务运行状态接口时等待查询是否成功 пре 1 година
  fuyuchuan e315bfbecf Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 1 година
  fuyuchuan 6af1464d0d 我的消息分页接口-消息类型整合 пре 1 година
  zhaojinyu 3a9963b857 新增服务运行状态获取及更新至数据库的方法与实现 пре 1 година
  fuyuchuan ce7d77921e Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 1 година
  fuyuchuan 8309e431ec 消息分页接口添加倒叙 пре 1 година
  fuyuchuan 4c26b9b8c7 Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 1 година
  fuyuchuan 1b8ebb0164 新增小铃铛消息分页接口 пре 1 година
  zhaojinyu 54cb7c6538 优化检查更新接口返回内容 пре 1 година
  zhaojinyu 86856ddba8 修改服务运行控制返回 пре 1 година
  zhaojinyu 42ffc4801c 优化检查更新接口返回内容 пре 1 година
  zhaojinyu 93db3fbc79 扫描服务接口返回数据格式进行调整 пре 1 година
  zhaojinyu c0526b32d3 服务是否需要更新值改为int类型 пре 1 година
  zhaojinyu 1d623398be 修改为不回显文件所在目录、不统计文件版本号 пре 1 година
  zhaojinyu f86b7b4893 修改查询目前服务目录存在服务是否已在数据表中录入,已有则不返回 пре 1 година
  zhaojinyu f66ec11f01 增加新功能:扫描服务所在目录中的文件可选择加入服务信息表 пре 1 година
  zhaojinyu d92b2e9dbe 数据表增加创建时间字段,修改记录时间逻辑代码 пре 1 година
  zhaojinyu 32f4fcfc64 修改接口反馈 пре 1 година
  zhaojinyu e87ead9c07 修改状态显示 пре 1 година
  zhaojinyu d7ad1aba84 修改下载更新服务实现类,下载更新后自动执行一次重启服务操作 пре 1 година
  zhaojinyu 2375cba34c 添加服务接口注解 пре 1 година
  zhaojinyu 7e27ab216a 修改服务远程更新接口,添加服务状态控制接口 пре 1 година
  hanzhengyi e3f88af378 Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 1 година
  zhaojinyu e392759428 修改代码获取file服务所在目录逻辑,正确解析路径 пре 1 година
  fuyuchuan e76ef05525 消息中心新增发布人数据返回;个人消息删除接口 пре 1 година
  zhaojinyu 27998f4db2 修改服务录入方式,根据服务所在目录扫描录入的服务名称 пре 1 година
  zhaojinyu 32919713f2 更改代码结构,创建目录将代码分类存放 пре 1 година
  fuyuchuan ed789791e3 修复工作报告消息中心发送异常问题 пре 1 година
  zhaojinyu 475dccfd41 添加检测本地服务版本从远程获取更新功能 пре 1 година
  fuyuchuan 2fccc22339 修复租户切换导致报错 пре 1 година
  gez 86256b2ae0 Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 1 година
  hanzhengyi 9e3a646c72 Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 1 година
  fuyuchuan 7f8bf9ae7f 通知公告表新增tenant_id字段,通知列表增加是否为接收部门成员筛选;用户角色表新增tenant_id字段;统一用户多个角色菜单显示异常问题修复 пре 1 година
  zhaojinyu 11c735da1b 查询分页未生效问题解决 пре 1 година
  zhaojinyu 69486e93da 修改删除与更新操作后响应类 пре 1 година
  gez a3de469dc2 Merge branch 'system-zjy' of uskycloud/usky-cloud into master пре 1 година
  zhaojinyu bb27f8d732 修改file查询接口返回格式,解决返回总数为0问题,删除传参改为id пре 1 година
  gez 7255b39dc3 Merge branch 'system-zjy' of uskycloud/usky-cloud into master пре 1 година
  zhaojinyu 8e9f79f670 移除Ai模块 пре 1 година
  gez 5ab687398c Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 1 година
  zhaojinyu 6788389d5d 去掉递增值表相关代码 пре 1 година
  zhaojinyu ce0a201ea6 添加查询时按照创建时间倒序排列 пре 1 година
  zhaojinyu 997c0d3304 完善查询条件 пре 1 година
  fuyuchuan 3ae3342bc5 Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 1 година
  fuyuchuan 9ea96c9a1f 通知公告列表添加租户筛选条件 пре 1 година
  fuyuchuan acb997c31a Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 1 година
  zhaojinyu 418968a14e 添加查询条件 пре 1 година
  fuyuchuan 49415e6428 同一用户多个角色数据权限异常问题修复;改造通知公告代码,调用新消息中心代码 пре 1 година
  fuyuchuan e1bcaf7c44 同一用户多个角色数据权限异常问题修复;改造通知公告代码,调用新消息中心代码 пре 1 година
  zhaojinyu 0adb1eac83 上传文件删除功能完善 пре 1 година
  zhaojinyu 60793145d4 修复上传文件后无法访问问题 пре 1 година
  hanzhengyi 12322bd205 Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 1 година
  fuyuchuan 7361cd2c61 消息中心代码改造 пре 1 година
  fuyuchuan fda47bfe01 消息中心代码改造 пре 1 година
  zhaojinyu b189011874 修改file上传文件为实现附件管理 пре 1 година
  zhaojinyu 683ad08f06 修改file上传文件 пре 1 година
  zhaojinyu 155145423d 调整 пре 1 година
  zhaojinyu a525f77b89 回退file代码为无修改 пре 1 година
  zhaojinyu 9cf8823016 整理代码并回退file修改 пре 1 година
  fuyuchuan 0e4cc6773b Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 1 година
  fuyuchuan 804eb784f6 通知公告问题修复 пре 1 година
  gez 287e1fb0d9 Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 1 година
  zhaojinyu 3e37b4fa6b 修改服务访问名称 пре 1 година
  zhaojinyu 66883d1f70 修改服务端口 пре 1 година
  zhaojinyu 98443ff879 历史会话传参修改为token пре 1 година
  zhaojinyu 2ef4bc5b0d 修改历史会话查询返回内容格式 пре 1 година
  fuyuchuan 6c45e90edc Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 1 година
  fuyuchuan f61654a20e 通知公告优化改造 пре 1 година
  fuyuchuan 304b40c097 通知公告优化改造 пре 1 година
  zhaojinyu 8d97deb0eb 修改传参及回复内容格式 пре 1 година
  fuyuchuan bc46a8b37e 通知公告优化改造 пре 1 година
  fuyuchuan e6e682ef17 Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 1 година
  fuyuchuan 7c61ef37f9 人员列表接口添加真实姓名查询参数 пре 1 година
  zhaojinyu 228b0aac04 将接口中参数调整为变量设置到nacos配置中 пре 1 година
  zhaojinyu 5cc0ee5356 修改AI大模型内容返回方式,添加html文件进行测试实现流式输出效果 пре 1 година
  gez 53a35123f1 Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 1 година
  fuyuchuan 3a6fcc6e1e Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 1 година
  fuyuchuan e66de0c0d5 定时任务列表接口添加倒序条件;移动端用户注册手机号、用户名、邮箱修改为全平台唯一校验 пре 1 година
  fuyuchuan 6cedf40f12 修复消息列表仅本人数据入库有部门id пре 1 година
  fuyuchuan acdd4458ef Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 1 година
  fuyuchuan cb9b0aeebf 修复新注册用户数据库缺少租户id;新增用户岗位关联数据 пре 1 година
  zhaojinyu 1cb813c99b 更新接口配置 пре 1 година
  zhaojinyu fa64b8a0d1 将接口分为大模型调用、会话ID存储、详细内容存储 пре 1 година
  gez 1ed2f18425 Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 1 година
  fuyuchuan 7fc81271b0 Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 1 година
  fuyuchuan 9de77f4e7b Merge branch 'system-165' into fu-dev пре 1 година
  fuyuchuan 2faed7dc63 消息中心推送消息不成功bug修复” пре 1 година
  gez 96a5815e0e Merge branch 'fu-dev' of uskycloud/usky-cloud into master пре 1 година
  fuyuchuan 04c48ecf87 新增部门数据查询接口,无数据权限;修改默认消息配置代码“ пре 1 година
  unknown e34bd3f2d3 流式输出并将提取content字段的值存入数据库 пре 1 година
  unknown e3309245e7 修改文件名称及添加deeepseeek пре 1 година
  unknown 430e323d5c 添加ai模块接入阿里百炼大模型 пре 1 година
  fuyuchuan b2deccaf6b Merge branch 'master' of http://47.111.81.118:3000/uskycloud/usky-cloud into fu-dev пре 1 година
  gez 954ce7b39c Merge branch 'system-zyj' of uskycloud/usky-cloud into master пре 1 година
  james 05cfbbce1d Merge branch 'system-zyj' into system-165 пре 1 година
  james 65357cfec8 Merge branch 'system-zyj' into system-165 пре 1 година
  james addd134c65 Merge branch 'system-zyj' into system-165 пре 1 година
  james 3cf0e072a0 Merge branch 'system-zyj' into system-165 пре 1 година
  james 71a16b3213 Merge branch 'system-zyj' into system-165 пре 1 година
  fuyuchuan 9b99b424e9 Merge branch 'master' into fu-dev пре 1 година
  gez 56b0d90f9b Merge branch 'han' of uskycloud/usky-cloud into master пре 1 година
  hanzhengyi 235315980d Merge branch 'han' пре 1 година
  fuyuchuan a34f7c8f12 Merge branch 'master' into fu-dev пре 1 година
  gez d2ab8b5255 Merge branch 'system-zyj' of uskycloud/usky-cloud into master пре 1 година
  james dda36c7ed1 Merge branch 'system-zyj' into system-165 пре 1 година
  hanzhengyi cd8e558c47 Merge branch 'han' of uskycloud/usky-cloud into system-165 пре 1 година
  hanzhengyi 331e60214e 解决冲突 пре 1 година
  hanzhengyi 9365966231 修复租户切换时租户未更新、部分手机号无法直接登录问题 пре 1 година
  fuyuchuan 61a646e2cc Merge branch 'master' into fu-dev пре 1 година
  gez e5e810e332 Merge branch 'system-zyj' of uskycloud/usky-cloud into master пре 1 година
  james 7c2ca6862f Merge branch 'system-zyj' into system-165 пре 1 година
  james c2523b3d40 Merge branch 'system-165' of http://47.111.81.118:3000/uskycloud/usky-cloud into system-165 пре 1 година
  james 4c89556593 Merge branch 'han' into system-165 пре 1 година
  hanzhengyi ccfc5f7ed1 Merge branch 'han' of uskycloud/usky-cloud into system-165 пре 1 година
  fuyuchuan b33d94f36d Merge branch 'master' of http://47.111.81.118:3000/uskycloud/usky-cloud into fu-dev пре 1 година
  James 70e5a6dc83 Merge branch 'system-zyj' of uskycloud/usky-cloud into system-165 пре 1 година
  hanzhengyi 834855a4ea Merge branch 'master' into system-165 пре 1 година
  ZJY cdb72f2fde 一键强退用户所有token接口传参方式变更 пре 1 година
  ZJY 2afb202d82 删除部分失效代码 пре 1 година
  hanzhengyi b5a33ea590 Merge branch 'system-zjy' of uskycloud/usky-cloud into system-165 пре 1 година
  fuyuchuan 5c615473e8 Merge branch 'master' of http://47.111.81.118:3000/uskycloud/usky-cloud into fu-dev пре 1 година
  fuyuchuan aa8c2710da 下拉树返回类型泛型添加 пре 1 година
  hanzhengyi 458c39e19f Merge branch 'han' of uskycloud/usky-cloud into system-165 пре 1 година
  hanzhengyi b32470e484 Merge branch 'fu-dev' of uskycloud/usky-cloud into system-165 пре 1 година
  hanzhengyi 3ed3588869 Merge branch 'system-zjy' of uskycloud/usky-cloud into system-165 пре 1 година
  hanzhengyi ba9f676b7f Merge branch 'han' of uskycloud/usky-cloud into system-165 пре 1 година
  hanzhengyi b4e3b722f8 Merge branch 'han' of uskycloud/usky-cloud into system-165 пре 1 година
  hanzhengyi 206f5a2a2f Merge branch 'han' of uskycloud/usky-cloud into system-165 пре 1 година
  hanzhengyi 1107435c1e Merge branch 'system-zjy' of uskycloud/usky-cloud into system-165 пре 1 година
100 измењених фајлова са 4855 додато и 1079 уклоњено
  1. 1 1
      base-common/ruoyi-common-datascope/src/main/java/com/ruoyi/common/datascope/aspect/DataScopeAspect.java
  2. 11 0
      base-components/monitor/pom.xml
  3. 67 0
      base-components/monitor/src/main/java/com/ruoyi/modules/monitor/notify/DingTalkNotifier.java
  4. 100 0
      base-components/monitor/src/main/java/com/ruoyi/modules/monitor/notify/ServiceChangeNotifier.java
  5. 41 11
      base-modules/service-file/pom.xml
  6. 42 5
      base-modules/service-file/src/main/java/com/ruoyi/file/RuoYiFileApplication.java
  7. 82 82
      base-modules/service-file/src/main/java/com/ruoyi/file/config/MinioConfig.java
  8. 16 0
      base-modules/service-file/src/main/java/com/ruoyi/file/config/MybatisPlusConfig.java
  9. 2 2
      base-modules/service-file/src/main/java/com/ruoyi/file/config/ResourcesConfig.java
  10. 19 0
      base-modules/service-file/src/main/java/com/ruoyi/file/config/WebConfig.java
  11. 127 0
      base-modules/service-file/src/main/java/com/ruoyi/file/controller/FileUpdateInfoController.java
  12. 156 0
      base-modules/service-file/src/main/java/com/ruoyi/file/controller/FilesController.java
  13. 47 47
      base-modules/service-file/src/main/java/com/ruoyi/file/controller/SysFileController.java
  14. 82 0
      base-modules/service-file/src/main/java/com/ruoyi/file/domain/FileUpdateInfo.java
  15. 14 0
      base-modules/service-file/src/main/java/com/ruoyi/file/domain/FileWithId.java
  16. 50 0
      base-modules/service-file/src/main/java/com/ruoyi/file/domain/FilesUpload.java
  17. 9 0
      base-modules/service-file/src/main/java/com/ruoyi/file/mapper/FileUpdateInfoMapper.java
  18. 10 0
      base-modules/service-file/src/main/java/com/ruoyi/file/mapper/FilesMapper.java
  19. 42 42
      base-modules/service-file/src/main/java/com/ruoyi/file/service/FastDfsSysFileServiceImpl.java
  20. 50 0
      base-modules/service-file/src/main/java/com/ruoyi/file/service/FileUpdateInfoService.java
  21. 30 0
      base-modules/service-file/src/main/java/com/ruoyi/file/service/FileUploadResponse.java
  22. 19 0
      base-modules/service-file/src/main/java/com/ruoyi/file/service/FilesService.java
  23. 20 20
      base-modules/service-file/src/main/java/com/ruoyi/file/service/ISysFileService.java
  24. 50 50
      base-modules/service-file/src/main/java/com/ruoyi/file/service/LocalSysFileServiceImpl.java
  25. 416 0
      base-modules/service-file/src/main/java/com/ruoyi/file/service/impl/FileUpdateInfoServiceImpl.java
  26. 241 0
      base-modules/service-file/src/main/java/com/ruoyi/file/service/impl/FilesServiceImpl.java
  27. 202 202
      base-modules/service-file/src/main/java/com/ruoyi/file/utils/FileUploadUtils.java
  28. 1 1
      base-modules/service-file/src/main/resources/bootstrap.yml
  29. 5 0
      base-modules/service-file/src/main/resources/mapper/file/FilesMapper.xml
  30. 1 0
      base-modules/service-job/src/main/resources/mapper/job/SysJobMapper.xml
  31. 17 4
      base-modules/service-system/service-system-api/src/main/java/com/usky/system/RemoteMceService.java
  32. 125 0
      base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/MceRequestVO.java
  33. 7 0
      base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/SysOperLogVO.java
  34. 25 0
      base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/SysPerson.java
  35. 24 0
      base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/SysPersonVo.java
  36. 13 0
      base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/SysUserVO.java
  37. 12 10
      base-modules/service-system/service-system-api/src/main/java/com/usky/system/factory/RemoteMceFallbackFactory.java
  38. 15 3
      base-modules/service-system/service-system-biz/pom.xml
  39. 2 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/RuoYiSystemApplication.java
  40. 8 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/constant/constant.java
  41. 8 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/api/SysMceControllerApi.java
  42. 1 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/AuthorityConfigController.java
  43. 52 19
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/MceReceiveController.java
  44. 12 2
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SendSmsController.java
  45. 9 2
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysDeptController.java
  46. 3 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysMenuController.java
  47. 226 4
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysPersonController.java
  48. 38 28
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysProfileController.java
  49. 26 12
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysUserController.java
  50. 21 3
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysUserPersonController.java
  51. 16 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysUserTenantController.java
  52. 27 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SystemInfoController.java
  53. 21 5
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/TokenController.java
  54. 68 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/Cpu.java
  55. 112 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/Jvm.java
  56. 47 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/Mem.java
  57. 41 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/Sys.java
  58. 53 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysFile.java
  59. 7 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysMenu.java
  60. 153 32
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysNotice.java
  61. 47 2
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysPerson.java
  62. 10 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysPlatform.java
  63. 12 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysTenant.java
  64. 27 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysUser.java
  65. 6 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysUserPerson.java
  66. 22 15
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysUserRole.java
  67. 185 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SystemHardwareInfo.java
  68. 8 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysDeptMapper.java
  69. 3 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysMenuMapper.java
  70. 9 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysMobileMenuMapper.java
  71. 1 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysPlatformMenuMapper.java
  72. 2 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysPostMapper.java
  73. 4 2
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysRoleMapper.java
  74. 2 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysTenantConfigMapper.java
  75. 6 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysUserMapper.java
  76. 4 4
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysUserRoleMapper.java
  77. 11 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/ISysDeptService.java
  78. 1 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/ISysMenuService.java
  79. 1 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/ISysRoleService.java
  80. 1 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/ISysUserService.java
  81. 3 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/MceContentService.java
  82. 14 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/MceReceiveService.java
  83. 43 24
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysLoginService.java
  84. 13 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysPersonService.java
  85. 1 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysUserPersonService.java
  86. 12 4
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysUserTenantService.java
  87. 17 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/config/Gzip/GzipConfig.java
  88. 81 9
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/MceContentServiceImpl.java
  89. 144 49
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/MceMbuserServiceImpl.java
  90. 579 77
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/MceReceiveServiceImpl.java
  91. 15 8
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysDeptServiceImpl.java
  92. 165 243
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysMenuServiceImpl.java
  93. 1 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysMobileMenuServiceImpl.java
  94. 71 31
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysNoticeServiceImpl.java
  95. 129 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysPersonServiceImpl.java
  96. 17 7
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysPlatformMenuServiceImpl.java
  97. 2 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysPlatformServiceImpl.java
  98. 7 4
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysRoleServiceImpl.java
  99. 2 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysUserOnlineServiceImpl.java
  100. 35 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysUserPersonServiceImpl.java

+ 1 - 1
base-common/ruoyi-common-datascope/src/main/java/com/ruoyi/common/datascope/aspect/DataScopeAspect.java

@@ -101,7 +101,7 @@ public class DataScopeAspect
             else if (DATA_SCOPE_CUSTOM.equals(dataScope))
             {
                 sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, role.getRoleId()));
-                sqlLambda.append(StringUtils.format(" OR dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, role.getRoleId()));
+                sqlLambda.append(StringUtils.format(" OR dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", role.getRoleId()));
             }
             else if (DATA_SCOPE_DEPT.equals(dataScope))
             {

+ 11 - 0
base-components/monitor/pom.xml

@@ -22,6 +22,12 @@
             <artifactId>spring-boot-admin-starter-server</artifactId>
             <version>${spring-boot-admin.version}</version>
         </dependency>
+
+        <!--增加安全防护,防止别人随便进-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
 		
         <!-- SpringCloud Alibaba Nacos -->
         <dependency>
@@ -52,6 +58,11 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-security</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-webflux</artifactId>
+        </dependency>
 		
     </dependencies>
 

+ 67 - 0
base-components/monitor/src/main/java/com/ruoyi/modules/monitor/notify/DingTalkNotifier.java

@@ -0,0 +1,67 @@
+package com.ruoyi.modules.monitor.notify;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Mono;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.time.Instant;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class DingTalkNotifier {
+
+    @Value("${dingtalk.webhook}")
+    private String webhook;
+
+    @Value("${dingtalk.secret:}")
+    private String secret;
+
+    private final WebClient webClient = WebClient.create();
+
+    public Mono<Void> sendMarkdown(String title, String content) {
+        String url = buildUrlWithSign();
+
+        Map<String, Object> markdownMsg = new HashMap<>();
+        markdownMsg.put("msgtype", "markdown");
+
+        Map<String, String> markdown = new HashMap<>();
+        markdown.put("title", title);
+        markdown.put("text", content);
+
+        markdownMsg.put("markdown", markdown);
+
+        return webClient.post()
+                .uri(url)
+                .contentType(MediaType.APPLICATION_JSON)
+                .body(BodyInserters.fromValue(markdownMsg))
+                .retrieve()
+                .bodyToMono(String.class)
+                .then();
+    }
+
+    private String buildUrlWithSign() {
+        if (secret == null || secret.trim().isEmpty()) {
+            return webhook;
+        }
+        long timestamp = Instant.now().toEpochMilli();
+        String stringToSign = timestamp + "\n" + secret;
+        try {
+            Mac mac = Mac.getInstance("HmacSHA256");
+            mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
+            byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
+            String sign = URLEncoder.encode(new String(Base64.getEncoder().encode(signData)), String.valueOf(StandardCharsets.UTF_8));
+            return webhook + "&timestamp=" + timestamp + "&sign=" + sign;
+        } catch (Exception e) {
+            throw new RuntimeException("生成钉钉签名失败", e);
+        }
+    }
+}

+ 100 - 0
base-components/monitor/src/main/java/com/ruoyi/modules/monitor/notify/ServiceChangeNotifier.java

@@ -0,0 +1,100 @@
+package com.ruoyi.modules.monitor.notify;
+
+import de.codecentric.boot.admin.server.domain.entities.Instance;
+import de.codecentric.boot.admin.server.domain.entities.InstanceRepository;
+import de.codecentric.boot.admin.server.domain.events.InstanceEvent;
+import de.codecentric.boot.admin.server.domain.events.InstanceStatusChangedEvent;
+import de.codecentric.boot.admin.server.notify.AbstractStatusChangeNotifier;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class ServiceChangeNotifier extends AbstractStatusChangeNotifier {
+
+    private final DingTalkNotifier dingTalkNotifier;
+    private final InstanceRepository repository;
+
+    /* 新增字段 */
+    private final ConcurrentHashMap<String, Instance> buffer = new ConcurrentHashMap<>();
+    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
+
+
+    public ServiceChangeNotifier(InstanceRepository repository,
+                                 DingTalkNotifier dingTalkNotifier) {
+        super(repository);
+        this.repository = repository;
+        this.dingTalkNotifier = dingTalkNotifier;
+
+        /* 每 5 秒聚合发送一次(可按需调整) */
+        scheduler.scheduleWithFixedDelay(this::flush, 5, 5, TimeUnit.SECONDS);
+    }
+
+    @Override
+    protected boolean shouldNotify(InstanceEvent event, Instance instance) {
+        return event instanceof InstanceStatusChangedEvent;
+    }
+
+    @Override
+    protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
+        /* 仅把实例放进 buffer,不做实际推送 */
+        buffer.put(String.valueOf(instance.getId()), instance);
+        return Mono.empty();
+    }
+
+    private void flush() {
+        if (buffer.isEmpty()) {
+            return;
+        }
+
+        /* 拿到此刻的快照,然后清空 buffer */
+        List<Instance> snapshot = new ArrayList<>(buffer.values());
+        buffer.clear();
+
+        /* 计算每个实例的 total,并排序 */
+        Map<Instance, Long> totalMap = new HashMap<>();
+        for (Instance inst : snapshot) {
+            long total = repository.findAll().collectList().block().size(); // 这里简单起见直接 block
+            totalMap.put(inst, total);
+        }
+
+        snapshot.sort(Comparator.comparing(totalMap::get));
+
+        /* 依次发送钉钉 */
+        for (Instance instance : snapshot) {
+            sendOne(instance);
+        }
+    }
+
+    private void sendOne(Instance instance) {
+        String serviceName = instance.getRegistration().getName();
+        String newStatus   = instance.getStatusInfo().getStatus();
+        String serviceUrl  = instance.getRegistration().getServiceUrl();
+        String time        = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
+
+        List<Instance> all = repository.findAll().collectList().block();
+        long total   = all.size();
+        long online  = all.stream().filter(i -> "UP".equals(i.getStatusInfo().getStatus())).count();
+        long offline = total - online;
+
+        /* 根据状态决定颜色 */
+        String icon = "UP".equalsIgnoreCase(newStatus)
+                ? "<font color=\"#00ff00\">✅</font>"
+                : "<font color=\"#ff0000\">🚨</font>";
+
+        String markdown = "### " + icon + " 服务状态变更告警\n" +
+                "- **服务名**: " + serviceName + "  \n" +
+                "- **当前状态**: " + newStatus + "  \n" +
+                "- **地址**: " + serviceUrl + "  \n" +
+                "- **时间**: " + time + "  \n" +
+                "- **统计**: 总 " + total + ",在线 " + online + ",离线 " + offline;
+
+        dingTalkNotifier.sendMarkdown("服务状态变更", markdown).subscribe();
+    }
+}

+ 41 - 11
base-modules/service-file/pom.xml

@@ -1,10 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xmlns="http://maven.apache.org/POM/4.0.0"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <groupId>com.usky</groupId>
         <artifactId>base-modules</artifactId>
+        <groupId>com.usky</groupId>
         <version>0.0.1</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
@@ -48,11 +46,11 @@
         </dependency>
         
         <!-- Minio -->
-        <dependency>
-            <groupId>io.minio</groupId>
-            <artifactId>minio</artifactId>
-            <version>${minio.version}</version>
-        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>io.minio</groupId>-->
+<!--            <artifactId>minio</artifactId>-->
+<!--            <version>${minio.version}</version>-->
+<!--        </dependency>-->
         
         <!-- RuoYi Api System -->
         <dependency>
@@ -72,7 +70,24 @@
         </dependency>
         <dependency>
             <groupId>com.usky</groupId>
-            <artifactId>ruoyi-common-core</artifactId>
+            <artifactId>common-cloud-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>2.1.4</version>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.7.36</version>
         </dependency>
 
     </dependencies>
@@ -92,7 +107,22 @@
                     </execution>
                 </executions>
             </plugin>
+            <plugin>
+                <groupId>com.github.shalousun</groupId>
+                <artifactId>smart-doc-maven-plugin</artifactId>
+                <version>2.1.1</version>
+                <configuration>
+                    <!--指定生成文档的使用的配置文件,配置文件放在自己的项目中-->
+                    <configFile>./src/main/resources/smart-doc.json</configFile>
+                    <!--指定项目名称-->
+                    <projectName>test</projectName>
+                    <!--                    <excludes>-->
+                    <!--                        <exclude>com.bizmatics:product-service-provider</exclude>-->
+                    <!--                        <exclude>cn.afterturn:easypoi-web</exclude>-->
+                    <!--                    </excludes>-->
+                </configuration>
+            </plugin>
         </plugins>
     </build>
-   
+
 </project>

+ 42 - 5
base-modules/service-file/src/main/java/com/ruoyi/file/RuoYiFileApplication.java

@@ -1,21 +1,58 @@
 package com.ruoyi.file;
 
+import org.mybatis.spring.annotation.MapperScan;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
 import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.core.env.Environment;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 
 /**
  * 文件服务
  * 
  * @author ruoyi
  */
+//@EnableCustomSwagger2
+//@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
+//public class RuoYiFileApplication
+//{
+//    public static void main(String[] args)
+//    {
+//        SpringApplication.run(RuoYiFileApplication.class, args);
+//    }
+//}
+
+
 @EnableCustomSwagger2
-@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
+@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
+@EnableFeignClients(basePackages = {"com.ruoyi"})
+@MapperScan(value = "com.ruoyi.file.mapper")
+@ComponentScan(basePackages = {"com.ruoyi"})
+@SpringBootApplication
 public class RuoYiFileApplication
 {
-    public static void main(String[] args)
-    {
-        SpringApplication.run(RuoYiFileApplication.class, args);
+    private static final Logger LOGGER = LoggerFactory.getLogger(RuoYiFileApplication.class);
+
+    public static void main(String[] args) throws UnknownHostException {
+        ConfigurableApplicationContext application = SpringApplication.run(RuoYiFileApplication.class, args);
+        Environment env = application.getEnvironment();
+        String ip = InetAddress.getLocalHost().getHostAddress();
+        String port = env.getProperty("server.port");
+        String path = env.getProperty("server.servlet.context-path");
+        LOGGER.info("\n----------------------------------------------------------\n\t" +
+                "Application is running! Access URLs:\n\t" +
+                "Local: \t\thttp://localhost:" + port + (null==path?"":path) + "/\n\t" +
+                "External: \thttp://" + ip + ":" + port + (null==path?"":path) + "/\n\t" +
+                "Api: \t\thttp://" + ip + ":" + port + (null==path?"":path) + "/swagger-ui/index.html\n\t" +
+                "----------------------------------------------------------");
     }
-}
+}

+ 82 - 82
base-modules/service-file/src/main/java/com/ruoyi/file/config/MinioConfig.java

@@ -1,82 +1,82 @@
-package com.ruoyi.file.config;
-
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import io.minio.MinioClient;
-
-/**
- * Minio 配置信息
- *
- * @author ruoyi
- */
-@Configuration
-@ConfigurationProperties(prefix = "minio")
-public class MinioConfig
-{
-    /**
-     * 服务地址
-     */
-    private String url;
-
-    /**
-     * 用户名
-     */
-    private String accessKey;
-
-    /**
-     * 密码
-     */
-    private String secretKey;
-
-    /**
-     * 存储桶名称
-     */
-    private String bucketName;
-
-    public String getUrl()
-    {
-        return url;
-    }
-
-    public void setUrl(String url)
-    {
-        this.url = url;
-    }
-
-    public String getAccessKey()
-    {
-        return accessKey;
-    }
-
-    public void setAccessKey(String accessKey)
-    {
-        this.accessKey = accessKey;
-    }
-
-    public String getSecretKey()
-    {
-        return secretKey;
-    }
-
-    public void setSecretKey(String secretKey)
-    {
-        this.secretKey = secretKey;
-    }
-
-    public String getBucketName()
-    {
-        return bucketName;
-    }
-
-    public void setBucketName(String bucketName)
-    {
-        this.bucketName = bucketName;
-    }
-
-    @Bean
-    public MinioClient getMinioClient()
-    {
-        return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();
-    }
-}
+//package com.ruoyi.file.config;
+//
+//import org.springframework.boot.context.properties.ConfigurationProperties;
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import io.minio.MinioClient;
+//
+///**
+// * Minio 配置信息
+// *
+// * @author ruoyi
+// */
+//@Configuration
+//@ConfigurationProperties(prefix = "minio")
+//public class MinioConfig
+//{
+//    /**
+//     * 服务地址
+//     */
+//    private String url;
+//
+//    /**
+//     * 用户名
+//     */
+//    private String accessKey;
+//
+//    /**
+//     * 密码
+//     */
+//    private String secretKey;
+//
+//    /**
+//     * 存储桶名称
+//     */
+//    private String bucketName;
+//
+//    public String getUrl()
+//    {
+//        return url;
+//    }
+//
+//    public void setUrl(String url)
+//    {
+//        this.url = url;
+//    }
+//
+//    public String getAccessKey()
+//    {
+//        return accessKey;
+//    }
+//
+//    public void setAccessKey(String accessKey)
+//    {
+//        this.accessKey = accessKey;
+//    }
+//
+//    public String getSecretKey()
+//    {
+//        return secretKey;
+//    }
+//
+//    public void setSecretKey(String secretKey)
+//    {
+//        this.secretKey = secretKey;
+//    }
+//
+//    public String getBucketName()
+//    {
+//        return bucketName;
+//    }
+//
+//    public void setBucketName(String bucketName)
+//    {
+//        this.bucketName = bucketName;
+//    }
+//
+//    @Bean
+//    public MinioClient getMinioClient()
+//    {
+//        return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();
+//    }
+//}

+ 16 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/config/MybatisPlusConfig.java

@@ -0,0 +1,16 @@
+package com.ruoyi.file.config;
+
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class MybatisPlusConfig {
+    @Bean
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
+        return interceptor;
+    }
+}

+ 2 - 2
base-modules/service-file/src/main/java/com/ruoyi/file/config/ResourcesConfig.java

@@ -9,7 +9,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 /**
  * 通用映射配置
- * 
+ *
  * @author ruoyi
  */
 @Configuration
@@ -34,7 +34,7 @@ public class ResourcesConfig implements WebMvcConfigurer
         registry.addResourceHandler(localFilePrefix + "/**")
                 .addResourceLocations("file:" + localFilePath + File.separator);
     }
-    
+
     /**
      * 开启跨域
      */

+ 19 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/config/WebConfig.java

@@ -0,0 +1,19 @@
+package com.ruoyi.file.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.format.FormatterRegistry;
+import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.time.format.DateTimeFormatter;
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+    @Override
+    public void addFormatters(FormatterRegistry registry) {
+        DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
+        registrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+        registrar.registerFormatters(registry);
+    }
+}

+ 127 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/controller/FileUpdateInfoController.java

@@ -0,0 +1,127 @@
+package com.ruoyi.file.controller;
+
+import com.ruoyi.file.domain.FileUpdateInfo;
+import com.ruoyi.file.domain.FileWithId;
+import com.ruoyi.file.service.FileUpdateInfoService;
+import com.usky.common.core.bean.ApiResult;
+import com.usky.common.core.bean.CommonPage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/api/update")
+public class FileUpdateInfoController {
+
+    @Autowired
+    private FileUpdateInfoService fileUpdateInfoService;
+
+    //增加服务信息
+    @PostMapping("/add")
+    public ApiResult<String> addFileToDatabase(@RequestBody FileUpdateInfo fileUpdateInfo) {
+        try {
+            fileUpdateInfoService.addFileToDatabase(fileUpdateInfo);
+            return ApiResult.success("文件信息录入成功");
+        } catch (Exception e) {
+            return ApiResult.error("文件信息录入失败: " + e.getMessage());
+        }
+    }
+
+    //检查服务版本
+    @PostMapping("/checkById")
+    public ApiResult<String> checkFileUpdate(@RequestParam Long id) {
+        try {
+            boolean isUpdateRequired = fileUpdateInfoService.checkFileUpdate(id);
+            String result = isUpdateRequired ? "待更新" : "无需更新";
+            return ApiResult.success(result);
+        } catch (Exception e) {
+            return ApiResult.error("检查文件更新失败:远程仓库未找到对应服务");
+        }
+    }
+
+    //下载更新服务
+    @PostMapping("/reloadById")
+    public ApiResult<String> performFileUpdate(@RequestParam Long id) {
+        try {
+            fileUpdateInfoService.performFileUpdate(id);
+            return ApiResult.success("文件更新成功");
+        } catch (Exception e) {
+            return ApiResult.error("文件更新失败," + e.getMessage());
+        }
+    }
+
+    //查询服务信息
+    @GetMapping("/query")
+    public ApiResult<CommonPage<FileUpdateInfo>> queryFiles(
+            @RequestParam(required = false) String fileName,
+            @RequestParam(required = false, defaultValue = "1") int current,
+            @RequestParam(required = false, defaultValue = "10") int size) {
+        try {
+            CommonPage<FileUpdateInfo> commonPage;
+            if (fileName == null || fileName.trim().isEmpty()) {
+                commonPage = fileUpdateInfoService.getAllFiles(current, size);
+            } else {
+                commonPage = fileUpdateInfoService.getFilesByFileNameContaining(fileName, current, size);
+            }
+            return ApiResult.success(commonPage);
+        } catch (Exception e) {
+            return ApiResult.error("查询文件信息失败: " + e.getMessage());
+        }
+    }
+
+    //删除服务信息
+    @DeleteMapping("/deleteById")
+    public ApiResult<String> deleteFileById(@RequestParam Long id) {
+        try {
+            fileUpdateInfoService.deleteFileById(id);
+            return ApiResult.success("文件信息删除成功");
+        } catch (Exception e) {
+            return ApiResult.error("删除文件信息失败: " + e.getMessage());
+        }
+    }
+
+    //控制服务运行状态(启动start、停止stop、重启restart)
+    @PostMapping("/controlById")
+    public ApiResult<String> controlServiceById(@RequestParam Long id, @RequestParam String action) {
+        try {
+            FileUpdateInfo fileUpdateInfo = fileUpdateInfoService.getFileById(id);
+            if (fileUpdateInfo == null) {
+                return ApiResult.error("未找到对应的文件信息,ID: " + id);
+            }
+            String fileName = fileUpdateInfo.getFileName();
+
+            // 在控制服务之前,先检测当前服务状态
+            int currentStatus = fileUpdateInfoService.getFileStatus(fileName);
+            if ((action.equals("start") && currentStatus == 1) || (action.equals("stop") && currentStatus == 2)) {
+                return ApiResult.error("服务已经是目标状态,无需重复操作");
+            }
+
+            fileUpdateInfoService.controlApplication(fileName, action);
+
+            // 根据 action 返回不同的成功消息
+            if ("start".equalsIgnoreCase(action)) {
+                return ApiResult.success("启动成功");
+            } else if ("stop".equalsIgnoreCase(action)) {
+                return ApiResult.success("停止成功");
+            } else if ("restart".equalsIgnoreCase(action)) {
+                return ApiResult.success("重启成功");
+            } else {
+                return ApiResult.success(action + "命令已发送");
+            }
+        } catch (Exception e) {
+            return ApiResult.error("控制服务失败: " + e.getMessage());
+        }
+    }
+
+    // 扫描服务所在目录下的文件
+    @GetMapping("/scan")
+    public ApiResult<CommonPage<FileWithId>> scanFilesInServiceDir(
+            @RequestParam(required = false, defaultValue = "1") int current,
+            @RequestParam(required = false, defaultValue = "10") int size) {
+        try {
+            CommonPage<FileWithId> fileNamesPage = fileUpdateInfoService.scanFilesInServiceDir(current, size);
+            return ApiResult.success(fileNamesPage);
+        } catch (Exception e) {
+            return ApiResult.error("扫描文件失败: " + e.getMessage());
+        }
+    }
+}

+ 156 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/controller/FilesController.java

@@ -0,0 +1,156 @@
+package com.ruoyi.file.controller;
+
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.file.service.FileUploadResponse;
+import com.ruoyi.file.domain.FilesUpload;
+import com.ruoyi.file.service.FilesService;
+import com.usky.common.core.bean.ApiResult;
+import com.usky.common.core.bean.CommonPage;
+import com.usky.common.security.utils.SecurityUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import java.net.URL;
+import java.time.LocalDateTime;
+import java.util.Enumeration;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+
+
+@RestController
+//@RequestMapping("/files")
+public class FilesController {
+
+    @Autowired
+    private FilesService filesService;
+
+    @PostMapping("/upload")
+    public ApiResult<FileUploadResponse> upload(@RequestParam MultipartFile file, HttpServletRequest request) {
+        // 打印所有请求头,以便调试
+/*        Enumeration<String> headerNames = request.getHeaderNames();
+        while (headerNames.hasMoreElements()) {
+            String headerName = headerNames.nextElement();
+            String headerValue = request.getHeader(headerName);
+            System.out.println(headerName + ": " + headerValue);
+        }*/
+
+        // 从请求头中获取 userid
+        String useridStr = request.getHeader("user_id");
+
+        Long userid = null; // 初始化为 null
+        if (useridStr != null && !useridStr.isEmpty()) {
+            try {
+                // 尝试将 userid 转换为 Long 类型
+                userid = Long.parseLong(useridStr);
+            } catch (NumberFormatException e) {
+                // 如果转换失败,打印错误信息并保持 userid 为 null
+                System.out.println("无法将 user_id 转换为 Long 类型: " + useridStr);
+            }
+        }
+
+        // 从请求头中获取 username
+        String username = request.getHeader("username");
+
+        // 如果用户名为空或解码失败,设置为“未知用户”
+        if (username == null || username.isEmpty()) {
+            username = "未知用户";
+        } else {
+            try {
+                // 使用 URLDecoder 解码用户名
+                username = URLDecoder.decode(username, StandardCharsets.UTF_8.name());
+            } catch (Exception e) {
+                // 如果解码失败,设置为“未知用户”
+                username = "未知用户";
+            }
+        }
+
+        // 从请求头中获取 referer
+        String referer = request.getHeader("referer");
+        String refererPath = "";
+        if (referer != null && !referer.isEmpty()) {
+            try {
+                // 提取 referer 的路径部分
+                URL url = new URL(referer);
+                refererPath = url.getPath();
+            } catch (Exception e) {
+                System.out.println("无法解析 referer URL: " + referer);
+            }
+        }
+
+        // 打印 referer 路径部分
+//        System.out.println("Referer 路径部分: " + refererPath);
+
+        // 继续处理文件上传逻辑
+        FileUploadResponse response = filesService.upload(file, userid, username, refererPath);
+        return ApiResult.success(response);
+    }
+
+
+    @DeleteMapping("/delete/{id}")
+    public ApiResult<String> delete(@PathVariable Integer id, HttpServletRequest request) {
+        // 打印所有请求头,以便调试
+/*        Enumeration<String> headerNames = request.getHeaderNames();
+        while (headerNames.hasMoreElements()) {
+            String headerName = headerNames.nextElement();
+            String headerValue = request.getHeader(headerName);
+            System.out.println(headerName + ": " + headerValue);
+        }*/
+
+        // 从请求头中获取 userid
+        String useridStr = request.getHeader("user_id");
+
+        Long userid = null; // 初始化为 null
+        if (useridStr != null && !useridStr.isEmpty()) {
+            try {
+                // 尝试将 userid 转换为 Long 类型
+                userid = Long.parseLong(useridStr);
+            } catch (NumberFormatException e) {
+                // 如果转换失败,打印错误信息并保持 userid 为 null
+                System.out.println("无法将 user_id 转换为 Long 类型: " + useridStr);
+            }
+        }
+
+        // 从请求头中获取username
+        String username = request.getHeader("username");
+
+        // 如果用户名为空或解码失败,设置为“未知用户”
+        if (username == null || username.isEmpty()) {
+            username = "未知用户";
+        } else {
+            try {
+                // 使用 URLDecoder 解码用户名
+                username = URLDecoder.decode(username, StandardCharsets.UTF_8.name());
+            } catch (Exception e) {
+                // 如果解码失败,设置为“未知用户”
+                username = "未知用户";
+            }
+        }
+
+        try {
+            filesService.deleteFile(id, userid, username);
+            return ApiResult.success("删除成功");
+        } catch (Exception e) {
+            return ApiResult.error("删除失败"); // 删除失败,返回错误信息
+        }
+    }
+
+    @GetMapping("/query")
+    public R<CommonPage<FilesUpload>> queryFiles(
+            @RequestParam(required = false) String filesName,
+            @RequestParam(required = false) LocalDateTime startTime,
+            @RequestParam(required = false) LocalDateTime endTime,
+            @RequestParam(required = false) Boolean isDeleted,
+            @RequestParam(required = false) String fileType,
+            @RequestParam(required = false) String userName,
+            @RequestParam int current,
+            @RequestParam int size) {
+
+        // 调用服务层方法
+        CommonPage<FilesUpload> resultPage = filesService.queryFiles(filesName, startTime, endTime, isDeleted, fileType, userName, current, size);
+
+        // 返回封装好的分页结果
+        return R.ok(resultPage);
+    }
+}

+ 47 - 47
base-modules/service-file/src/main/java/com/ruoyi/file/controller/SysFileController.java

@@ -1,47 +1,47 @@
-package com.ruoyi.file.controller;
-
-import com.ruoyi.common.core.domain.R;
-import com.usky.system.domain.SysFileVO;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.multipart.MultipartFile;
-import com.ruoyi.file.service.ISysFileService;
-import com.ruoyi.common.core.utils.file.FileUtils;
-
-/**
- * 文件请求处理
- * @author ruoyi
- */
-@RestController
-public class SysFileController
-{
-    private static final Logger log = LoggerFactory.getLogger(SysFileController.class);
-
-    @Autowired
-    private ISysFileService sysFileService;
-
-    /**
-     * 文件上传请求
-     */
-    @PostMapping("upload")
-    public R<SysFileVO> upload(MultipartFile file)
-    {
-        try
-        {
-            // 上传并返回访问地址
-            String url = sysFileService.uploadFile(file);
-            SysFileVO sysFile = new SysFileVO();
-            sysFile.setName(FileUtils.getName(url));
-            sysFile.setUrl(url);
-            return R.ok(sysFile);
-        }
-        catch (Exception e)
-        {
-            log.error("上传文件失败", e);
-            return R.fail(e.getMessage());
-        }
-    }
-}
+//package com.ruoyi.file.controller;
+//
+//import com.ruoyi.common.core.domain.R;
+//import com.usky.system.domain.SysFileVO;
+//import org.slf4j.Logger;
+//import org.slf4j.LoggerFactory;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.web.bind.annotation.PostMapping;
+//import org.springframework.web.bind.annotation.RestController;
+//import org.springframework.web.multipart.MultipartFile;
+//import com.ruoyi.file.service.ISysFileService;
+//import com.ruoyi.common.core.utils.file.FileUtils;
+//
+///**
+// * 文件请求处理
+// * @author ruoyi
+// */
+//@RestController
+//public class SysFileController
+//{
+//    private static final Logger log = LoggerFactory.getLogger(SysFileController.class);
+//
+//    @Autowired
+//    private ISysFileService sysFileService;
+//
+//    /**
+//     * 文件上传请求
+//     */
+//    @PostMapping("upload")
+//    public R<SysFileVO> upload(MultipartFile file)
+//    {
+//        try
+//        {
+//            // 上传并返回访问地址
+//            String url = sysFileService.uploadFile(file);
+//            SysFileVO sysFile = new SysFileVO();
+//            sysFile.setName(FileUtils.getName(url));
+//            sysFile.setUrl(url);
+//            return R.ok(sysFile);
+//        }
+//        catch (Exception e)
+//        {
+//            log.error("上传文件失败", e);
+//            return R.fail(e.getMessage());
+//        }
+//    }
+//}

+ 82 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/domain/FileUpdateInfo.java

@@ -0,0 +1,82 @@
+package com.ruoyi.file.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Data;
+
+import java.io.File;
+import java.net.URL;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("file_update_info")
+public class FileUpdateInfo {
+    private Long id;
+    private String fileName; // 文件名
+    private String fileMd5;
+    private String remoteMd5;
+
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    private int updateStatus;    // 0表示无需更新,1表示待更新
+
+    // 新增版本号字段
+    @TableField(fill = FieldFill.INSERT)
+    private String version = "v1.0.0"; // 默认版本号
+
+    // 新增运行状态字段
+    private int fileStatus; // 0:未知,1:运行中,2:已停止
+
+    // 获取带版本号的文件名
+//    @JsonIgnore // 忽略该字段的序列化
+//    public String getVersionedFileName() {
+//        return fileName.substring(0, fileName.lastIndexOf('.')) + "-" + version + fileName.substring(fileName.lastIndexOf('.'));
+//    }
+
+    // 获取文件完整路径(基于 JAR 文件所在的目录)
+    @JsonIgnore // 忽略该字段的序列化
+    public String getFilePath() {
+        return getServiceDir() + File.separator + fileName;
+    }
+
+    // 动态获取 JAR 文件所在的目录
+    public static String getServiceDir() {
+        try {
+            // 获取当前类的 ClassLoader
+            ClassLoader classLoader = FileUpdateInfo.class.getClassLoader();
+            // 获取当前类的资源路径(例如 JAR 文件路径)
+            URL url = classLoader.getResource(FileUpdateInfo.class.getName().replace('.', '/') + ".class");
+            if (url != null && "jar".equals(url.getProtocol())) {
+                // 从 JAR 文件中获取路径
+                String jarPath = url.getPath();
+                // 去掉 JAR 文件内部路径部分
+                int bangIndex = jarPath.indexOf("!/");
+                if (bangIndex > 0) {
+                    jarPath = jarPath.substring(0, bangIndex);
+                }
+                // 去掉 "file:" 前缀
+                if (jarPath.startsWith("file:")) {
+                    jarPath = jarPath.substring(5);
+                }
+                // 获取 JAR 文件所在的目录
+                return new java.io.File(jarPath).getParent();
+            } else if (url != null && "file".equals(url.getProtocol())) {
+                // 如果是直接运行的文件路径
+                String filePath = url.getPath();
+                return new java.io.File(filePath).getParent();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return System.getProperty("user.dir"); // 如果无法获取 JAR 路径,退回到当前工作目录
+    }
+}

+ 14 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/domain/FileWithId.java

@@ -0,0 +1,14 @@
+package com.ruoyi.file.domain;
+
+import lombok.Data;
+
+@Data
+public class FileWithId {
+    private Long id;
+    private String fileName;
+
+    public FileWithId(Long id, String fileName) {
+        this.id = id;
+        this.fileName = fileName;
+    }
+}

+ 50 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/domain/FilesUpload.java

@@ -0,0 +1,50 @@
+package com.ruoyi.file.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("file_upload")
+public class FilesUpload implements Serializable {
+    private Integer id;//编号
+
+    private String filesName;//文件真实名称
+
+    private String name;//文件名
+
+    private String path;
+
+    private String type;//文件类型
+
+    private Double size;//文件大小
+
+    private String url;//下载链接
+
+    private  String refererPath;//引用路径
+
+    private Boolean enable;//链接是否可用(1:是 0:否)
+
+    private String createBy;//创建者
+
+    private Long createId;//创建者ID
+
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;//创建时间
+
+    private String updateBy;//更新者
+
+    private Long updateId;//更新者ID
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;//更新时间
+
+    private Integer isDelete;//是否删除(1:是 0:否)
+}

+ 9 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/mapper/FileUpdateInfoMapper.java

@@ -0,0 +1,9 @@
+package com.ruoyi.file.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.file.domain.FileUpdateInfo;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface FileUpdateInfoMapper extends BaseMapper<FileUpdateInfo> {
+}

+ 10 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/mapper/FilesMapper.java

@@ -0,0 +1,10 @@
+package com.ruoyi.file.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.file.domain.FilesUpload;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface FilesMapper extends BaseMapper<FilesUpload> {
+
+}

+ 42 - 42
base-modules/service-file/src/main/java/com/ruoyi/file/service/FastDfsSysFileServiceImpl.java

@@ -1,42 +1,42 @@
-package com.ruoyi.file.service;
-
-import org.apache.commons.io.FilenameUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
-import org.springframework.web.multipart.MultipartFile;
-import com.github.tobato.fastdfs.domain.fdfs.StorePath;
-import com.github.tobato.fastdfs.service.FastFileStorageClient;
-
-/**
- * FastDFS 文件存储
- * 
- * @author ruoyi
- */
-@Service
-public class FastDfsSysFileServiceImpl implements ISysFileService
-{
-    /**
-     * 域名或本机访问地址
-     */
-    @Value("${fdfs.domain}")
-    public String domain;
-
-    @Autowired
-    private FastFileStorageClient storageClient;
-
-    /**
-     * FastDfs文件上传接口
-     * 
-     * @param file 上传的文件
-     * @return 访问地址
-     * @throws Exception
-     */
-    @Override
-    public String uploadFile(MultipartFile file) throws Exception
-    {
-        StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(),
-                FilenameUtils.getExtension(file.getOriginalFilename()), null);
-        return domain + "/" + storePath.getFullPath();
-    }
-}
+//package com.ruoyi.file.service;
+//
+//import org.apache.commons.io.FilenameUtils;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.beans.factory.annotation.Value;
+//import org.springframework.stereotype.Service;
+//import org.springframework.web.multipart.MultipartFile;
+//import com.github.tobato.fastdfs.domain.fdfs.StorePath;
+//import com.github.tobato.fastdfs.service.FastFileStorageClient;
+//
+///**
+// * FastDFS 文件存储
+// *
+// * @author ruoyi
+// */
+//@Service
+//public class FastDfsSysFileServiceImpl implements ISysFileService
+//{
+//    /**
+//     * 域名或本机访问地址
+//     */
+//    @Value("${fdfs.domain}")
+//    public String domain;
+//
+//    @Autowired
+//    private FastFileStorageClient storageClient;
+//
+//    /**
+//     * FastDfs文件上传接口
+//     *
+//     * @param file 上传的文件
+//     * @return 访问地址
+//     * @throws Exception
+//     */
+//    @Override
+//    public String uploadFile(MultipartFile file) throws Exception
+//    {
+//        StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(),
+//                FilenameUtils.getExtension(file.getOriginalFilename()), null);
+//        return domain + "/" + storePath.getFullPath();
+//    }
+//}

+ 50 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/service/FileUpdateInfoService.java

@@ -0,0 +1,50 @@
+package com.ruoyi.file.service;
+
+import com.ruoyi.file.domain.FileUpdateInfo;
+import com.ruoyi.file.domain.FileWithId;
+import com.usky.common.core.bean.CommonPage;
+import org.springframework.web.bind.annotation.RequestParam;
+
+public interface FileUpdateInfoService {
+
+    /**
+     * 获取文件的运行状态
+     * @param fileName 文件名
+     * @return 状态码(1: 运行中,2: 已停止,0: 未知)
+     */
+    int getFileStatus(String fileName);
+
+    //添加服务信息
+    void addFileToDatabase(FileUpdateInfo fileUpdateInfo) throws Exception;
+
+    //检查服务更新
+    boolean checkFileUpdate(Long id) throws Exception;
+
+    //执行服务更新
+    void performFileUpdate(Long id) throws Exception;
+
+    // 获取所有服务信息(分页)
+    CommonPage<FileUpdateInfo> getAllFiles(
+            @RequestParam(required = false, defaultValue = "1") int current,
+            @RequestParam(required = false, defaultValue = "10") int size) throws Exception;
+
+    // 根据文件名模糊查询服务信息(分页)
+    CommonPage<FileUpdateInfo> getFilesByFileNameContaining(
+            @RequestParam(required = false) String fileName,
+            @RequestParam(required = false, defaultValue = "1") int current,
+            @RequestParam(required = false, defaultValue = "10") int size) throws Exception;
+
+    //根据id查询服务信息
+    FileUpdateInfo getFileById(Long id) throws Exception;
+
+    //删除服务信息
+    void deleteFileById(Long id) throws Exception;
+
+    //控制服务运行状态
+    void controlApplication(String fileName, String action) throws Exception;
+
+    // 扫描 JAR 文件所在的目录并获取文件列表
+    CommonPage<FileWithId> scanFilesInServiceDir(
+            @RequestParam(required = false, defaultValue = "1") int current,
+            @RequestParam(required = false, defaultValue = "10") int size) throws Exception;
+}

+ 30 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/service/FileUploadResponse.java

@@ -0,0 +1,30 @@
+package com.ruoyi.file.service;
+
+import lombok.Data;
+
+@Data
+public class FileUploadResponse {
+    private String name;
+    private String url;
+
+    public FileUploadResponse(String name, String url) {
+        this.name = name;
+        this.url = url;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+}

+ 19 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/service/FilesService.java

@@ -0,0 +1,19 @@
+package com.ruoyi.file.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.file.domain.FilesUpload;
+import com.usky.common.core.bean.CommonPage;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.time.LocalDateTime;
+
+public interface FilesService extends IService<FilesUpload> {
+    // 修改返回类型为 FileUploadResponse
+    FileUploadResponse upload(MultipartFile file, Long userid, String userName, String refererPath);
+
+    // 删除文件
+    void deleteFile(Integer id, Long userid, String userName);
+
+    // 查询方法
+    CommonPage<FilesUpload> queryFiles(String filesName, LocalDateTime startTime, LocalDateTime endTime, Boolean isDeleted, String fileType, String userName, int current, int size);
+}

+ 20 - 20
base-modules/service-file/src/main/java/com/ruoyi/file/service/ISysFileService.java

@@ -1,20 +1,20 @@
-package com.ruoyi.file.service;
-
-import org.springframework.web.multipart.MultipartFile;
-
-/**
- * 文件上传接口
- * 
- * @author ruoyi
- */
-public interface ISysFileService
-{
-    /**
-     * 文件上传接口
-     * 
-     * @param file 上传的文件
-     * @return 访问地址
-     * @throws Exception
-     */
-    public String uploadFile(MultipartFile file) throws Exception;
-}
+//package com.ruoyi.file.service;
+//
+//import org.springframework.web.multipart.MultipartFile;
+//
+///**
+// * 文件上传接口
+// *
+// * @author ruoyi
+// */
+//public interface ISysFileService
+//{
+//    /**
+//     * 文件上传接口
+//     *
+//     * @param file 上传的文件
+//     * @return 访问地址
+//     * @throws Exception
+//     */
+//    public String uploadFile(MultipartFile file) throws Exception;
+//}

+ 50 - 50
base-modules/service-file/src/main/java/com/ruoyi/file/service/LocalSysFileServiceImpl.java

@@ -1,50 +1,50 @@
-package com.ruoyi.file.service;
-
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Primary;
-import org.springframework.stereotype.Service;
-import org.springframework.web.multipart.MultipartFile;
-import com.ruoyi.file.utils.FileUploadUtils;
-
-/**
- * 本地文件存储
- *
- * @author ruoyi
- */
-@Primary
-@Service
-public class LocalSysFileServiceImpl implements ISysFileService
-{
-    /**
-     * 资源映射路径 前缀
-     */
-    @Value("${file.prefix}")
-    public String localFilePrefix;
-
-    /**
-     * 域名或本机访问地址
-     */
-    @Value("${file.domain}")
-    public String domain;
-
-    /**
-     * 上传文件存储在本地的根路径
-     */
-    @Value("${file.path}")
-    private String localFilePath;
-
-    /**
-     * 本地文件上传接口
-     *
-     * @param file 上传的文件
-     * @return 访问地址
-     * @throws Exception
-     */
-    @Override
-    public String uploadFile(MultipartFile file) throws Exception
-    {
-        String name = FileUploadUtils.upload(localFilePath, file);
-        String url = domain + localFilePrefix + name;
-        return url;
-    }
-}
+//package com.ruoyi.file.service;
+//
+//import org.springframework.beans.factory.annotation.Value;
+//import org.springframework.context.annotation.Primary;
+//import org.springframework.stereotype.Service;
+//import org.springframework.web.multipart.MultipartFile;
+//import com.ruoyi.file.utils.FileUploadUtils;
+//
+///**
+// * 本地文件存储
+// *
+// * @author ruoyi
+// */
+//@Primary
+//@Service
+//public class LocalSysFileServiceImpl implements ISysFileService
+//{
+//    /**
+//     * 资源映射路径 前缀
+//     */
+//    @Value("${file.prefix}")
+//    public String localFilePrefix;
+//
+//    /**
+//     * 域名或本机访问地址
+//     */
+//    @Value("${file.domain}")
+//    public String domain;
+//
+//    /**
+//     * 上传文件存储在本地的根路径
+//     */
+//    @Value("${file.path}")
+//    private String localFilePath;
+//
+//    /**
+//     * 本地文件上传接口
+//     *
+//     * @param file 上传的文件
+//     * @return 访问地址
+//     * @throws Exception
+//     */
+//    @Override
+//    public String uploadFile(MultipartFile file) throws Exception
+//    {
+//        String name = FileUploadUtils.upload(localFilePath, file);
+//        String url = domain + localFilePrefix + name;
+//        return url;
+//    }
+//}

+ 416 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/service/impl/FileUpdateInfoServiceImpl.java

@@ -0,0 +1,416 @@
+package com.ruoyi.file.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.file.domain.FileUpdateInfo;
+import com.ruoyi.file.domain.FileWithId;
+import com.ruoyi.file.mapper.FileUpdateInfoMapper;
+import com.ruoyi.file.service.FileUpdateInfoService;
+import com.usky.common.core.bean.CommonPage;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+public class FileUpdateInfoServiceImpl implements FileUpdateInfoService {
+    private static final Logger logger = LoggerFactory.getLogger(FileUpdateInfoServiceImpl.class);
+
+    @Autowired
+    private FileUpdateInfoMapper fileUpdateInfoMapper;
+
+    @Value("${file.remote-url}")
+    private String remoteUrlBase;
+
+    // 从配置文件中读取脚本名称
+    @Value("${file.linuxrestart}")
+    private String linuxContralScript;
+
+    @Value("${file.windowsstop}")
+    private String windowsStopScript;
+
+    @Value("${file.windowsstart}")
+    private String windowsStartScript;
+
+    @Override
+    public void addFileToDatabase(FileUpdateInfo fileUpdateInfo) throws Exception {
+        // 假设前端只传入文件名
+        String fileName = fileUpdateInfo.getFileName();
+        if (fileName == null || fileName.trim().isEmpty()) {
+            throw new IllegalArgumentException("文件名不能为空");
+        }
+
+        // 设置文件路径
+        String filePath = FileUpdateInfo.getServiceDir() + File.separator + fileUpdateInfo.getFileName();
+
+        File file = new File(filePath);
+
+        if (file.exists()) {
+            // 如果文件存在,计算本地文件的 MD5 值
+            String fileMd5 = DigestUtils.md5Hex(new FileInputStream(file));
+            fileUpdateInfo.setFileMd5(fileMd5);
+            fileUpdateInfo.setUpdateStatus(0);
+        } else {
+            // 如果文件不存在,设置状态为“待更新”
+            fileUpdateInfo.setFileMd5(null);
+            fileUpdateInfo.setUpdateStatus(1);
+        }
+
+        fileUpdateInfo.setVersion("v1.0.0"); // 初始化版本号
+        fileUpdateInfo.setCreateTime(LocalDateTime.now());
+        fileUpdateInfo.setUpdateTime(null);
+        fileUpdateInfoMapper.insert(fileUpdateInfo);
+    }
+
+    //检查是否需要更新
+    @Override
+    public boolean checkFileUpdate(Long id) throws Exception {
+        FileUpdateInfo fileUpdateInfo = fileUpdateInfoMapper.selectById(id);
+        if (fileUpdateInfo == null) {
+            throw new FileNotFoundException("文件信息未找到:id=" + id);
+        }
+
+        String localFilePath = fileUpdateInfo.getFilePath(); // 使用新的 getFilePath 方法
+        File localFile = new File(localFilePath);
+
+        String remoteFileMd5 = getRemoteFileMd5(fileUpdateInfo.getFileName());
+
+        if (!localFile.exists()) {
+            // 如果本地文件不存在,设置状态为“待更新”
+            fileUpdateInfo.setRemoteMd5(remoteFileMd5);
+            fileUpdateInfo.setUpdateStatus(1); // 设置为待更新
+            fileUpdateInfoMapper.updateById(fileUpdateInfo);
+            return true; // 需要更新
+        } else {
+            // 如果本地文件存在,比较 MD5 值
+            String localFileMd5 = DigestUtils.md5Hex(new FileInputStream(localFile));
+            boolean isUpdateRequired = !localFileMd5.equals(remoteFileMd5);
+            fileUpdateInfo.setRemoteMd5(remoteFileMd5);
+            fileUpdateInfo.setUpdateStatus(isUpdateRequired ? 1 : 0);  // 0表示无需更新,1表示待更新
+            fileUpdateInfoMapper.updateById(fileUpdateInfo);
+            return isUpdateRequired;
+        }
+    }
+
+    //下载更新
+    @Override
+    public void performFileUpdate(Long id) throws Exception {
+        FileUpdateInfo fileUpdateInfo = fileUpdateInfoMapper.selectById(id);
+        if (fileUpdateInfo == null) {
+            throw new FileNotFoundException("文件信息未找到:id=" + id);
+        }
+
+        String localFilePath = fileUpdateInfo.getFilePath(); // 使用新的 getFilePath 方法
+        String fileName = fileUpdateInfo.getFileName();
+        String remoteUrl = remoteUrlBase + fileName;
+
+        try {
+            // 获取 JAR 文件所在的目录
+            String serviceDir = FileUpdateInfo.getServiceDir();
+            String backupDirPath = serviceDir + File.separator + "backup";
+            File backupDir = new File(backupDirPath);
+            if (!backupDir.exists()) {
+                boolean created = backupDir.mkdirs();
+                if (!created) {
+                    throw new IOException("无法创建备份目录");
+                }
+            }
+
+            File originalFile = new File(localFilePath);
+            if (originalFile.exists()) {
+                String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
+                String backupFilePath = backupDirPath + File.separator + fileName + "." + timestamp;
+                Files.move(originalFile.toPath(), Paths.get(backupFilePath), StandardCopyOption.REPLACE_EXISTING);
+                System.out.println("旧文件已备份到: " + backupFilePath);
+            }
+
+            downloadFileFromRemote(remoteUrl, localFilePath);
+
+            String newFileMd5 = DigestUtils.md5Hex(new FileInputStream(localFilePath));
+            fileUpdateInfo.setFileMd5(newFileMd5);
+            fileUpdateInfo.setCreateTime(fileUpdateInfo.getCreateTime());
+            fileUpdateInfo.setUpdateTime(LocalDateTime.now());
+            fileUpdateInfo.setUpdateStatus(0);
+
+            // 递增版本号
+            String currentVersion = fileUpdateInfo.getVersion();
+            String[] versionParts = currentVersion.substring(1).split("\\."); // 去掉 'v' 并拆分版本号
+            int major = Integer.parseInt(versionParts[0]);
+            int minor = Integer.parseInt(versionParts[1]);
+            int patch = Integer.parseInt(versionParts[2]) + 1; // 小版本号加 1
+            fileUpdateInfo.setVersion("v" + major + "." + minor + "." + patch);
+
+            fileUpdateInfoMapper.updateById(fileUpdateInfo);
+
+            // 下载完成后重启服务
+            controlApplication(fileName, "restart");
+
+        } catch (FileNotFoundException e) {
+            throw new Exception("原因: " + e.getMessage(), e);
+        } catch (IOException e) {
+            throw new Exception("原因: " + e.getMessage(), e);
+        } catch (Exception e) {
+            throw new Exception("原因: 远程仓库未找到服务包");
+        }
+    }
+
+    private void downloadFileFromRemote(String remoteUrl, String localFilePath) throws Exception {
+        URL url = new URL(remoteUrl);
+        Path path = Paths.get(localFilePath);
+        try {
+            Files.copy(url.openStream(), path, StandardCopyOption.REPLACE_EXISTING);
+            System.out.println("文件下载成功");
+        } catch (IOException e) {
+            System.err.println("文件下载失败" + ",原因: " + e.getMessage());
+            throw new Exception("文件下载失败");
+        }
+    }
+
+    private String getRemoteFileMd5(String fileName) throws Exception {
+        String remoteUrl = remoteUrlBase + fileName;
+        System.out.println("远程文件 URL: " + remoteUrl);
+        URL url = new URL(remoteUrl);
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+        connection.setRequestProperty("Cache-Control", "no-cache");
+        try (InputStream in = connection.getInputStream()) {
+            return DigestUtils.md5Hex(in);
+        }
+    }
+
+    @Override
+    public CommonPage<FileUpdateInfo> getAllFiles(int current, int size) throws Exception {
+        // 使用 MyBatis-Plus 的分页功能
+        Page<FileUpdateInfo> page = new Page<>(current, size);
+        IPage<FileUpdateInfo> result = fileUpdateInfoMapper.selectPage(page, null);
+
+        // 更新每个文件的运行状态
+        for (FileUpdateInfo fileUpdateInfo : result.getRecords()) {
+            checkServiceStatus(fileUpdateInfo);
+        }
+
+        // 将 MyBatis-Plus 的分页结果转换为 CommonPage
+        return new CommonPage<>(
+                result.getRecords(),
+                (int) result.getTotal(),
+                size,
+                current
+        );
+    }
+
+    @Override
+    public CommonPage<FileUpdateInfo> getFilesByFileNameContaining(String fileName, int current, int size) throws Exception {
+        // 使用 MyBatis-Plus 的分页功能
+        Page<FileUpdateInfo> page = new Page<>(current, size);
+        QueryWrapper<FileUpdateInfo> queryWrapper = new QueryWrapper<>();
+        queryWrapper.like("file_name", fileName);
+        IPage<FileUpdateInfo> result = fileUpdateInfoMapper.selectPage(page, queryWrapper);
+
+        // 更新每个文件的运行状态
+        for (FileUpdateInfo fileUpdateInfo : result.getRecords()) {
+            checkServiceStatus(fileUpdateInfo);
+        }
+
+        // 将 MyBatis-Plus 的分页结果转换为 CommonPage
+        return new CommonPage<>(
+                result.getRecords(),
+                (int) result.getTotal(),
+                size,
+                current
+        );
+    }
+
+    @Override
+    public FileUpdateInfo getFileById(Long id) {
+        return fileUpdateInfoMapper.selectById(id);
+    }
+
+    @Override
+    public void deleteFileById(Long id) {
+        fileUpdateInfoMapper.deleteById(id);
+    }
+
+    @Override
+    public void controlApplication(String fileName, String action) throws Exception {
+        String osName = System.getProperty("os.name").toLowerCase();
+
+        if (osName.contains("linux") || osName.contains("unix")) {
+            // Linux 系统
+            String command = "sh " + linuxContralScript + " " + action + " " + fileName;
+            Runtime.getRuntime().exec(command);
+        } else if (osName.contains("windows")) {
+            // Windows 系统
+            String command;
+            switch (action.toLowerCase()) {
+                case "start":
+                    command = windowsStartScript + " " + fileName;
+                    break;
+                case "stop":
+                    command = windowsStopScript + " " + fileName;
+                    break;
+                case "restart":
+                    // Windows 系统没有单独的重启脚本,需要先停止再启动
+                    Runtime.getRuntime().exec(windowsStopScript + " " + fileName);
+                    Thread.sleep(3000); // 等待 3 秒,确保服务停止
+                    Runtime.getRuntime().exec(windowsStartScript + " " + fileName);
+                    return;
+                default:
+                    throw new IllegalArgumentException("不支持的操作类型: " + action);
+            }
+            Runtime.getRuntime().exec(command);
+        } else {
+            throw new Exception("不支持的操作系统: " + osName);
+        }
+
+        // 等待操作完成
+        long startTime = System.currentTimeMillis();
+        long timeout = 8000; // 最长等待时间 8 秒
+        boolean isActionCompleted = false;
+
+        while (System.currentTimeMillis() - startTime < timeout) {
+            int currentStatus = getFileStatus(fileName); // 获取当前服务状态
+            if (action.equals("start") && currentStatus == 1) {
+                isActionCompleted = true;
+                break; // 服务已启动
+            } else if (action.equals("stop") && currentStatus == 2) {
+                isActionCompleted = true;
+                break; // 服务已停止
+            } else if (action.equals("restart") && currentStatus == 1) {
+                isActionCompleted = true;
+                break; // 服务已重启
+            }
+
+            Thread.sleep(500); // 每隔 500 毫秒检测一次状态
+        }
+
+        if (!isActionCompleted) {
+            throw new Exception("操作超时,服务状态未达到预期");
+        }
+    }
+
+    //扫描服务所在目录下的文件
+    @Override
+    public CommonPage<FileWithId> scanFilesInServiceDir(int current, int size) throws Exception {
+        // 获取 JAR 文件所在的目录
+        String serviceDir = FileUpdateInfo.getServiceDir();
+        File dir = new File(serviceDir);
+
+        if (!dir.exists() || !dir.isDirectory()) {
+            throw new Exception("无法找到服务目录: " + serviceDir);
+        }
+
+        // 获取目录中的所有文件名
+        File[] files = dir.listFiles();
+        if (files == null) {
+            throw new Exception("无法读取目录内容: " + serviceDir);
+        }
+
+        // 提取文件名
+        List<String> fileNames = new ArrayList<>();
+        for (File file : files) {
+            if (file.isFile()) {
+                fileNames.add(file.getName());
+            }
+        }
+
+        // 查询数据库中已存在的文件名
+        List<String> existingFileNames = fileUpdateInfoMapper.selectList(null).stream()
+                .map(FileUpdateInfo::getFileName)
+                .collect(Collectors.toList());
+
+        // 从扫描结果中排除已存在的文件名
+        List<String> newFileNames = fileNames.stream()
+                .filter(fileName -> !existingFileNames.contains(fileName))
+                .collect(Collectors.toList());
+
+        // 对文件名列表进行分页处理
+        int total = newFileNames.size();
+        int start = (current - 1) * size;
+        int end = Math.min(start + size, total);
+
+        List<String> pageFileNames = newFileNames.subList(start, end);
+
+        // 创建包含 id 的文件信息列表
+        List<FileWithId> fileWithIds = new ArrayList<>();
+        for (int i = 0; i < pageFileNames.size(); i++) {
+            fileWithIds.add(new FileWithId((long) (start + i + 1), pageFileNames.get(i)));
+        }
+
+        // 返回分页结果
+        return new CommonPage<>(fileWithIds, total, size, current);
+    }
+
+
+    // 检测服务运行状态并更新到数据库
+    private void checkServiceStatus(FileUpdateInfo fileUpdateInfo) {
+        String fileName = fileUpdateInfo.getFileName();
+        int fileStatus = getFileStatus(fileName); // 调用方法获取文件运行状态
+        fileUpdateInfo.setFileStatus(fileStatus); // 更新运行状态
+        fileUpdateInfoMapper.updateById(fileUpdateInfo); // 更新数据库
+    }
+
+    // 获取文件运行状态
+    @Override
+    public int getFileStatus(String fileName) {
+        String osName = System.getProperty("os.name").toLowerCase();
+
+        if (osName.contains("linux") || osName.contains("unix")) {
+            // Linux 系统
+            String command = "pgrep -f " + fileName;
+            try {
+                Process process = Runtime.getRuntime().exec(command);
+                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+                String line;
+                boolean isRunning = false;
+                while ((line = reader.readLine()) != null) {
+                    if (line != null && !line.isEmpty()) {
+                        isRunning = true;
+                        break;
+                    }
+                }
+                return isRunning ? 1 : 2; // 1: 运行中,2: 已停止
+            } catch (IOException e) {
+                logger.error("Failed to execute command: {}", command, e);
+            }
+        } else if (osName.contains("windows")) {
+            // Windows 系统
+            String command = "sc query " + fileName;
+            try {
+                Process process = Runtime.getRuntime().exec(command);
+                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+                String line;
+                boolean isRunning = false;
+                while ((line = reader.readLine()) != null) {
+                    if (line.contains("RUNNING")) {
+                        isRunning = true;
+                        break;
+                    } else if (line.contains("STOPPED")) {
+                        break;
+                    }
+                }
+                return isRunning ? 1 : 2; // 1: 运行中,2: 已停止
+            } catch (IOException e) {
+                logger.error("Failed to execute command: {}", command, e);
+            }
+        } else {
+            logger.warn("Unsupported operating system: {}", osName);
+        }
+        return 0; // 未知
+    }
+}

+ 241 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/service/impl/FilesServiceImpl.java

@@ -0,0 +1,241 @@
+package com.ruoyi.file.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.file.mapper.FilesMapper;
+import com.ruoyi.file.service.FileUploadResponse;
+import com.ruoyi.file.service.FilesService;
+import com.ruoyi.file.domain.FilesUpload;
+import com.usky.common.core.bean.CommonPage;
+import com.usky.common.security.utils.SecurityUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.*;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+@Service
+public class FilesServiceImpl extends ServiceImpl<FilesMapper, FilesUpload> implements FilesService {
+    @Value("${file.path}")
+    private String filesUploadPath;//获取文件路径
+
+    @Value("${file.domain}")
+    private String filesUploadDomain;//文件域名
+
+    @Value("${file.prefix}")
+    private String filesPrefix;//文件前缀
+
+
+
+    @Override
+    public FileUploadResponse upload(MultipartFile file, Long userid, String userName, String refererPath) {
+
+        // 获取当前登录用户昵称(如果可用)
+//        String userName = SecurityUtils.getUsername();
+
+        // 文件夹路径名称
+        String originalFilename = file.getOriginalFilename();
+
+        //文件大小
+        double size = file.getSize() / (1024.0);
+
+        // 获取当前日期时间
+        LocalDateTime now = LocalDateTime.now();
+//        String timestamp = now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
+
+        //文件类型
+        String type = originalFilename.substring(originalFilename.lastIndexOf(".") + 1).toLowerCase();
+
+        // 按照年月创建文件夹
+        String yearMonth = now.format(DateTimeFormatter.ofPattern("yyyyMM"));
+        // 获取每月递增值
+        int monthIncrement = getMonthIncrement(yearMonth);
+        // 新文件名格式:时间戳+每月递增值+文件类型
+//        String fileUuid = timestamp + "A" + String.format("%04d", monthIncrement) + "." + type;
+
+        // 将相对路径转化为绝对路径
+        String destPath = filesUploadPath + "/" + yearMonth;
+
+        // 新的文件地址,绝对路径+新的文件名称
+//        File uploadFile = new File(destPath + "/" + fileUuid);
+        File uploadFile;
+        String fileUuid = originalFilename; // 初始使用原文件名
+        int count = 1; // 用于生成重复文件名的序号
+        while (true) {
+            uploadFile = new File(destPath + "/" + fileUuid);
+            if (!uploadFile.exists()) { // 如果文件不存在,直接使用该文件名
+                break;
+            } else { // 如果文件已存在,修改文件名
+                String nameWithoutType = originalFilename.substring(0, originalFilename.lastIndexOf("."));
+                fileUuid = nameWithoutType + "(" + count + ")." + type;
+                count++;
+            }
+        }
+
+        // 判断配置的文件目录是否存在,若不存在则创建一个新的文件目录
+        File parentFile = uploadFile.getParentFile();
+        if (!parentFile.exists()) {
+            parentFile.mkdirs();
+        }
+
+        try {
+            // 存储文件到本地磁盘
+            file.transferTo(uploadFile);
+
+            // 设置文件url
+            String url = filesUploadDomain + filesPrefix + "/" + yearMonth + "/" + fileUuid;
+
+            // 将文件存储到数据库
+            FilesUpload saveFile = new FilesUpload();
+            saveFile.setFilesName(originalFilename);
+            saveFile.setName(fileUuid);
+            saveFile.setPath(destPath);
+            saveFile.setType(type);
+            saveFile.setSize(size); // (单位:KB)
+            saveFile.setUrl(url);
+            saveFile.setEnable(true);
+            saveFile.setIsDelete(0);
+            saveFile.setRefererPath(refererPath);
+            saveFile.setCreateId(userid);
+            saveFile.setCreateBy(userName);
+            saveFile.setCreateTime(LocalDateTime.now());
+            saveFile.setUpdateId(null);
+            saveFile.setUpdateBy(null);
+            saveFile.setUpdateTime(null);
+            // 保存操作
+            save(saveFile);
+
+            // 返回 FileUploadResponse 对象
+            return new FileUploadResponse(originalFilename, url);
+        } catch (IOException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 获取每月递增值
+     * @param yearMonth 年月(格式:yyyyMM)
+     * @return 递增值
+     */
+    private int getMonthIncrement(String yearMonth) {
+        // 目标文件夹路径
+        String destPath = filesUploadPath + "/" + yearMonth;
+        File folder = new File(destPath);
+
+        // 如果文件夹不存在,则递增值从1开始
+        if (!folder.exists()) {
+            folder.mkdirs();
+            return 1;
+        }
+
+        // 获取文件夹中已有的文件数量
+        File[] files = folder.listFiles();
+        if (files == null || files.length == 0) {
+            return 1;
+        }
+
+        // 递增值为文件夹中现有文件数量 + 1
+        return files.length + 1;
+    }
+
+    @Override
+    public void deleteFile(Integer id, Long userid, String userName) {
+        try {
+            // 根据 id 查询文件信息
+            FilesUpload file = getById(id);
+            if (file == null) {
+                throw new RuntimeException("文件不存在,无法删除");
+            }
+
+            // 删除本地文件
+            String filePath = file.getPath() + "/" + file.getName();
+            File localFile = new File(filePath);
+            if (localFile.exists()) {
+                if (!localFile.delete()) {
+                    throw new RuntimeException("文件删除失败");
+                }
+            }
+
+            // 更新数据库记录
+            FilesUpload updateFile = new FilesUpload();
+            updateFile.setId(file.getId());
+            updateFile.setFilesName(file.getFilesName());
+            updateFile.setName(file.getName());
+            updateFile.setPath(file.getPath());
+            updateFile.setType(file.getType());
+            updateFile.setSize(file.getSize());
+            updateFile.setUrl(file.getUrl());
+            updateFile.setEnable(false);
+            updateFile.setIsDelete(1); // 设置为已删除
+            updateFile.setRefererPath(file.getRefererPath());
+            updateFile.setCreateId(file.getCreateId());
+            updateFile.setCreateBy(file.getCreateBy());
+            updateFile.setCreateTime(file.getCreateTime()); // 保留原始的 createTime
+            updateFile.setUpdateId(userid);
+            updateFile.setUpdateBy(userName);
+            updateFile.setUpdateTime(LocalDateTime.now());
+
+            // 提交更新到数据库
+            updateById(updateFile); // 调用 updateById 方法更新数据库记录
+        } catch (Exception e) {
+            throw new RuntimeException("删除文件失败:" + e.getMessage());
+        }
+    }
+
+    @Override
+    public CommonPage<FilesUpload> queryFiles(String filesName, LocalDateTime startTime, LocalDateTime endTime, Boolean isDeleted, String fileType, String userName, int current, int size) {
+        QueryWrapper<FilesUpload> queryWrapper = new QueryWrapper<>();
+
+        // 默认查询未删除的文件
+        if (isDeleted == null) {
+            queryWrapper.eq("is_delete", 0);
+        } else {
+            queryWrapper.eq("is_delete", isDeleted ? 1 : 0);
+        }
+
+        if (filesName != null && !filesName.isEmpty()) {
+            queryWrapper.like("files_name", filesName);
+        }
+
+        if (startTime != null && endTime != null) {
+            queryWrapper.ge("create_time", startTime); // 大于等于起始时间
+            queryWrapper.le("create_time", endTime);   // 小于等于结束时间
+        } else if (startTime != null) {
+            queryWrapper.ge("create_time", startTime); // 只有起始时间
+        } else if (endTime != null) {
+            queryWrapper.le("create_time", endTime);   // 只有结束时间
+        }
+
+        if (fileType != null && !fileType.isEmpty()) {
+            queryWrapper.eq("type", fileType);
+        }
+
+        if (userName != null && !userName.isEmpty()) {
+            queryWrapper.like("create_by", userName);
+        }
+
+        // 按照创建时间倒序排列
+        queryWrapper.orderByDesc("create_time");
+
+        // 创建分页请求对象
+        Page<FilesUpload> page = new Page<>(current, size);
+
+        // 执行分页查询
+        IPage<FilesUpload> iPage = baseMapper.selectPage(page, queryWrapper);
+
+        // 将 MyBatis Plus 的 IPage 转换为 CommonPage
+        CommonPage<FilesUpload> commonPage = new CommonPage<>();
+        commonPage.setRecords(iPage.getRecords());
+        commonPage.setTotal(iPage.getTotal());
+        commonPage.setSize(iPage.getSize());
+        commonPage.setCurrent(iPage.getCurrent());
+
+        return commonPage;
+    }
+
+}

+ 202 - 202
base-modules/service-file/src/main/java/com/ruoyi/file/utils/FileUploadUtils.java

@@ -1,202 +1,202 @@
-package com.ruoyi.file.utils;
-
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Paths;
-import java.util.Date;
-import java.util.Objects;
-
-import com.ruoyi.common.core.exception.file.FileNameLengthLimitExceededException;
-import com.ruoyi.common.core.exception.file.InvalidExtensionException;
-import org.apache.commons.io.FilenameUtils;
-import com.ruoyi.common.core.exception.file.FileSizeLimitExceededException;
-import com.ruoyi.common.core.utils.DateUtils;
-import com.ruoyi.common.core.utils.StringUtils;
-import com.ruoyi.common.core.utils.file.MimeTypeUtils;
-import com.ruoyi.common.core.utils.uuid.Seq;
-import org.apache.commons.lang3.time.DateFormatUtils;
-import org.springframework.web.multipart.MultipartFile;
-
-
-/**
- * 文件上传工具类
- *
- * @author ruoyi
- */
-public class FileUploadUtils
-{
-    /**
-     * 默认大小 50M
-     */
-    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
-
-    /**
-     * 默认的文件名最大长度 100
-     */
-    public static final int DEFAULT_FILE_NAME_LENGTH = 100;
-
-    /**
-     * 根据文件路径上传
-     *
-     * @param baseDir 相对应用的基目录
-     * @param file 上传的文件
-     * @return 文件名称
-     * @throws IOException
-     */
-    public static final String upload(String baseDir, MultipartFile file) throws IOException
-    {
-        try
-        {
-            return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
-        }
-        catch (Exception e)
-        {
-            throw new IOException(e.getMessage(), e);
-        }
-    }
-
-    /**
-     * 文件上传
-     *
-     * @param baseDir 相对应用的基目录
-     * @param file 上传的文件
-     * @param allowedExtension 上传文件类型
-     * @return 返回上传成功的文件名
-     * @throws FileSizeLimitExceededException 如果超出最大大小
-     * @throws FileNameLengthLimitExceededException 文件名太长
-     * @throws IOException 比如读写文件出错时
-     * @throws InvalidExtensionException 文件校验异常
-     */
-    public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
-            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
-            InvalidExtensionException
-    {
-        int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
-        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
-        {
-            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
-        }
-
-        assertAllowed(file, allowedExtension);
-
-        String fileName = extractFilename(file);
-
-        String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
-        file.transferTo(Paths.get(absPath));
-        return getPathFileName(fileName);
-    }
-
-    /**
-     * 编码文件名
-     */
-    public static final String extractFilename(MultipartFile file)
-    {
-//        return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
-//                FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
-        String datePath = DateFormatUtils.format(new Date(), "yyyyMM");
-        return StringUtils.format("{}/{}.{}",datePath , Seq.getId(Seq.uploadSeqType), getExtension(file));
-    }
-
-    private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
-    {
-        File desc = new File(uploadDir + File.separator + fileName);
-
-        if (!desc.exists())
-        {
-            if (!desc.getParentFile().exists())
-            {
-                desc.getParentFile().mkdirs();
-            }
-        }
-        return desc.isAbsolute() ? desc : desc.getAbsoluteFile();
-    }
-
-    private static final String getPathFileName(String fileName) throws IOException
-    {
-        String pathFileName = "/" + fileName;
-        return pathFileName;
-    }
-
-    /**
-     * 文件大小校验
-     *
-     * @param file 上传的文件
-     * @throws FileSizeLimitExceededException 如果超出最大大小
-     * @throws InvalidExtensionException 文件校验异常
-     */
-    public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
-            throws FileSizeLimitExceededException, InvalidExtensionException
-    {
-        long size = file.getSize();
-        if (size > DEFAULT_MAX_SIZE)
-        {
-            throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE/1024/1024);
-        }
-
-        String fileName = file.getOriginalFilename();
-        String extension = getExtension(file);
-        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
-        {
-            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
-            {
-                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
-                        fileName);
-            }
-            else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
-            {
-                throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
-                        fileName);
-            }
-            else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
-            {
-                throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
-                        fileName);
-            }
-            else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
-            {
-                throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
-                        fileName);
-            }
-            else
-            {
-                throw new InvalidExtensionException(allowedExtension, extension, fileName);
-            }
-        }
-    }
-
-    /**
-     * 判断MIME类型是否是允许的MIME类型
-     *
-     * @param extension 上传文件类型
-     * @param allowedExtension 允许上传文件类型
-     * @return true/false
-     */
-    public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
-    {
-        for (String str : allowedExtension)
-        {
-            if (str.equalsIgnoreCase(extension))
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * 获取文件名的后缀
-     *
-     * @param file 表单文件
-     * @return 后缀名
-     */
-    public static final String getExtension(MultipartFile file)
-    {
-        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
-        if (StringUtils.isEmpty(extension))
-        {
-            extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
-        }
-        return extension;
-    }
-}
+//package com.ruoyi.file.utils;
+//
+//
+//import java.io.File;
+//import java.io.IOException;
+//import java.nio.file.Paths;
+//import java.util.Date;
+//import java.util.Objects;
+//
+//import com.ruoyi.common.core.exception.file.FileNameLengthLimitExceededException;
+//import com.ruoyi.common.core.exception.file.InvalidExtensionException;
+//import org.apache.commons.io.FilenameUtils;
+//import com.ruoyi.common.core.exception.file.FileSizeLimitExceededException;
+//import com.ruoyi.common.core.utils.DateUtils;
+//import com.ruoyi.common.core.utils.StringUtils;
+//import com.ruoyi.common.core.utils.file.MimeTypeUtils;
+//import com.ruoyi.common.core.utils.uuid.Seq;
+//import org.apache.commons.lang3.time.DateFormatUtils;
+//import org.springframework.web.multipart.MultipartFile;
+//
+//
+///**
+// * 文件上传工具类
+// *
+// * @author ruoyi
+// */
+//public class FileUploadUtils
+//{
+//    /**
+//     * 默认大小 50M
+//     */
+//    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
+//
+//    /**
+//     * 默认的文件名最大长度 100
+//     */
+//    public static final int DEFAULT_FILE_NAME_LENGTH = 100;
+//
+//    /**
+//     * 根据文件路径上传
+//     *
+//     * @param baseDir 相对应用的基目录
+//     * @param file 上传的文件
+//     * @return 文件名称
+//     * @throws IOException
+//     */
+//    public static final String upload(String baseDir, MultipartFile file) throws IOException
+//    {
+//        try
+//        {
+//            return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
+//        }
+//        catch (Exception e)
+//        {
+//            throw new IOException(e.getMessage(), e);
+//        }
+//    }
+//
+//    /**
+//     * 文件上传
+//     *
+//     * @param baseDir 相对应用的基目录
+//     * @param file 上传的文件
+//     * @param allowedExtension 上传文件类型
+//     * @return 返回上传成功的文件名
+//     * @throws FileSizeLimitExceededException 如果超出最大大小
+//     * @throws FileNameLengthLimitExceededException 文件名太长
+//     * @throws IOException 比如读写文件出错时
+//     * @throws InvalidExtensionException 文件校验异常
+//     */
+//    public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
+//            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
+//            InvalidExtensionException
+//    {
+//        int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
+//        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
+//        {
+//            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
+//        }
+//
+//        assertAllowed(file, allowedExtension);
+//
+//        String fileName = extractFilename(file);
+//
+//        String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
+//        file.transferTo(Paths.get(absPath));
+//        return getPathFileName(fileName);
+//    }
+//
+//    /**
+//     * 编码文件名
+//     */
+//    public static final String extractFilename(MultipartFile file)
+//    {
+////        return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
+////                FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
+//        String datePath = DateFormatUtils.format(new Date(), "yyyyMM");
+//        return StringUtils.format("{}/{}.{}",datePath , Seq.getId(Seq.uploadSeqType), getExtension(file));
+//    }
+//
+//    private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
+//    {
+//        File desc = new File(uploadDir + File.separator + fileName);
+//
+//        if (!desc.exists())
+//        {
+//            if (!desc.getParentFile().exists())
+//            {
+//                desc.getParentFile().mkdirs();
+//            }
+//        }
+//        return desc.isAbsolute() ? desc : desc.getAbsoluteFile();
+//    }
+//
+//    private static final String getPathFileName(String fileName) throws IOException
+//    {
+//        String pathFileName = "/" + fileName;
+//        return pathFileName;
+//    }
+//
+//    /**
+//     * 文件大小校验
+//     *
+//     * @param file 上传的文件
+//     * @throws FileSizeLimitExceededException 如果超出最大大小
+//     * @throws InvalidExtensionException 文件校验异常
+//     */
+//    public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
+//            throws FileSizeLimitExceededException, InvalidExtensionException
+//    {
+//        long size = file.getSize();
+//        if (size > DEFAULT_MAX_SIZE)
+//        {
+//            throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE/1024/1024);
+//        }
+//
+//        String fileName = file.getOriginalFilename();
+//        String extension = getExtension(file);
+//        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
+//        {
+//            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
+//            {
+//                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
+//                        fileName);
+//            }
+//            else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
+//            {
+//                throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
+//                        fileName);
+//            }
+//            else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
+//            {
+//                throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
+//                        fileName);
+//            }
+//            else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
+//            {
+//                throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
+//                        fileName);
+//            }
+//            else
+//            {
+//                throw new InvalidExtensionException(allowedExtension, extension, fileName);
+//            }
+//        }
+//    }
+//
+//    /**
+//     * 判断MIME类型是否是允许的MIME类型
+//     *
+//     * @param extension 上传文件类型
+//     * @param allowedExtension 允许上传文件类型
+//     * @return true/false
+//     */
+//    public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
+//    {
+//        for (String str : allowedExtension)
+//        {
+//            if (str.equalsIgnoreCase(extension))
+//            {
+//                return true;
+//            }
+//        }
+//        return false;
+//    }
+//
+//    /**
+//     * 获取文件名的后缀
+//     *
+//     * @param file 表单文件
+//     * @return 后缀名
+//     */
+//    public static final String getExtension(MultipartFile file)
+//    {
+//        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
+//        if (StringUtils.isEmpty(extension))
+//        {
+//            extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
+//        }
+//        return extension;
+//    }
+//}

+ 1 - 1
base-modules/service-file/src/main/resources/bootstrap.yml

@@ -3,7 +3,7 @@ server:
   port: 9300
 
 # Spring
-spring: 
+spring:
   application:
     # 应用名称
     name: service-file

+ 5 - 0
base-modules/service-file/src/main/resources/mapper/file/FilesMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.file.mapper.FilesMapper">
+
+</mapper>

+ 1 - 0
base-modules/service-job/src/main/resources/mapper/job/SysJobMapper.xml

@@ -41,6 +41,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 				AND invoke_target like concat('%', #{invokeTarget}, '%')
 			</if>
 		</where>
+		ORDER BY job_id DESC
 	</select>
 	
 	<select id="selectJobAll" resultMap="SysJobResult">

+ 17 - 4
base-modules/service-system/service-system-api/src/main/java/com/usky/system/RemoteMceService.java

@@ -2,6 +2,8 @@ package com.usky.system;
 
 
 import com.usky.common.core.bean.ApiResult;
+
+import com.usky.system.domain.MceRequestVO;
 import com.usky.system.factory.RemoteMceFallbackFactory;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.http.MediaType;
@@ -11,19 +13,30 @@ import org.springframework.web.bind.annotation.RequestBody;
 
 /**
  * 消息服务
- * 
+ *
  * @author ruoyi
  */
 @FeignClient(contextId = "remoteMceService", value = "usky-system", fallbackFactory = RemoteMceFallbackFactory.class)
-public interface RemoteMceService
-{
+public interface RemoteMceService {
     /**
      * 新增消息推送
      *
      * @param mceInfo 消息信息
      * @return 结果
      */
-    @PostMapping(value = "/addMce",produces= MediaType.APPLICATION_JSON_UTF8_VALUE,consumes = "application/json;" +
+    @PostMapping(value = "/addMce", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = "application/json;" +
             "charset=UTF-8")
     public ApiResult<Void> addMce(@RequestBody String mceInfo);
+
+    /**
+     * @description: 消息推送-新
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/3/14 14:58
+     * @param: [mceInfo]
+     * @return: com.usky.common.core.bean.ApiResult<java.lang.Void>
+     **/
+    @PostMapping(value = "/addMceReceive")
+    ApiResult<Void> addMceReceive(MceRequestVO mceInfo);
+
 }

+ 125 - 0
base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/MceRequestVO.java

@@ -0,0 +1,125 @@
+package com.usky.system.domain;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.usky.common.core.bean.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ *
+ * @author fyc
+ * @email yuchuan.fu@chinausky.com
+ * @date 2025/3/13
+ */
+@EqualsAndHashCode(callSuper = true)
+@Slf4j
+@Data
+public class MceRequestVO extends BaseEntity {
+
+    /** 字典标签  */
+    private String infoTypeName;
+
+    /** 消息类型  */
+    @NotBlank(message = "消息类型 infoType 不能为空!")
+    private String infoType;
+
+    /** 消息标题  */
+    @NotBlank(message = "消息标题 infoTitle 不能为空!")
+    private String infoTitle;
+
+    /** 消息内容  */
+    @NotBlank(message = "消息内容 infoContent 不能为空!")
+    private String infoContent;
+
+    /** 用户名称
+     * 登录账号 loginAccount
+     * */
+    @NotBlank(message = "消息发布人 userName 不能为空!")
+    private String userName;
+
+    /** 消息详情id  */
+    @NotNull(message = "消息详情 id 不能为空!")
+    private Integer id;
+
+    /** 消息接收人userId集合  */
+    @NotNull(message = "消息接收人 userIds 不能为空!")
+    private List<Long> userIds;
+
+    /**
+     * ip地址
+     */
+    private String ipAddress;
+
+    /**
+     * 登录地址
+     */
+    private String loginAddress;
+
+    /**
+     * 登录方式
+     */
+    private String loginType;
+
+    /**
+     * 审批结果
+     */
+    private String approvalResult;
+
+    /**
+     * 流程名称
+     */
+    private String processName;
+
+    /**
+     * 审批节点
+     */
+    private String approvalNode;
+
+    /**
+     * 真实姓名
+     */
+    private String realName;
+
+    /**
+     * oa跳转类型 (todo我的待办、me我发起的、copy抄送我的)
+     */
+    private String oaType;
+
+    /**
+     * 设备id
+     */
+    private String deviceId;
+
+    /**
+     * 报警时间
+     */
+    private String alarmTime;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 报警发送方式(站内消息通知是默认的,1:APP,2:微信)
+     */
+    private String alarmSendType;
+
+    @Override
+    public String toString() {
+        ObjectMapper objectMapper = new ObjectMapper();
+        try {
+            return objectMapper.writeValueAsString(this);
+        } catch (JsonProcessingException e) {
+            log.error("MceRequestVO toString error: {}", e.getMessage());
+            return "{}";
+        }
+    }
+}

+ 7 - 0
base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/SysOperLogVO.java

@@ -47,6 +47,9 @@ public class SysOperLogVO extends BaseEntity
     /** 操作地址 */
     private String operIp;
 
+    /** 操作地点 */
+    private String operLocation;
+
     /** 请求参数 */
     private String operParam;
 
@@ -195,6 +198,10 @@ public class SysOperLogVO extends BaseEntity
         this.operIp = operIp;
     }
 
+    public String getOperLocation() { return operLocation; }
+
+    public void setOperLocation(String operLocation) { this.operLocation = operLocation; }
+
     public String getOperParam()
     {
         return operParam;

+ 25 - 0
base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/SysPerson.java

@@ -106,6 +106,31 @@ public class SysPerson implements Serializable {
      */
     private Date updateTime;
 
+    /**
+     * 图片数据(base64编码)
+     */
+    private String faceBase;
+
+    /**
+     * 验证次数(默认0)
+     */
+    private Integer vefNum;
+
+    /**
+     * 人脸备注
+     */
+    private String remark;
+
+    /**
+     * 人脸状态(0=可用,1=不可用)
+     */
+    private Integer faceStatus;
+
+    /**
+     * 卡号
+     */
+    private String cardNum;
+
     public static long getSerialVersionUID() {
         return serialVersionUID;
     }

+ 24 - 0
base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/SysPersonVo.java

@@ -105,5 +105,29 @@ public class SysPersonVo implements Serializable {
      */
     private LocalDateTime updateTime;
 
+    /**
+     * 图片数据(base64编码)
+     */
+    private String faceBase;
+
+    /**
+     * 验证次数(默认0)
+     */
+    private Integer vefNum;
+
+    /**
+     * 人脸备注
+     */
+    private String remark;
+
+    /**
+     * 人脸状态(0=可用,1=不可用)
+     */
+    private Integer faceStatus;
+
+    /**
+     * 卡号
+     */
+    private String cardNum;
 
 }

+ 13 - 0
base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/SysUserVO.java

@@ -133,6 +133,19 @@ public class SysUserVO extends BaseEntity {
      */
     private String fullName;
 
+    /**
+     * 是否打开登录通知(1 表示是,0 表示否,默认 0)
+     */
+    private Integer isLoginNotify;
+
+    public Integer getIsLoginNotify() {
+        return isLoginNotify;
+    }
+
+    public void setIsLoginNotify(Integer isLoginNotify) {
+        this.isLoginNotify = isLoginNotify;
+    }
+
     public String getAddress() {
         return address;
     }

+ 12 - 10
base-modules/service-system/service-system-api/src/main/java/com/usky/system/factory/RemoteMceFallbackFactory.java

@@ -3,6 +3,7 @@ package com.usky.system.factory;
 
 import com.usky.common.core.bean.ApiResult;
 import com.usky.system.RemoteMceService;
+import com.usky.system.domain.MceRequestVO;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.cloud.openfeign.FallbackFactory;
@@ -10,24 +11,25 @@ import org.springframework.stereotype.Component;
 
 /**
  * 消息服务降级处理
- * 
+ *
  * @author ruoyi
  */
 @Component
-public class RemoteMceFallbackFactory implements FallbackFactory<RemoteMceService>
-{
+public class RemoteMceFallbackFactory implements FallbackFactory<RemoteMceService> {
     private static final Logger log = LoggerFactory.getLogger(RemoteMceFallbackFactory.class);
 
     @Override
-    public RemoteMceService create(Throwable throwable)
-    {
+    public RemoteMceService create(Throwable throwable) {
         log.error("用户服务调用失败:{}", throwable.getMessage());
-        return new RemoteMceService()
-        {
+        return new RemoteMceService() {
             @Override
-            public ApiResult<Void> addMce(String mceInfo)
-            {
-                return ApiResult.error("500","新增消息失败:" + throwable.getMessage());
+            public ApiResult<Void> addMce(String mceInfo) {
+                return ApiResult.error("500", "新增消息失败:" + throwable.getMessage());
+            }
+
+            @Override
+            public ApiResult<Void> addMceReceive(MceRequestVO mceInfo) {
+                return ApiResult.error("500", "新增消息失败:" + throwable.getMessage());
             }
         };
     }

+ 15 - 3
base-modules/service-system/service-system-biz/pom.xml

@@ -59,10 +59,22 @@
             <artifactId>hutool-all</artifactId>
         </dependency>
 
+        <!-- 监控服务器资源状态 -->
         <dependency>
-            <groupId>org.json</groupId>
-            <artifactId>json</artifactId>
-            <version>20210307</version>
+            <groupId>com.github.oshi</groupId>
+            <artifactId>oshi-core</artifactId>
+            <version>3.9.1</version>
+        </dependency>
+        <dependency>
+            <groupId>net.java.dev.jna</groupId>
+            <artifactId>jna-platform</artifactId>
+            <version>4.5.2</version>
+        </dependency>
+        <!-- 支持 gzip,确保 Spring 能自动解压 -->
+        <dependency>
+            <groupId>net.sourceforge.pjl-comp-filter</groupId>
+            <artifactId>pjl-comp-filter</artifactId>
+            <version>1.7</version>
         </dependency>
     </dependencies>
 

+ 2 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/RuoYiSystemApplication.java

@@ -12,6 +12,7 @@ import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.EnableAspectJAutoProxy;
 import org.springframework.core.env.Environment;
+import org.springframework.scheduling.annotation.EnableAsync;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
@@ -28,6 +29,7 @@ import java.net.UnknownHostException;
 @MapperScan(value = "com.usky.system.mapper")
 @ComponentScan(basePackages = {"com.usky"})
 @SpringBootApplication
+@EnableAsync
 public class RuoYiSystemApplication
 {
     private static final Logger LOGGER = LoggerFactory.getLogger(RuoYiSystemApplication.class);

+ 8 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/constant/constant.java

@@ -17,11 +17,18 @@ public class constant {
     public static final String WE_CHAT_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
     // 微信公众号消息推送地址
     public static final String WE_CHAT_REQUEST_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";
-    // 微信公众号推送消息模板id
+    // 微信公众号推送-告警-消息模板id
     public static final String WE_CHAT_TEMPLATE_ID = "FmrNuMzgh0E8bWg1j8a2R3zTmRarHYtZ72TSzPrF9Iw";
+    // 微信公众号推送-OA-消息模板id
+    public static final String WE_CHAT_OA_TEMPLATE_ID = "RDahJYyDGpQKEn6vzdifS9u9F-vxA6FOIIDe1cUw8WU";
+    // 微信公众号推送-报告提醒(工单)-消息模板id
+    public static final String WE_CHAT_WORK_TEMPLATE_ID = "0J7pBGkXq5nCEVsc9L6HBmfmUrO4BEOk-3d5WCndWZk";
+    // 微信公众号推送-登录-消息模板id
+    public static final String WE_CHAT_LOGIN_TEMPLATE_ID = "7o6J1_0gi89RsW3sR7Q853KTaWYT7Yu-jXjLnHbcB8M";
     // 微信公众号的消息回调地址(这儿可根据业务需求自定义动作,可选)
     public static final String WE_CHAT_CUSTOMER_CALL_URL = "https://manager.usky.cn/mobile/#/pages/common/appMessage/index?type=%s&typeName=%s&id=%s";
     public static final String WE_CHAT_CUSTOMER_CALL_URL1 = "https://manager.usky.cn/mobile/#/pages/common/appMessage/index?type=%s&id=%s";
+    public static final String WE_CHAT_CUSTOMER_CALL_URL3 = "https://manager.usky.cn/mobile/#/pages/common/appMessage/index?type=%s&typeName=%s&id=%s&oaType=%s";
     // 微信公众号的主题颜色
     public static final String WE_CHAT_TOP_COLOR = "#A349A4";
     // 微信公众号微信用户授权地址

+ 8 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/api/SysMceControllerApi.java

@@ -2,15 +2,16 @@ package com.usky.system.controller.api;
 
 import com.usky.common.core.bean.ApiResult;
 import com.usky.system.RemoteMceService;
+import com.usky.system.domain.MceRequestVO;
 import com.usky.system.service.MceReceiveService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
 
 
 @RestController
 public class SysMceControllerApi implements RemoteMceService {
 
-
     @Autowired
     private MceReceiveService mceReceiveService;
 
@@ -19,4 +20,10 @@ public class SysMceControllerApi implements RemoteMceService {
         mceReceiveService.add(mceInfo);
         return ApiResult.success();
     }
+
+    @Override
+    public ApiResult<Void> addMceReceive(@RequestBody MceRequestVO mceRequestVO) {
+        mceReceiveService.addMceReceive(mceRequestVO);
+        return ApiResult.success();
+    }
 }

+ 1 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/AuthorityConfigController.java

@@ -78,7 +78,7 @@ public class AuthorityConfigController {
     @GetMapping("getMobileConfigMenuList")
     public ApiResult<Map<String, Object>> getMobileConfigMenuList(@RequestParam(value = "platformId") Integer platformId,
                                                                      @RequestParam(value = "tenantId") Integer tenantId) {
-        List<SysMobileMenu> menus =sysPlatformMenuService.getMobilePlatformMenuList(platformId);
+        List<SysMobileMenu> menus =sysPlatformMenuService.getMobilePlatformMenuList(tenantId);
         Map<String, Object> ajax = new HashMap<>();
         ajax.put("checkedKeys", sysPlatformMenuService.selectMobilePlatformMenu(tenantId));
         ajax.put("menus", menuService.buildMobileMenuTreeSelect(menus));

+ 52 - 19
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/MceReceiveController.java

@@ -7,7 +7,9 @@ import com.usky.common.log.annotation.Log;
 import com.usky.common.log.enums.BusinessType;
 import com.usky.system.domain.MceReceive;
 import com.usky.system.service.MceReceiveService;
+import com.usky.system.service.vo.MceReceiveResponseVO;
 import io.swagger.models.auth.In;
+import org.apache.ibatis.annotations.Param;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -33,7 +35,7 @@ public class MceReceiveController {
     /**
      * 消息列表分页
      * @param infoTitle  消息标题
-     * @param infoType  消息标题
+     * @param infoType  消息类型
      * @param startTime  开始时间
      * @param endTime  开始时间
      * @param current      当前页
@@ -45,11 +47,11 @@ public class MceReceiveController {
                                                  @RequestParam(value = "infoType", required = false) String infoType,
                                                  @RequestParam(value = "startTime", required = false) String startTime,
                                                  @RequestParam(value = "endTime", required = false) String endTime,
-                                                 @RequestParam(value = "id",required = false) Integer id,
+                                                 @RequestParam(value = "id", required = false) Integer id,
+                                                 @RequestParam(value = "infoId", required = false) Integer infoId,
                                                  @RequestParam(value = "current", required = false, defaultValue = "1") Integer current,
-                                                 @RequestParam(value = "size", required = false, defaultValue = "10") Integer size)
-    {
-        return ApiResult.success(mceReceiveService.mceList(infoTitle, infoType,startTime, endTime, id,current, size));
+                                                 @RequestParam(value = "size", required = false, defaultValue = "10") Integer size) {
+        return ApiResult.success(mceReceiveService.mceList(infoTitle, infoType, startTime, endTime, id, infoId, current, size));
     }
 
     /**
@@ -68,9 +70,8 @@ public class MceReceiveController {
                                                        @RequestParam(value = "startTime", required = false) String startTime,
                                                        @RequestParam(value = "endTime", required = false) String endTime,
                                                        @RequestParam(value = "current", required = false, defaultValue = "1") Integer current,
-                                                       @RequestParam(value = "size", required = false, defaultValue = "10") Integer size)
-    {
-        return ApiResult.success(mceReceiveService.mceManageList(infoTitle, infoType,startTime, endTime, current, size));
+                                                       @RequestParam(value = "size", required = false, defaultValue = "10") Integer size) {
+        return ApiResult.success(mceReceiveService.mceManageList(infoTitle, infoType, startTime, endTime, current, size));
     }
 
     /**
@@ -83,9 +84,8 @@ public class MceReceiveController {
     @GetMapping("/mceManageById")
     public ApiResult<CommonPage<MceReceive>> mceManageById(@RequestParam(value = "id") Integer id,
                                                            @RequestParam(value = "current", required = false, defaultValue = "1") Integer current,
-                                                           @RequestParam(value = "size", required = false, defaultValue = "10") Integer size)
-    {
-        return ApiResult.success(mceReceiveService.mceManageById(id,current,size));
+                                                           @RequestParam(value = "size", required = false, defaultValue = "10") Integer size) {
+        return ApiResult.success(mceReceiveService.mceManageById(id, current, size));
     }
 
     /**
@@ -93,17 +93,26 @@ public class MceReceiveController {
      * @return
      */
     @GetMapping("/mceReceiveStatic")
-    public ApiResult<Map<String, Object>> mceReceiveStatic()
-    {
+    public ApiResult<Map<String, Object>> mceReceiveStatic() {
         return ApiResult.success(mceReceiveService.mceReceiveStatic());
     }
 
+    /**
+     * 消息中心分页接口
+     * @return
+     */
+    @GetMapping("/getMceReceiveList")
+    public ApiResult<CommonPage<MceReceiveResponseVO>> getMceReceiveList(@RequestParam(value = "pageNumber", required = false, defaultValue = "1") Integer pageNumber,
+                                                                         @RequestParam(value = "pageSize", required = false, defaultValue = "20") Integer pageSize) {
+        return ApiResult.success(mceReceiveService.getMceReceiveResponseVOList(pageNumber, pageSize));
+    }
+
     /**
      * 已读
      * @return
      */
     @PutMapping
-    ApiResult<Void> updateMceReceive(@RequestBody MceReceive mceReceive){
+    ApiResult<Void> updateMceReceive(@RequestBody MceReceive mceReceive) {
         mceReceiveService.updateMceReceive(mceReceive);
         return ApiResult.success();
     }
@@ -114,20 +123,44 @@ public class MceReceiveController {
      */
     @Log(title = "新增发布消息", businessType = BusinessType.INSERT)
     @PostMapping("/mceAdd")
-    ApiResult<Void> add(@RequestBody String mceReceive){
+    ApiResult<Void> add(@RequestBody String mceReceive) {
         mceReceiveService.add(mceReceive);
         return ApiResult.success();
     }
 
     /**
-     * 删除
+     * 消息发布-无需token
+     * @return
+     */
+    @PostMapping("/addMceNew")
+    ApiResult<Void> addNoToken(@RequestBody String mceNoToken) {
+        mceReceiveService.addNoToken(mceNoToken);
+        return ApiResult.success();
+    }
+
+
+    /**
+     * 删除消息及内容,并清空所有的消息接收表数据
      */
     @Log(title = "删除已发布消息", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{id}")
-    public ApiResult<Void> removeById(@PathVariable("id") Integer id)
-    {
+    @DeleteMapping("/remove/{contentId}")
+    public ApiResult<Void> removeById(@PathVariable("contentId") Integer id) {
         mceReceiveService.removeById(id);
         return ApiResult.success();
     }
+
+    /**
+     * 删除一条消息
+     **/
+    @Log(title = "删除消息", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{id}")
+    public ApiResult<Void> deleteById(@PathVariable("id") Integer id) {
+        boolean f = mceReceiveService.deleteById(id);
+        if (f) {
+            return ApiResult.success();
+        } else {
+            return ApiResult.error("删除失败");
+        }
+    }
 }
 

+ 12 - 2
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SendSmsController.java

@@ -16,6 +16,7 @@ import com.usky.system.domain.SysMobileTenantConfig;
 import com.usky.system.domain.SysUser;
 import com.usky.system.mapper.SysUserMapper;
 import com.usky.system.service.ISysUserService;
+import org.springframework.beans.factory.annotation.Value;
 import com.usky.system.service.SysMobileTenantConfigService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -47,13 +48,22 @@ public class SendSmsController {
     @Autowired
     private ISysUserService sysUserService;
 
+    @Value("${sms.ali.region-id}")
+    private String regionId;
+
+    @Value("${sms.ali.access-key-id}")
+    private String accessKeyId;
+
+    @Value("${sms.ali.access-key-secret}")
+    private String accessKeySecret;
+
     @GetMapping("/noteSending")
     public ApiResult<Void> noteSending(@RequestParam(value = "tenantId" ,required = false) Integer tenantId,@RequestParam(value = "phone") String phone) {
         if((tenantId != null) && !StringUtils.isBlank(phone)){
-            sysUserService.getAppUserInfo(null, tenantId, phone);
+            sysUserService.getAppUserInfo(null, tenantId, phone,null);
         }
 
-        DefaultProfile profile = DefaultProfile.getProfile("cn-beijing", "LTAI9WERPIFIlHDg", "p7SQ0rYpraebcdoJ0l3tOtYmmgrR4q");
+        DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
         String code = String.valueOf(new Random().nextInt(1000000));
         redisHelper.set(phone,code,300,TimeUnit.SECONDS);//key为手机号,value为验证码存储
         IAcsClient client = new DefaultAcsClient(profile);

+ 9 - 2
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysDeptController.java

@@ -12,6 +12,7 @@ import com.usky.system.domain.SysUser;
 import com.usky.system.domain.constants.UserConstants;
 import com.usky.system.service.ISysDeptService;
 import com.usky.system.service.ISysUserService;
+import com.usky.system.service.vo.TreeNode;
 import org.apache.commons.lang3.ArrayUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -46,6 +47,12 @@ public class SysDeptController extends BaseController {
         return ApiResult.success(depts);
     }
 
+    @GetMapping("/deptList")
+    public ApiResult deptList(SysDept dept) {
+        List<SysDept> depts = deptService.selectDept(dept);
+        return ApiResult.success(depts);
+    }
+
     /**
      * 查询部门列表(排除节点)
      */
@@ -84,7 +91,7 @@ public class SysDeptController extends BaseController {
      * 获取部门人员下拉树列表
      */
     @GetMapping("/deptUserTreeSelect")
-    public ApiResult treeselect(SysDept dept, SysUser user) {
+    public ApiResult <List<TreeNode>> treeselect(SysDept dept, SysUser user) {
         List<SysDept> depts = deptService.deptList(dept);
         List<SysUser> users = iSysUserService.selectDUserList(user);
         return ApiResult.success(deptService.buildDeptUserTreeSelect(depts, users));
@@ -94,7 +101,7 @@ public class SysDeptController extends BaseController {
      * 部门人员下拉树-工时统计
      */
     @GetMapping("/jurisdictionDeptUserTree")
-    public ApiResult jurisdictionDeptUserTree(SysDept dept, SysUser user) {
+    public ApiResult <List<TreeNode>> jurisdictionDeptUserTree(SysDept dept, SysUser user) {
         List<SysDept> depts = deptService.selectDeptList(dept);
         List<SysUser> users = iSysUserService.selectUserList(user);
         return ApiResult.success(deptService.buildDeptUserTreeSelect(depts, users));

+ 3 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysMenuController.java

@@ -17,6 +17,7 @@ import com.usky.system.domain.constants.UserConstants;
 import com.usky.system.model.LoginUser;
 import com.usky.system.service.ISysMenuService;
 import com.usky.system.service.ISysUserService;
+import com.usky.system.service.vo.PlatformRouterVo;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
@@ -176,7 +177,8 @@ public class SysMenuController extends BaseController
     @GetMapping("getRouters1")
     public ApiResult getRouters1()
     {
-        return ApiResult.success(menuService.buildPlatformMenus());
+        List<PlatformRouterVo> list = menuService.buildPlatformMenus();
+        return ApiResult.success(list);
     }
 
     /**

+ 226 - 4
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysPersonController.java

@@ -1,9 +1,31 @@
 package com.usky.system.controller.web;
 
 
-import org.springframework.web.bind.annotation.RequestMapping;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.usky.common.core.exception.BusinessException;
+import com.usky.common.core.bean.ApiResult;
+import com.usky.system.controller.web.page.TableDataInfo;
+import com.usky.common.security.utils.SecurityUtils;
+import com.usky.system.domain.SysPerson;
+import com.usky.system.domain.SysUser;
+import com.usky.system.domain.SysUserPerson;
+import com.usky.system.service.ISysUserService;
+import com.usky.system.service.SysPersonService;
+import com.usky.system.service.SysUserPersonService;
+import com.usky.common.core.util.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.BeanUtils;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
 
-import org.springframework.stereotype.Controller;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -13,9 +35,209 @@ import org.springframework.stereotype.Controller;
  * @author JCB
  * @since 2022-08-22
  */
-@Controller
+@RestController
 @RequestMapping("/sysPerson")
-public class SysPersonController {
+public class SysPersonController extends BaseController {
 
+    @Autowired
+    private SysPersonService sysPersonService;
+    @Autowired
+    private SysUserPersonService sysUserPersonService;
+    @Autowired
+    private ISysUserService sysUserService;
+
+    /**
+     * 人员列表(分页)
+     */
+    @GetMapping("/list")
+    public ApiResult<TableDataInfo> list(SysPerson person) {
+        startPage();
+        // 支持 fullName 模糊查询;其他字段保持按传入条件精确匹配
+        Long filterDeptId = person != null ? person.getDeptId() : null;
+
+        SysPerson queryEntity = new SysPerson();
+        if (person != null) {
+            BeanUtils.copyProperties(person, queryEntity);
+            // fullName 用 like 查询,避免 Wrappers.query(entity) 产生 fullName=xxx 的精确条件
+            queryEntity.setFullName(null);
+            // 部门、岗位以关联用户为准,不作为人员表列条件;部门筛选见下方按用户 dept_id 关联
+            queryEntity.setDeptId(null);
+            queryEntity.setPostId(null);
+        }
+        QueryWrapper<SysPerson> queryWrapper = Wrappers.query(queryEntity);
+        queryWrapper.lambda()
+                .like(person != null && StringUtils.isNotBlank(person.getFullName()),
+                        SysPerson::getFullName, person.getFullName());
+
+        // 按部门筛选:关联用户的 dept_id = filterDeptId
+        if (filterDeptId != null) {
+            LambdaQueryWrapper<SysUser> userQuery = Wrappers.<SysUser>lambdaQuery()
+                    .eq(SysUser::getDeptId, filterDeptId)
+                    .eq(SysUser::getDelFlag, "0");
+            Integer tenantId = SecurityUtils.getTenantId();
+            if (tenantId != null) {
+                userQuery.eq(SysUser::getTenantId, tenantId);
+            }
+            List<SysUser> deptUsers = sysUserService.list(userQuery);
+            if (deptUsers == null || deptUsers.isEmpty()) {
+                queryWrapper.apply("1 = 0");
+            } else {
+                List<Long> userIds = deptUsers.stream()
+                        .map(SysUser::getUserId)
+                        .filter(Objects::nonNull)
+                        .distinct()
+                        .collect(Collectors.toList());
+                List<SysUserPerson> deptRelations = sysUserPersonService.list(
+                        Wrappers.<SysUserPerson>lambdaQuery()
+                                .in(SysUserPerson::getUserId, userIds)
+                );
+                if (deptRelations == null || deptRelations.isEmpty()) {
+                    queryWrapper.apply("1 = 0");
+                } else {
+                    List<Integer> deptPersonIds = deptRelations.stream()
+                            .map(SysUserPerson::getPersonId)
+                            .filter(Objects::nonNull)
+                            .distinct()
+                            .collect(Collectors.toList());
+                    queryWrapper.lambda().in(SysPerson::getId, deptPersonIds);
+                }
+            }
+        }
+
+        List<SysPerson> list = sysPersonService.list(queryWrapper);
+
+        // 回显 userId,以及通过 userId 回显部门、岗位
+        if (list != null && !list.isEmpty()) {
+            List<Integer> personIds = list.stream()
+                    .map(SysPerson::getId)
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toList());
+            if (!personIds.isEmpty()) {
+                List<SysUserPerson> relations = sysUserPersonService.list(
+                        Wrappers.<SysUserPerson>lambdaQuery()
+                                .in(SysUserPerson::getPersonId, personIds)
+                );
+                final Map<Integer, Long> personUserMap;
+                if (relations != null && !relations.isEmpty()) {
+                    personUserMap = relations.stream()
+                            .collect(Collectors.toMap(
+                                    SysUserPerson::getPersonId,
+                                    SysUserPerson::getUserId,
+                                    (u1, u2) -> u1
+                            ));
+                    list.forEach(p -> {
+                        Long userId = personUserMap.get(p.getId());
+                        if (userId != null) {
+                            p.setUserId(userId);
+                        }
+                    });
+                } else {
+                    personUserMap = new HashMap<>();
+                }
+                sysPersonService.fillDeptAndPostForList(list, personUserMap);
+            }
+        }
+        return ApiResult.success(getDataTable(list));
+    }
+
+    /**
+     * 根据主键获取人员详情
+     */
+    @GetMapping("/{id}")
+    public ApiResult<SysPerson> getInfo(@PathVariable("id") Integer id) {
+        SysPerson person = sysPersonService.getById(id);
+        if (person != null) {
+            Long userId = null;
+            SysUserPerson userPerson = sysUserPersonService.getOne(
+                    Wrappers.<SysUserPerson>lambdaQuery()
+                            .eq(SysUserPerson::getPersonId, id)
+                            .last("limit 1")
+            );
+            if (userPerson != null) {
+                userId = userPerson.getUserId();
+                person.setUserId(userId);
+            }
+            sysPersonService.fillDeptAndPostFromUser(person, userId);
+        }
+        return ApiResult.success(person);
+    }
+
+    /**
+     * 新增人员并绑定用户
+     */
+    @PostMapping
+    @Transactional
+    public ApiResult<Void> add(@RequestBody SysPerson person) {
+        Long userId = person.getUserId();
+        if (Objects.isNull(userId)) {
+            throw new BusinessException("lack necessary param:userId is required!");
+        }
+        // 校验账户是否已被其他人员绑定
+        SysUserPerson existBind = sysUserPersonService.getOne(
+                Wrappers.<SysUserPerson>lambdaQuery()
+                        .eq(SysUserPerson::getUserId, userId)
+                        .last("limit 1")
+        );
+        if (existBind != null) {
+            throw new BusinessException("此账户已被其它人员绑定,请解绑后重试!");
+        }
+        // 先保存人员信息
+        sysPersonService.save(person);
+        // 新增用户-人员关联
+        SysUserPerson userPerson = new SysUserPerson();
+        userPerson.setUserId(userId);
+        userPerson.setPersonId(person.getId());
+        userPerson.setIsLoginNotify(0);
+        sysUserPersonService.save(userPerson);
+        return ApiResult.success();
+    }
+
+    /**
+     * 修改人员并更新绑定用户
+     */
+    @PutMapping
+    @Transactional
+    public ApiResult<Void> edit(@RequestBody SysPerson person) {
+        Long userId = person.getUserId();
+        if (Objects.isNull(userId)) {
+            throw new BusinessException("lack necessary param:userId is required!");
+        }
+        // 校验账户是否已被其他人员绑定(排除当前人员本身)
+        SysUserPerson existBind = sysUserPersonService.getOne(
+                Wrappers.<SysUserPerson>lambdaQuery()
+                        .eq(SysUserPerson::getUserId, userId)
+                        .last("limit 1")
+        );
+        if (existBind != null && !Objects.equals(existBind.getPersonId(), person.getId())) {
+            throw new BusinessException("此账户已被其它人员绑定,请解绑后重试!");
+        }
+        // 更新人员信息
+        sysPersonService.updateById(person);
+        // 先删除原有关联,再按当前传入的 userId 重新绑定
+        QueryWrapper<SysUserPerson> wrapper = Wrappers.query();
+        wrapper.eq("person_id", person.getId());
+        sysUserPersonService.remove(wrapper);
+
+        SysUserPerson userPerson = new SysUserPerson();
+        userPerson.setUserId(userId);
+        userPerson.setPersonId(person.getId());
+        userPerson.setIsLoginNotify(0);
+        sysUserPersonService.save(userPerson);
+        return ApiResult.success();
+    }
+
+    /**
+     * 删除人员(支持批量,逗号分隔),并解绑与用户的关联
+     */
+    @DeleteMapping("/{ids}")
+    public ApiResult<Void> remove(@PathVariable("ids") Integer[] ids) {
+        // 先删除关联关系
+        QueryWrapper<SysUserPerson> wrapper = Wrappers.query();
+        wrapper.in("person_id", Arrays.asList(ids));
+        sysUserPersonService.remove(wrapper);
+        // 再删除人员
+        sysPersonService.removeByIds(Arrays.asList(ids));
+        return ApiResult.success();
+    }
 }
 

+ 38 - 28
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysProfileController.java

@@ -7,10 +7,12 @@ import com.usky.common.core.util.StringUtils;
 import com.usky.common.security.service.TokenService;
 import com.usky.common.security.utils.SecurityUtils;
 import com.usky.system.domain.SysUser;
+import com.usky.system.domain.SysUserPerson;
 import com.usky.system.domain.SysUserVO;
 import com.usky.system.domain.constants.UserConstants;
 import com.usky.system.model.LoginUser;
 import com.usky.system.service.ISysUserService;
+import com.usky.system.service.SysUserPersonService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -21,29 +23,37 @@ import java.util.Map;
 
 /**
  * 个人信息 业务处理
- * 
+ *
  * @author yq
  */
 @RestController
 @RequestMapping("/user/profile")
-public class SysProfileController extends BaseController
-{
+public class SysProfileController extends BaseController {
     @Autowired
     private ISysUserService userService;
 
     @Autowired
     private TokenService tokenService;
 
+    @Autowired
+    private SysUserPersonService sysUserPersonService;
+
     /**
      * 个人信息
      */
     @GetMapping
-    public ApiResult profile()
-    {
+    public ApiResult profile() {
         LoginUser loginUser = SecurityUtils.getLoginUser();
         SysUserVO user = loginUser.getSysUser();
-        Map<String,Object> map = new HashMap<>();
-        map.put("user",user);
+
+        SysUserPerson one = sysUserPersonService.lambdaQuery()
+                .eq(SysUserPerson::getUserId, user.getUserId())
+                .select(SysUserPerson::getIsLoginNotify)
+                .one();
+        user.setIsLoginNotify(one.getIsLoginNotify());
+
+        Map<String, Object> map = new HashMap<>();
+        map.put("user", user);
         map.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername()));
         map.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername()));
         return ApiResult.success(map);
@@ -53,24 +63,30 @@ public class SysProfileController extends BaseController
      * 修改用户
      */
     @PutMapping
-    public ApiResult updateProfile(@RequestBody SysUser user)
-    {
+    public ApiResult updateProfile(@RequestBody SysUser user) {
         if (StringUtils.isNotEmpty(user.getPhonenumber())
-                && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
-        {
+                && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
             throw new BusinessException("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
         }
         if (StringUtils.isNotEmpty(user.getEmail())
-                && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
-        {
+                && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
             throw new BusinessException("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
         }
         LoginUser loginUser = SecurityUtils.getLoginUser();
         SysUserVO sysUser = loginUser.getSysUser();
         user.setUserId(sysUser.getUserId());
         user.setPassword(null);
-        if (userService.updateUserProfile(user) > 0)
-        {
+        if (userService.updateUserProfile(user) > 0) {
+
+            // 更新登录通知设置
+            Integer isLoginNotify = user.getIsLoginNotify();
+            if (isLoginNotify != null) {
+                sysUserPersonService.lambdaUpdate()
+                        .eq(SysUserPerson::getUserId, sysUser.getUserId())
+                        .set(SysUserPerson::getIsLoginNotify, isLoginNotify)
+                        .update();
+            }
+
             // 更新缓存用户信息
             sysUser.setNickName(user.getNickName());
             sysUser.setPhonenumber(user.getPhonenumber());
@@ -86,22 +102,18 @@ public class SysProfileController extends BaseController
      * 重置密码
      */
     @PutMapping("/updatePwd")
-    public ApiResult updatePwd(String oldPassword, String newPassword)
-    {
+    public ApiResult updatePwd(String oldPassword, String newPassword) {
         LoginUser loginUser = SecurityUtils.getLoginUser();
         SysUserVO sysUser = loginUser.getSysUser();
         String userName = sysUser.getUserName();
         String password = sysUser.getPassword();
-        if (!SecurityUtils.matchesPassword(oldPassword, password))
-        {
+        if (!SecurityUtils.matchesPassword(oldPassword, password)) {
             throw new BusinessException("修改密码失败,旧密码错误");
         }
-        if (SecurityUtils.matchesPassword(newPassword, password))
-        {
+        if (SecurityUtils.matchesPassword(newPassword, password)) {
             throw new BusinessException("新密码不能与旧密码相同");
         }
-        if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0)
-        {
+        if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0) {
             // 更新缓存用户密码
             sysUser.setPassword(SecurityUtils.encryptPassword(newPassword));
             tokenService.setLoginUser(loginUser);
@@ -114,13 +126,11 @@ public class SysProfileController extends BaseController
      * 头像上传
      */
     @PostMapping("/avatar")
-    public ApiResult avatar(@RequestParam String filePath) throws IOException
-    {
+    public ApiResult avatar(@RequestParam String filePath) throws IOException {
         LoginUser loginUser = SecurityUtils.getLoginUser();
         SysUserVO sysUser = loginUser.getSysUser();
-        if (userService.updateUserAvatar(loginUser.getUsername(), filePath))
-        {
-            Map<String,Object> map = new HashMap<>();
+        if (userService.updateUserAvatar(loginUser.getUsername(), filePath)) {
+            Map<String, Object> map = new HashMap<>();
             map.put("imgUrl", filePath);
             // 更新缓存用户头像
             sysUser.setAvatar(filePath);

+ 26 - 12
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysUserController.java

@@ -7,14 +7,10 @@ import com.usky.common.security.utils.SecurityUtils;
 import com.usky.common.core.bean.ApiResult;
 import com.usky.common.core.exception.BusinessErrorCode;
 import com.usky.system.controller.web.page.TableDataInfo;
-import com.usky.system.domain.SysDept;
-import com.usky.system.domain.SysRole;
-import com.usky.system.domain.SysUser;
+import com.usky.system.domain.*;
 import com.usky.system.domain.constants.UserConstants;
-import com.usky.system.service.ISysDeptService;
-import com.usky.system.service.ISysPostService;
-import com.usky.system.service.ISysRoleService;
-import com.usky.system.service.ISysUserService;
+import com.usky.system.mapper.SysUserTenantMapper;
+import com.usky.system.service.*;
 import com.usky.system.service.vo.SysUserNewVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
@@ -29,7 +25,7 @@ import java.util.stream.Collectors;
 
 /**
  * 用户信息
- * 
+ *
  * @author yq
  */
 @RestController
@@ -48,6 +44,12 @@ public class SysUserController extends BaseController
     @Autowired
     private ISysDeptService deptService;
 
+    @Autowired
+    private SysUserTenantMapper sysUserTenantMapper;
+
+    @Autowired
+    private SysUserPersonService sysUserPersonService;
+
     /**
      * 获取用户列表
      */
@@ -113,6 +115,7 @@ public class SysUserController extends BaseController
     @GetMapping(value = { "/", "/{userId}" })
     public ApiResult<Map<String,Object>> getInfo(@PathVariable(value = "userId", required = false) Long userId)
     {
+        Integer tenantId = SecurityUtils.getTenantId();
         Map<String,Object> ajax = new HashMap<>();
         List<SysRole> roles = roleService.selectRoleAll();
         ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
@@ -121,7 +124,7 @@ public class SysUserController extends BaseController
         {
             ajax.put("data", userService.selectUserById(userId));
             ajax.put("postIds", postService.selectPostListByUserId(userId));
-            ajax.put("roleIds", roleService.selectRoleListByUserId(userId));
+            ajax.put("roleIds", roleService.selectRoleListByUserId(userId, tenantId));
         }
         return ApiResult.success(ajax);
     }
@@ -149,6 +152,13 @@ public class SysUserController extends BaseController
         user.setCreateBy(SecurityUtils.getUsername());
         user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
         int row = userService.insertUser(user);
+
+        // 新增用户登录通知设置
+        SysUserPerson sysUserPerson = new SysUserPerson();
+        sysUserPerson.setUserId(user.getUserId());
+        sysUserPerson.setIsLoginNotify(0);
+        sysUserPersonService.save(sysUserPerson);
+
         return toAjax(row);
     }
 
@@ -160,20 +170,24 @@ public class SysUserController extends BaseController
     @PostMapping("/appAdd")
     public ApiResult<Void> appAdd(@Validated @RequestBody SysUser user)
     {
-        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserName(),user.getTenantId())))
+        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserName(),0)))
         {
             return ApiResult.error(BusinessErrorCode.BIZ_BUSINESS_ERROR.getCode(), "新增用户'" + user.getUserName() + "'失败,登录账号已存在");
         }
-        if(UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique1(user.getPhonenumber(),user.getTenantId()))){
+        if(UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique1(user.getPhonenumber(),0))){
             return ApiResult.error(BusinessErrorCode.BIZ_BUSINESS_ERROR.getCode(), "新增手机号'" + user.getPhonenumber() + "'失败,手机号已存在");
         }
+        if(UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique1(user.getEmail(),0))){
+            return ApiResult.error(BusinessErrorCode.BIZ_BUSINESS_ERROR.getCode(), "新增邮箱'" + user.getEmail() + "'失败,邮箱已存在");
+        }
         List<SysDept> list = deptService.deptListByTenant(user.getTenantId());
-        if (list.size() > 0){
+        if (!list.isEmpty()){
             user.setDeptId(list.get(0).getDeptId());
         }
         user.setUserType("00");
         user.setTenantId(user.getTenantId());
         user.setCreateBy(user.getUserName());
+        user.setTenantId(user.getTenantId());
         user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
         int row = userService.insertUser(user);
         return toAjax(row);

+ 21 - 3
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysUserPersonController.java

@@ -1,9 +1,13 @@
 package com.usky.system.controller.web;
 
-
+import com.usky.common.core.bean.ApiResult;
+import com.usky.system.service.SysUserPersonService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PutMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 
-import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
 
 /**
  * <p>
@@ -13,9 +17,23 @@ import org.springframework.stereotype.Controller;
  * @author JCB
  * @since 2022-08-22
  */
-@Controller
+@RestController
 @RequestMapping("/sysUserPerson")
 public class SysUserPersonController {
 
+    @Autowired
+    private SysUserPersonService sysUserPersonService;
+
+    /**
+     * 修改登录通知开关状态
+     * @param useId 用户id
+     * @param isLoginNotify 1:开启 0:关闭
+     * @return 0:失败
+     */
+    @PutMapping("/upIsLoginNotify")
+    public ApiResult<Integer> upIsLoginNotice(@RequestParam Long userId,
+                                              @RequestParam Integer isLoginNotify) {
+        return ApiResult.success(sysUserPersonService.upIsLoginNotify(userId, isLoginNotify));
+    }
 }
 

+ 16 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysUserTenantController.java

@@ -5,10 +5,14 @@ import com.usky.common.core.bean.ApiResult;
 import com.usky.common.core.exception.BusinessErrorCode;
 import com.usky.common.log.annotation.Log;
 import com.usky.common.log.enums.BusinessType;
+import com.usky.common.security.utils.SecurityUtils;
 import com.usky.system.domain.SysTenant;
+import com.usky.system.domain.SysUser;
 import com.usky.system.domain.SysUserTenant;
 import com.usky.system.service.SysUserTenantService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
@@ -62,5 +66,17 @@ public class SysUserTenantController extends BaseController {
     {
         return ApiResult.success(sysUserTenantService.getTenantByUser(userId));
     }
+
+    /**
+     * 修改用户默认租户
+     */
+    @Log(title = "修改用户默认租户", businessType = BusinessType.UPDATE)
+    @Transactional
+    @PutMapping
+    public ApiResult<Void> edit(@Validated @RequestBody SysUserTenant userTenant)
+    {
+        sysUserTenantService.updateUserTenant(userTenant);
+        return ApiResult.success();
+    }
 }
 

+ 27 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SystemInfoController.java

@@ -0,0 +1,27 @@
+package com.usky.system.controller.web;
+
+import com.usky.system.domain.SystemHardwareInfo;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/oshi")
+public class SystemInfoController {
+
+    @GetMapping("/list")
+    public SystemHardwareInfo getSystemHardwareInfo() {
+        SystemHardwareInfo systemHardwareInfo = new SystemHardwareInfo();
+        try {
+            // 调用 copyTo() 方法填充数据
+            systemHardwareInfo.copyTo();
+        } catch (Exception e) {
+            // 日志记录异常信息
+            e.printStackTrace();
+            // 可以根据需要返回错误信息或空对象
+            return null;
+        }
+        // 返回填充后的数据
+        return systemHardwareInfo;
+    }
+}

+ 21 - 5
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/TokenController.java

@@ -16,6 +16,7 @@ import com.usky.system.domain.*;
 import com.usky.system.mapper.SysUserMapper;
 import com.usky.system.model.LoginUser;
 import com.usky.system.service.*;
+import com.usky.system.service.util.IpUtils;
 import com.usky.system.service.vo.LoginBody;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -58,6 +59,9 @@ public class TokenController {
     @Autowired
     private MceSettingService mceSettingService;
 
+    @Autowired
+    private SysUserTenantService sysUserTenantService;
+
     @Resource
     private HttpServletRequest request;
     @Resource
@@ -76,10 +80,16 @@ public class TokenController {
     public ApiResult<?> appLogin(@RequestBody LoginBody form) {
 //        String phone = null;
         // 用户登录
-        SysUser userInfo = sysLoginService.appLogin(form.getUsername(), form.getPassword(), form.getTenantId(), form.getPhone(), form.getVerify());
+        SysUser userInfo = sysLoginService.appLogin(form.getUsername(), form.getPassword(), form.getTenantId(),
+                form.getPhone(), form.getVerify(), form.getMethod());
+        Integer isDefaulTenant = sysUserTenantService.getIsDefaultByUser(userInfo.getUserId());
         LoginUser sysUser = new LoginUser();
         SysUserVO sysUserVO = BeanMapperUtils.map(userInfo, SysUserVO.class);
-        sysUserVO.setTenantId(userInfo.getTenantId());
+        if (null != form.getMethod() && form.getMethod().equals("switch")){
+            sysUserVO.setTenantId(userInfo.getTenantId());
+        }else {
+            sysUserVO.setTenantId(isDefaulTenant);
+        }
         sysUser.setSysUser(sysUserVO);
         Set<String> rolePermission = permissionService.getRolePermission(userInfo.getUserId());
         sysUser.setRoles(rolePermission);
@@ -126,9 +136,9 @@ public class TokenController {
         if(CollectionUtils.isEmpty(list)){
             //新增消息设置记录
             MceSetting mceSetting = new MceSetting();
-            mceSetting.setAppMode("{\"1\":true,\"2\":true,\"3\":true,\"4\":true}");
-            mceSetting.setPcMode("{\"1\":true,\"2\":true,\"3\":true,\"4\":true}");
-            mceSetting.setWcMode("{\"1\":true,\"2\":true,\"3\":true,\"4\":true}");
+            mceSetting.setAppMode("{\"1\":true,\"2\":true,\"3\":true,\"4\":true,\"5\":true}");
+            mceSetting.setPcMode("{\"1\":true,\"2\":true,\"3\":true,\"4\":true,\"5\":true}");
+            mceSetting.setWcMode("{\"1\":true,\"2\":true,\"3\":true,\"4\":true,\"5\":true}");
 
             mceSetting.setCreateBy(userInfo.getUserName());
             mceSetting.setCreateTime(LocalDateTime.now());
@@ -145,6 +155,12 @@ public class TokenController {
         return ApiResult.success(tokenService.createToken(sysUser,openId));
     }
 
+    @PostMapping("getIp")
+    public ApiResult<?> getIp() {
+        String clientIp = IpUtils.getClientIp(request);
+        return ApiResult.success(clientIp);
+    }
+
 
     //手机端发送扫码信息,二维码编号,用户名信息
     @GetMapping("getQrCodeResult")

+ 68 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/Cpu.java

@@ -0,0 +1,68 @@
+package com.usky.system.domain;
+
+import cn.hutool.core.util.NumberUtil;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class Cpu implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    /**
+     * 核心数
+     */
+    private int cpuNum;
+
+
+    /**
+     * CPU总的使用率
+     */
+    private double total;
+
+
+    /**
+     * CPU系统使用率
+     */
+    private double sys;
+
+
+    /**
+     * CPU用户使用率
+     */
+    private double used;
+
+
+    /**
+     * CPU当前等待率
+     */
+    private double wait;
+
+
+    /**
+     * CPU当前空闲率
+     */
+    private double free;
+
+
+    public double getTotal() {
+        return NumberUtil.round(NumberUtil.mul(total, 100), 2).doubleValue();
+    }
+
+    public double getSys() {
+        return NumberUtil.round(NumberUtil.mul(sys / total, 100), 2).doubleValue();
+    }
+
+    public double getUsed() {
+        return NumberUtil.round(NumberUtil.mul(used / total, 100), 2).doubleValue();
+    }
+
+    public double getWait() {
+        return NumberUtil.round(NumberUtil.mul(wait / total, 100), 2).doubleValue();
+    }
+
+    public double getFree() {
+        return NumberUtil.round(NumberUtil.mul(free / total, 100), 2).doubleValue();
+    }
+}

+ 112 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/Jvm.java

@@ -0,0 +1,112 @@
+package com.usky.system.domain;
+
+import cn.hutool.core.date.DateUnit;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.NumberUtil;
+import lombok.Data;
+import java.io.Serializable;
+import java.lang.management.ManagementFactory;
+import java.util.Date;
+
+@Data
+public class Jvm implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+
+    /**
+     * 当前JVM占用的内存总数(M)
+     */
+    private double total;
+
+
+    /**
+     * JVM最大可用内存总数(M)
+     */
+    private double max;
+
+
+    /**
+     * JVM空闲内存(M)
+     */
+    private double free;
+
+
+    /**
+     * JDK版本
+     */
+    private String version;
+
+
+    /**
+     * JDK路径
+     */
+    private String home;
+
+
+    public double getTotal() {
+        return NumberUtil.div(total, (1024 * 1024), 2);
+    }
+
+    public double getMax() {
+        return NumberUtil.div(max, (1024 * 1024), 2);
+    }
+
+    public double getFree() {
+        return NumberUtil.div(free, (1024 * 1024), 2);
+    }
+
+    public double getUsed() {
+        return NumberUtil.div(total - free, (1024 * 1024), 2);
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public String getHome() {
+        return home;
+    }
+
+    public double getUsage() {
+        return NumberUtil.mul(NumberUtil.div(total - free, total, 4), 100);
+    }
+    /**
+     * 获取JDK名称
+     */
+    public String getName() {
+        return ManagementFactory.getRuntimeMXBean().getVmName();
+    }
+
+    /**
+     * JDK启动时间
+     */
+    public String getStartTime() {
+        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+        Date date = new Date(time);
+        return DateUtil.formatDateTime(date);
+    }
+
+    /**
+     * JDK运行时间
+     */
+    public String getRunTime() {
+        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+        Date date = new Date(time);
+
+
+        //运行多少分钟
+        long runMS = DateUtil.between(date, new Date(), DateUnit.MS);
+
+
+        long nd = 1000 * 24 * 60 * 60;
+        long nh = 1000 * 60 * 60;
+        long nm = 1000 * 60;
+
+
+        long day = runMS / nd;
+        long hour = runMS % nd / nh;
+        long min = runMS % nd % nh / nm;
+        return day + "天" + hour + "小时" + min + "分钟";
+    }
+}

+ 47 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/Mem.java

@@ -0,0 +1,47 @@
+package com.usky.system.domain;
+
+import cn.hutool.core.util.NumberUtil;
+import lombok.Data;
+import java.io.Serializable;
+
+
+@Data
+public class Mem implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+
+    /**
+     * 内存总量
+     */
+    private double total;
+
+
+    /**
+     * 已用内存
+     */
+    private double used;
+
+
+    /**
+     * 剩余内存
+     */
+    private double free;
+
+
+    public double getTotal() {
+        return NumberUtil.div(total, (1024 * 1024 * 1024), 2);
+    }
+
+    public double getUsed() {
+        return NumberUtil.div(used, (1024 * 1024 * 1024), 2);
+    }
+
+    public double getFree() {
+        return NumberUtil.div(free, (1024 * 1024 * 1024), 2);
+    }
+
+    public double getUsage() {
+        return NumberUtil.mul(NumberUtil.div(used, total, 4), 100);
+    }
+}

+ 41 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/Sys.java

@@ -0,0 +1,41 @@
+package com.usky.system.domain;
+
+import lombok.Data;
+import java.io.Serializable;
+
+
+@Data
+public class Sys implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+
+    /**
+     * 服务器名称
+     */
+    private String computerName;
+
+
+    /**
+     * 服务器Ip
+     */
+    private String computerIp;
+
+
+    /**
+     * 项目路径
+     */
+    private String userDir;
+
+
+    /**
+     * 操作系统
+     */
+    private String osName;
+
+
+    /**
+     * 系统架构
+     */
+    private String osArch;
+}

+ 53 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysFile.java

@@ -0,0 +1,53 @@
+package com.usky.system.domain;
+
+import lombok.Data;
+import java.io.Serializable;
+
+
+@Data
+public class SysFile implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+
+    /**
+     * 盘符路径
+     */
+    private String dirName;
+
+
+    /**
+     * 盘符类型
+     */
+    private String sysTypeName;
+
+
+    /**
+     * 文件类型
+     */
+    private String typeName;
+
+
+    /**
+     * 总大小
+     */
+    private String total;
+
+
+    /**
+     * 剩余大小
+     */
+    private String free;
+
+
+    /**
+     * 已经使用量
+     */
+    private String used;
+
+
+    /**
+     * 资源的使用率
+     */
+    private double usage;
+}

+ 7 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysMenu.java

@@ -57,6 +57,9 @@ public class SysMenu extends BaseEntity
     /** 类型(M目录 C菜单 F按钮) */
     private String menuType;
 
+    /** 类型(1.基础功能,2.业务功能) */
+    private Integer menuMold;
+
     /** 显示状态(0显示 1隐藏) */
     private String visible;
     
@@ -195,6 +198,10 @@ public class SysMenu extends BaseEntity
         this.menuType = menuType;
     }
 
+    public Integer getMenuMold() { return menuMold; }
+
+    public void setMenuMold(Integer menuMold) { this.menuMold = menuMold; }
+
     public String getVisible()
     {
         return visible;

+ 153 - 32
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysNotice.java

@@ -1,22 +1,27 @@
 package com.usky.system.domain;
 
 
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.usky.common.core.bean.BaseEntity;
 import io.swagger.models.auth.In;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
+import org.springframework.data.annotation.Transient;
+import org.springframework.format.annotation.DateTimeFormat;
 
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.Size;
+import java.time.LocalDateTime;
 
 
 /**
  * 通知公告表 sys_notice
- * 
+ *
  * @author yq
  */
-public class SysNotice extends BaseEntity
-{
+public class SysNotice {
     private static final long serialVersionUID = 1L;
 
     /** 公告ID */
@@ -34,18 +39,52 @@ public class SysNotice extends BaseEntity
     /** 公告状态(0正常 1关闭) */
     private String status;
 
-    public Integer getNoticeId()
-    {
+    /** 附件地址 */
+    private String fileUrl;
+
+    /** 作者 */
+    private String author;
+
+    /** 通知接收部门id */
+    private String deptId;
+
+    // 新增临时字段,用于时间段查询
+    @TableField(exist = false)
+    @JsonIgnore
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime startTime;
+
+    @TableField(exist = false)
+    @JsonIgnore
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime endTime;
+
+    /** 创建者 */
+    private String createBy;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    /** 更新者 */
+    private String updateBy;
+
+    /** 更新时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    /** 租户id */
+    private Integer tenantId;
+
+    public Integer getNoticeId() {
         return noticeId;
     }
 
-    public void setNoticeId(Integer noticeId)
-    {
+    public void setNoticeId(Integer noticeId) {
         this.noticeId = noticeId;
     }
 
-    public void setNoticeTitle(String noticeTitle)
-    {
+    public void setNoticeTitle(String noticeTitle) {
         this.noticeTitle = noticeTitle;
     }
 
@@ -56,49 +95,131 @@ public class SysNotice extends BaseEntity
         return noticeTitle;
     }
 
-    public void setNoticeType(String noticeType)
-    {
+    public void setNoticeType(String noticeType) {
         this.noticeType = noticeType;
     }
 
-    public String getNoticeType()
-    {
+    public String getNoticeType() {
         return noticeType;
     }
 
-    public void setNoticeContent(String noticeContent)
-    {
+    public void setNoticeContent(String noticeContent) {
         this.noticeContent = noticeContent;
     }
 
-    public String getNoticeContent()
-    {
+    @NotBlank(message = "公告内容不能为空")
+    public String getNoticeContent() {
         return noticeContent;
     }
 
-    public void setStatus(String status)
-    {
+    public void setStatus(String status) {
         this.status = status;
     }
 
-    public String getStatus()
-    {
+    public String getStatus() {
         return status;
     }
 
+    public String getFileUrl() {
+        return fileUrl;
+    }
+
+    public void setFileUrl(String fileUrl) {
+        this.fileUrl = fileUrl;
+    }
+
+    public String getAuthor() {
+        return author;
+    }
+
+    public void setAuthor(String author) {
+        this.author = author;
+    }
+
+    public LocalDateTime getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(LocalDateTime startTime) {
+        this.startTime = startTime;
+    }
+
+    public LocalDateTime getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(LocalDateTime endTime) {
+        this.endTime = endTime;
+    }
+
+    @NotBlank(message = "通知接收部门id不能为空")
+    public String getDeptId() {
+        return deptId;
+    }
+
+    public void setDeptId(String deptId) {
+        this.deptId = deptId;
+    }
+
+    public String getCreateBy() {
+        return createBy;
+    }
+
+    public void setCreateBy(String createBy) {
+        this.createBy = createBy;
+    }
+
+    public LocalDateTime getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(LocalDateTime createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getUpdateBy() {
+        return updateBy;
+    }
+
+    public void setUpdateBy(String updateBy) {
+        this.updateBy = updateBy;
+    }
+
+    public LocalDateTime getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(LocalDateTime updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public Integer getTenantId() {
+        return tenantId;
+    }
+
+    public void setTenantId(Integer tenantId) {
+        this.tenantId = tenantId;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
-            .append("noticeId", getNoticeId())
-            .append("noticeTitle", getNoticeTitle())
-            .append("noticeType", getNoticeType())
-            .append("noticeContent", getNoticeContent())
-            .append("status", getStatus())
-            .append("createBy", getCreateBy())
-            .append("createTime", getCreateTime())
-            .append("updateBy", getUpdateBy())
-            .append("updateTime", getUpdateTime())
-            .append("remark", getRemark())
-            .toString();
+                .append("noticeId", getNoticeId())
+                .append("noticeTitle", getNoticeTitle())
+                .append("noticeType", getNoticeType())
+                .append("noticeContent", getNoticeContent())
+                .append("status", getStatus())
+                .append("createBy", getCreateBy())
+                .append("createTime", getCreateTime())
+                .append("updateBy", getUpdateBy())
+                .append("updateTime", getUpdateTime())
+                .append("fileUrl", getFileUrl())
+                .append("author", getAuthor())
+                .append("deptId", getDeptId())
+                .append("createTime", getCreateTime())
+                .append("createBy", getCreateBy())
+                .append("updateBy", getUpdateBy())
+                .append("updateTime", getUpdateTime())
+                .toString();
     }
 }

+ 47 - 2
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysPerson.java

@@ -1,6 +1,7 @@
 package com.usky.system.domain;
 
 import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -64,13 +65,15 @@ public class SysPerson implements Serializable {
     private String linkPhone;
 
     /**
-     * 岗位ID
+     * 岗位ID(来自关联用户,不入库)
      */
+    @TableField(exist = false)
     private Long postId;
 
     /**
-     * 部门ID
+     * 部门ID(来自关联用户,不入库)
      */
+    @TableField(exist = false)
     private Long deptId;
 
     /**
@@ -113,5 +116,47 @@ public class SysPerson implements Serializable {
      */
     private Date updateTime;
 
+    /**
+     * 图片数据(base64编码)
+     */
+    private String faceBase;
+
+    /**
+     * 验证次数(默认0)
+     */
+    private Integer vefNum;
+
+    /**
+     * 人脸备注
+     */
+    private String remark;
+
+    /**
+     * 人脸状态(0=可用,1=不可用)
+     */
+    private Integer faceStatus;
+
+    /**
+     * 卡号
+     */
+    private String cardNum;
+
+    /**
+     * 关联的用户ID(非持久化字段,仅用于回显)
+     */
+    @TableField(exist = false)
+    private Long userId;
+
+    /**
+     * 部门名称(非持久化字段,仅用于回显)
+     */
+    @TableField(exist = false)
+    private String deptName;
+
+    /**
+     * 岗位名称(来自关联用户,不入库)
+     */
+    @TableField(exist = false)
+    private String postName;
 
 }

+ 10 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysPlatform.java

@@ -51,6 +51,16 @@ public class SysPlatform implements Serializable {
      */
     private String icon;
 
+    /**
+     * 显示顺序
+     */
+    private Integer orderNum;
+
+    /**
+     * 应用类型(1.基础功能,2.业务功能)
+     */
+    private Integer platformType;
+
     /**
      * 创建者
      */

+ 12 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysTenant.java

@@ -121,4 +121,16 @@ public class SysTenant implements Serializable {
      */
     @TableField(exist = false)
     private Integer originalTenantId;
+
+    /**
+     * 是否为默认租户(默认0; 0:否,1:是)
+     */
+    @TableField(exist = false)
+    private Boolean isDefault;
+
+    /**
+     * 租户logo
+     */
+    @TableField(exist = false)
+    private String tenantLogo;
 }

+ 27 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysUser.java

@@ -13,6 +13,7 @@ import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.Size;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
 
 /**
@@ -24,6 +25,17 @@ public class SysUser extends BaseEntity
 {
     private static final long serialVersionUID = 1L;
 
+    /**
+     * 与 BaseEntity 同名字段:MyBatis-Plus 按子类优先收集字段,此处显式 {@code exist = false},
+     * 避免仅依赖父类 private 字段注解时仍生成 {@code search_value}/{@code params} 列。
+     * 读写仍使用继承自 BaseEntity 的 getter/setter(操作父类字段)。
+     */
+    @TableField(exist = false)
+    private String searchValue;
+
+    @TableField(exist = false)
+    private Map<String, Object> params;
+
     /** 用户ID */
     @TableId
     private Long userId;
@@ -100,6 +112,20 @@ public class SysUser extends BaseEntity
     /** 姓名 */
     private String fullName;
 
+    /**
+     * 是否打开登录通知(1 表示是,0 表示否,默认 0)
+     */
+    @TableField(exist = false)
+    private Integer isLoginNotify;
+
+    public Integer getIsLoginNotify() {
+        return isLoginNotify;
+    }
+
+    public void setIsLoginNotify(Integer isLoginNotify) {
+        this.isLoginNotify = isLoginNotify;
+    }
+
     /** 岗位 */
     @TableField(exist = false)
     private String post;
@@ -391,6 +417,7 @@ public class SysUser extends BaseEntity
             .append("updateTime", getUpdateTime())
             .append("remark", getRemark())
             .append("dept", getDept())
+            .append("isLoginNotify",  getIsLoginNotify())
             .toString();
     }
 }

+ 6 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysUserPerson.java

@@ -1,6 +1,7 @@
 package com.usky.system.domain;
 
 import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import java.io.Serializable;
 import lombok.Data;
@@ -36,5 +37,10 @@ public class SysUserPerson implements Serializable {
      */
     private Integer personId;
 
+    /**
+     * 是否打开登录通知(1 表示是,0 表示否,默认 0)
+     */
+    private Integer isLoginNotify;
+
 
 }

+ 22 - 15
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysUserRole.java

@@ -5,42 +5,49 @@ import org.apache.commons.lang3.builder.ToStringStyle;
 
 /**
  * 用户和角色关联 sys_user_role
- * 
+ *
  * @author yq
  */
-public class SysUserRole
-{
+public class SysUserRole {
     /** 用户ID */
     private Long userId;
-    
+
     /** 角色ID */
     private Long roleId;
 
-    public Long getUserId()
-    {
+    /** 租户ID */
+    private Integer tenantId;
+
+    public Long getUserId() {
         return userId;
     }
 
-    public void setUserId(Long userId)
-    {
+    public void setUserId(Long userId) {
         this.userId = userId;
     }
 
-    public Long getRoleId()
-    {
+    public Long getRoleId() {
         return roleId;
     }
 
-    public void setRoleId(Long roleId)
-    {
+    public void setRoleId(Long roleId) {
         this.roleId = roleId;
     }
 
+    public Integer getTenantId() {
+        return tenantId;
+    }
+
+    public void setTenantId(Integer tenantId) {
+        this.tenantId = tenantId;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
-            .append("userId", getUserId())
-            .append("roleId", getRoleId())
-            .toString();
+                .append("userId", getUserId())
+                .append("roleId", getRoleId())
+                .append("tenantId", getTenantId())
+                .toString();
     }
 }

+ 185 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SystemHardwareInfo.java

@@ -0,0 +1,185 @@
+package com.usky.system.domain;
+
+import cn.hutool.core.net.NetUtil;
+import cn.hutool.core.util.NumberUtil;
+import lombok.Data;
+import oshi.SystemInfo;
+import oshi.hardware.CentralProcessor;
+import oshi.hardware.CentralProcessor.TickType;
+import oshi.hardware.GlobalMemory;
+import oshi.hardware.HardwareAbstractionLayer;
+import oshi.software.os.FileSystem;
+import oshi.software.os.OSFileStore;
+import oshi.software.os.OperatingSystem;
+import oshi.util.Util;
+import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+
+
+@Data
+public class SystemHardwareInfo  implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+
+    private static final int OSHI_WAIT_SECOND = 1000;
+
+
+    /**
+     * CPU相关信息
+     */
+    private Cpu cpu = new Cpu();
+
+
+    /**
+     * 內存相关信息
+     */
+    private Mem mem = new Mem();
+
+
+    /**
+     * JVM相关信息
+     */
+    private Jvm jvm = new Jvm();
+
+
+    /**
+     * 服务器相关信息
+     */
+    private Sys sys = new Sys();
+
+
+    /**
+     * 磁盘相关信息
+     */
+    private List<SysFile> sysFiles = new LinkedList<SysFile>();
+
+
+    public void copyTo() throws Exception {
+        SystemInfo si = new SystemInfo();
+        HardwareAbstractionLayer hal = si.getHardware();
+
+
+        setCpuInfo(hal.getProcessor());
+
+
+        setMemInfo(hal.getMemory());
+
+
+        setSysInfo();
+
+
+        setJvmInfo();
+
+
+        setSysFiles(si.getOperatingSystem());
+    }
+
+    /**
+     * 设置CPU信息
+     */
+    private void setCpuInfo(CentralProcessor processor) {
+        // CPU信息
+        long[] prevTicks = processor.getSystemCpuLoadTicks();
+        Util.sleep(OSHI_WAIT_SECOND);
+        long[] ticks = processor.getSystemCpuLoadTicks();
+        long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];
+        long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];
+        long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()];
+        long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()];
+        long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()];
+        long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()];
+        long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()];
+        long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()];
+        long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
+        cpu.setCpuNum(processor.getLogicalProcessorCount());
+        cpu.setTotal(totalCpu);
+        cpu.setSys(cSys);
+        cpu.setUsed(user);
+        cpu.setWait(iowait);
+        cpu.setFree(idle);
+    }
+
+    /**
+     * 设置内存信息
+     */
+    private void setMemInfo(GlobalMemory memory) {
+        mem.setTotal(memory.getTotal());
+        mem.setUsed(memory.getTotal() - memory.getAvailable());
+        mem.setFree(memory.getAvailable());
+    }
+
+    /**
+     * 设置服务器信息
+     */
+    private void setSysInfo() {
+        Properties props = System.getProperties();
+        SystemInfo si = new SystemInfo();
+        OperatingSystem os = si.getOperatingSystem();
+        // 使用 oshi 获取主机名
+        sys.setComputerName(os.getNetworkParams().getHostName());
+        sys.setComputerIp(NetUtil.getLocalhostStr());
+        sys.setOsName(props.getProperty("os.name"));
+        sys.setOsArch(props.getProperty("os.arch"));
+        sys.setUserDir(props.getProperty("user.dir"));
+    }
+
+    /**
+     * 设置Java虚拟机
+     */
+    private void setJvmInfo() {
+        Properties props = System.getProperties();
+        jvm.setTotal(Runtime.getRuntime().totalMemory());
+        jvm.setMax(Runtime.getRuntime().maxMemory());
+        jvm.setFree(Runtime.getRuntime().freeMemory());
+        jvm.setVersion(props.getProperty("java.version"));
+        jvm.setHome(props.getProperty("java.home"));
+    }
+
+    /**
+     * 设置磁盘信息
+     */
+    private void setSysFiles(OperatingSystem os) {
+        FileSystem fileSystem = os.getFileSystem();
+        OSFileStore[] fsArray = fileSystem.getFileStores();
+        for (OSFileStore fs : fsArray) {
+            long free = fs.getUsableSpace();
+            long total = fs.getTotalSpace();
+            long used = total - free;
+            SysFile sysFile = new SysFile();
+            sysFile.setDirName(fs.getMount());
+            sysFile.setSysTypeName(fs.getType());
+            sysFile.setTypeName(fs.getName());
+            sysFile.setTotal(convertFileSize(total));
+            sysFile.setFree(convertFileSize(free));
+            sysFile.setUsed(convertFileSize(used));
+            sysFile.setUsage(NumberUtil.round(NumberUtil.mul(used, total, 4), 100).doubleValue());
+            sysFiles.add(sysFile);
+        }
+    }
+
+    /**
+     * 字节转换
+     *
+     * @param size 字节大小
+     * @return 转换后值
+     */
+    public String convertFileSize(long size) {
+        long kb = 1024;
+        long mb = kb * 1024;
+        long gb = mb * 1024;
+        if (size >= gb) {
+            return String.format("%.1f GB" , (float) size / gb);
+        } else if (size >= mb) {
+            float f = (float) size / mb;
+            return String.format(f > 100 ? "%.0f MB" : "%.1f MB" , f);
+        } else if (size >= kb) {
+            float f = (float) size / kb;
+            return String.format(f > 100 ? "%.0f KB" : "%.1f KB" , f);
+        } else {
+            return String.format("%d B" , size);
+        }
+    }
+}

+ 8 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysDeptMapper.java

@@ -46,6 +46,14 @@ public interface SysDeptMapper extends BaseMapper<SysDept>
      */
     public SysDept selectDeptById(@Param("deptId") Long deptId);
 
+    /**
+     * 根据部门ID列表批量查询部门信息
+     *
+     * @param deptIds 部门ID列表
+     * @return 部门信息列表
+     */
+    public List<SysDept> selectDeptByIds(@Param("deptIds") List<Long> deptIds);
+
     /**
      * 根据ID查询所有子部门
      * 

+ 3 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysMenuMapper.java

@@ -86,7 +86,9 @@ public interface SysMenuMapper extends CrudMapper<SysMenu> {
      * @param platformId 应用ID
      * @return 应用级菜单列表
      */
-    public List<SysMenu> selectMenuTreeByUserId1(@Param("userId") Long userId,@Param("platformId") Long platformId);
+    public List<SysMenu> selectMenuTreeByUserId1(@Param("userId") Long userId,
+                                                 @Param("platformId") Long platformId,
+                                                 @Param("tenantId") Integer tenantId);
 
     public List<SysMenu> selectMenuTreeByUserIdOne(@Param("tenantId") Integer tenantId);
 

+ 9 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysMobileMenuMapper.java

@@ -43,6 +43,15 @@ public interface SysMobileMenuMapper extends CrudMapper<SysMobileMenu> {
      */
     public List<SysMobileMenu> selectMenuTreeByUserId(@Param("userId") long userId);
 
+    /**
+     * 根据用户Id查询菜单
+     *
+     * @param userId 用户Id
+     * @return 菜单列表
+     */
+    public List<SysMobileMenu> selectMenuTreeByUserId1(@Param("userId") long userId,
+                                                       @Param("tenantId") Integer tenantId);
+
     /**
      * 根据租户Id查询菜单
      *

+ 1 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysPlatformMenuMapper.java

@@ -22,7 +22,7 @@ public interface SysPlatformMenuMapper extends CrudMapper<SysPlatformMenu> {
     List<SysMenu> getMenuList(@Param("platformId") Integer platformId,
                               @Param("menuType") String menuType);
 
-    List<SysMobileMenu> getMobileMenuList(@Param("platformId") Integer platformId,
+    List<SysMobileMenu> getMobileMenuList(@Param("platformIds") List<Integer> platformIds,
                               @Param("menuType") String menuType);
 
     List<SysMenu> getMenuIdList(@Param("menuIds") Long[] menuIds,

+ 2 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysPostMapper.java

@@ -53,7 +53,8 @@ public interface SysPostMapper extends CrudMapper<SysPost>
      * @param userName 用户名
      * @return 结果
      */
-    public List<SysPost> selectPostsByUserName(@Param("userName") String userName);
+    public List<SysPost> selectPostsByUserName(@Param("userName") String userName,
+                                               @Param("tenantId") Integer tenantId);
 
     /**
      * 删除岗位信息

+ 4 - 2
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysRoleMapper.java

@@ -45,7 +45,8 @@ public interface SysRoleMapper extends CrudMapper<SysRole>
      * @param userId 用户ID
      * @return 选中角色ID列表
      */
-    public List<Integer> selectRoleListByUserId(@Param("userId") Long userId);
+    public List<Integer> selectRoleListByUserId(@Param("userId") Long userId,
+                                                @Param("tenantId") Integer tenantId);
 
     /**
      * 通过角色ID查询角色
@@ -61,7 +62,8 @@ public interface SysRoleMapper extends CrudMapper<SysRole>
      * @param userName 用户名
      * @return 角色列表
      */
-    public List<SysRole> selectRolesByUserName(@Param("userName") String userName);
+    public List<SysRole> selectRolesByUserName(@Param("userName") String userName,
+                                               @Param("tenantId") Integer tenantId);
 
     /**
      * 校验角色名称是否唯一

+ 2 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysTenantConfigMapper.java

@@ -5,6 +5,7 @@ import com.usky.system.domain.SysMenu;
 import com.usky.system.domain.SysTenantConfig;
 import com.usky.system.service.vo.SysTenantConfigVo;
 import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
 
 import java.util.List;
 
@@ -16,6 +17,7 @@ import java.util.List;
  * @author ya
  * @since 2022-05-06
  */
+@Repository
 public interface SysTenantConfigMapper extends CrudMapper<SysTenantConfig> {
     List<SysTenantConfigVo> getTenantConfig(@Param("url") String url);
 

+ 6 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysUserMapper.java

@@ -187,4 +187,10 @@ public interface SysUserMapper extends CrudMapper<SysUser> {
 
     SysUser selectUserTenantDataOne(@Param("tenantId") Integer tenantId,
                                     @Param("phone") String phone);
+
+    SysUser selectUserTenantData1(@Param("userName") String userName,
+                                 @Param("tenantId") Integer tenantId);
+
+    SysUser selectUserTenantDataOne1(@Param("tenantId") Integer tenantId,
+                                    @Param("phone") String phone);
 }

+ 4 - 4
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysUserRoleMapper.java

@@ -22,7 +22,7 @@ public interface SysUserRoleMapper extends CrudMapper<SysUserRole>
      * @param userId 用户ID
      * @return 结果
      */
-    public int deleteUserRoleByUserId(@Param("userId") Long userId);
+    public int deleteUserRoleByUserId(@Param("userId") Long userId, @Param("tenantId") Integer tenantId);
 
     /**
      * 批量删除用户和角色关联
@@ -30,7 +30,7 @@ public interface SysUserRoleMapper extends CrudMapper<SysUserRole>
      * @param ids 需要删除的数据ID
      * @return 结果
      */
-    public int deleteUserRole(@Param("ids") Long[] ids);
+    public int deleteUserRole(@Param("ids") Long[] ids, @Param("tenantId") Integer tenantId);
 
     /**
      * 通过角色ID查询角色使用数量
@@ -38,7 +38,7 @@ public interface SysUserRoleMapper extends CrudMapper<SysUserRole>
      * @param roleId 角色ID
      * @return 结果
      */
-    public int countUserRoleByRoleId(@Param("roleId") Long roleId);
+    public int countUserRoleByRoleId(@Param("roleId") Long roleId, @Param("tenantId") Integer tenantId);
 
     /**
      * 批量新增用户角色信息
@@ -63,5 +63,5 @@ public interface SysUserRoleMapper extends CrudMapper<SysUserRole>
      * @param userIds 需要删除的用户数据ID
      * @return 结果
      */
-    public int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds);
+    public int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds, @Param("tenantId") Integer tenantId);
 }

+ 11 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/ISysDeptService.java

@@ -24,6 +24,9 @@ public interface ISysDeptService extends IService<SysDept>
      */
     public List<SysDept> selectDeptList(SysDept dept);
 
+    // 查询租户下部门信,无数据权限
+    List<SysDept> selectDept(SysDept dept);
+
     public List<SysDept> deptList(SysDept dept);
 
     public List<SysDept> deptListByTenant(Integer tenantId);
@@ -67,6 +70,14 @@ public interface ISysDeptService extends IService<SysDept>
      */
     public SysDept selectDeptById(Long deptId);
 
+    /**
+     * 根据部门ID列表批量查询部门信息
+     *
+     * @param deptIds 部门ID列表
+     * @return 部门信息列表
+     */
+    public List<SysDept> selectDeptByIds(List<Long> deptIds);
+
     /**
      * 根据ID查询所有子部门(正常状态)
      * 

+ 1 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/ISysMenuService.java

@@ -71,7 +71,7 @@ public interface ISysMenuService extends CrudService<SysMenu>
      * @param userId 用户ID
      * @return 菜单列表
      */
-    public List<SysMenu> selectMenuTreeByUserId1(Long userId,Long platformId);
+    public List<SysMenu> selectMenuTreeByUserId1(Long userId,Long platformId, Integer tenantId);
 
     List<SysMenu> selectMenuTreeByUserIdOne(Integer tenantId);
 

+ 1 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/ISysRoleService.java

@@ -52,7 +52,7 @@ public interface ISysRoleService extends CrudService<SysRole>
      * @param userId 用户ID
      * @return 选中角色ID列表
      */
-    public List<Integer> selectRoleListByUserId(Long userId);
+    public List<Integer> selectRoleListByUserId(Long userId, Integer tenantId);
 
     /**
      * 通过角色ID查询角色

+ 1 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/ISysUserService.java

@@ -263,7 +263,7 @@ public interface ISysUserService extends CrudService<SysUser> {
 
     public LoginUser getUserInfoOne(String username,Integer tenantId);
 
-    SysUser getAppUserInfo(String username, Integer tenantId,String phone);
+    SysUser getAppUserInfo(String username, Integer tenantId,String phone,String method);
     
     public Boolean register(SysUser sysUser);
 

+ 3 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/MceContentService.java

@@ -3,6 +3,7 @@ package com.usky.system.service;
 import com.alibaba.fastjson.JSONObject;
 import com.usky.system.domain.MceContent;
 import com.usky.common.mybatis.core.CrudService;
+import com.usky.system.domain.MceRequestVO;
 
 /**
  * <p>
@@ -13,6 +14,8 @@ import com.usky.common.mybatis.core.CrudService;
  * @since 2024-05-09
  */
 public interface MceContentService extends CrudService<MceContent> {
+
     void sendApp(JSONObject mceReceiveVO, String cids, Integer mceReceiveId, Integer sendType);
 
+    void sendAppNew(MceRequestVO mceRequestVO, String cids, Integer mceReceiveId, Integer sendType);
 }

+ 14 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/MceReceiveService.java

@@ -3,6 +3,8 @@ package com.usky.system.service;
 import com.usky.common.core.bean.CommonPage;
 import com.usky.system.domain.MceReceive;
 import com.usky.common.mybatis.core.CrudService;
+import com.usky.system.domain.MceRequestVO;
+import com.usky.system.service.vo.MceReceiveResponseVO;
 
 import java.util.Map;
 
@@ -16,7 +18,7 @@ import java.util.Map;
  */
 public interface MceReceiveService extends CrudService<MceReceive> {
 
-    CommonPage<Object> mceList(String infoTitle, String infoType, String startTime, String endTime, Integer id, Integer current, Integer size);
+    CommonPage<Object> mceList(String infoTitle, String infoType, String startTime, String endTime, Integer id, Integer infoId, Integer current, Integer size);
 
     CommonPage<Object> mceManageList(String infoTitle, String infoType, String startTime, String endTime, Integer current, Integer size);
 
@@ -26,8 +28,19 @@ public interface MceReceiveService extends CrudService<MceReceive> {
 
     void updateMceReceive(MceReceive mceReceive);
 
+    void addMceReceive(MceRequestVO mceRequestVO);
+
     void add(String mceReceive);
 
     boolean removeById(Integer id);
 
+    boolean deleteById(Integer id);
+
+    CommonPage<MceReceiveResponseVO> getMceReceiveResponseVOList(Integer pageNumber, Integer pageSize);
+
+    /**
+     * 添加消息不带token
+     * @param mceReceive
+     */
+    void addNoToken(String mceReceive);
 }

+ 43 - 24
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysLoginService.java

@@ -18,7 +18,10 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
 
+import javax.servlet.http.HttpServletRequest;
 import java.util.List;
 import java.util.Objects;
 import java.util.Random;
@@ -62,19 +65,22 @@ public class SysLoginService {
 
         // 用户名或密码为空 错误
         if (StringUtils.isAnyBlank(username, password)) {
-            asyncManager.insertLog(tenantId,username,Constants.LOGIN_FAIL, "用户/密码必须填写", null);
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            asyncManager.insertLog(request, tenantId,username,Constants.LOGIN_FAIL, "用户/密码必须填写", null);
             throw new BusinessException("用户/密码必须填写");
         }
         // 密码如果不在指定范围内 错误
         if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                 || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
-            asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "用户密码不在指定范围", null);
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            asyncManager.insertLog(request, tenantId,username, Constants.LOGIN_FAIL, "用户密码不在指定范围", null);
             throw new BusinessException("用户密码不在指定范围");
         }
         // 用户名不在指定范围内 错误
         if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                 || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
-            asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "用户名不在指定范围", null);
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            asyncManager.insertLog(request, tenantId,username, Constants.LOGIN_FAIL, "用户名不在指定范围", null);
             throw new BusinessException("用户名不在指定范围");
         }
 
@@ -88,15 +94,18 @@ public class SysLoginService {
 
         SysUserVO user = loginUser.getSysUser();
         if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
-            asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除", null);
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            asyncManager.insertLog(request, tenantId,username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除", null);
             throw new BusinessException("对不起,您的账号:" + username + " 已被删除");
         }
         if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
-            asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员", null);
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            asyncManager.insertLog(request, tenantId,username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员", null);
             throw new BusinessException("对不起,您的账号:" + username + " 已停用");
         }
         if (!SecurityUtils.matchesPassword(password, user.getPassword())) {
-            asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "用户密码错误", null);
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            asyncManager.insertLog(request, tenantId,username, Constants.LOGIN_FAIL, "用户密码错误", null);
             throw new BusinessException("用户不存在/密码错误");
         }
 
@@ -109,7 +118,8 @@ public class SysLoginService {
             String status = list.get(0).getStatus();
             String domain = list.get(0).getDomain();
             if(status.equals("1")){
-                asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "系统已停用,请联系管理员", null);
+                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+                asyncManager.insertLog(request, tenantId,username, Constants.LOGIN_FAIL, "系统已停用,请联系管理员", null);
                 throw new BusinessException("对不起,系统已停用,请联系管理员");
             }
         }
@@ -128,44 +138,48 @@ public class SysLoginService {
 
         SysPerson sysPerson = sysPersonService.getsysPerson(user.getUserId());
         loginUser.setSysPerson(sysPerson);
-        asyncManager.insertLog(tenantId,username, Constants.LOGIN_SUCCESS, "登录成功", deptId);
+        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+        asyncManager.insertLog(request, tenantId,username, Constants.LOGIN_SUCCESS, "登录成功", deptId);
         return loginUser;
     }
 
 
-    public SysUser appLogin(String username, String password, Integer tenantId, String phone, String verify) {
+    public SysUser appLogin(String username, String password, Integer tenantId, String phone, String verify, String method) {
         SysUser loginUser = new SysUser();
         //查询用户信息
-        loginUser = sysUserService.getAppUserInfo(username, tenantId, null);
         if (!StringUtils.isBlank(username) && !StringUtils.isBlank(password)) {
             // 用户名或密码为空 错误
             if (StringUtils.isAnyBlank(username, password)) {
-                asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户/密码必须填写", null);
+                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+                asyncManager.insertLog(request, tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户/密码必须填写", null);
                 throw new BusinessException("用户/密码必须填写");
             }
 
             // 密码如果不在指定范围内 错误
             if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                     || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
-                asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户密码不在指定范围", null);
+                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+                asyncManager.insertLog(request, tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户密码不在指定范围", null);
                 throw new BusinessException("用户密码不在指定范围");
             }
 
             // 用户名不在指定范围内 错误
             if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                     || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
-                asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户名不在指定范围", null);
+                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+                asyncManager.insertLog(request, tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户名不在指定范围", null);
                 throw new BusinessException("用户名不在指定范围");
             }
-
-
+            loginUser = sysUserService.getAppUserInfo(username, tenantId, null, method);
             if (Objects.isNull(loginUser)) {
-                asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户不存在", null);
+                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+                asyncManager.insertLog(request, tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户不存在", null);
                 throw new BusinessException("用户不存在");
             }
 
             if (!SecurityUtils.matchesPassword(password, loginUser.getPassword())) {
-                asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户密码错误", null);
+                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+                asyncManager.insertLog(request, tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户密码错误", null);
                 throw new BusinessException("用户不存在/密码错误");
             }
         } else if(!StringUtils.isBlank(phone) && !StringUtils.isBlank(verify)) {
@@ -179,7 +193,7 @@ public class SysLoginService {
             if (StringUtils.isBlank(phone)) {
                 throw new BusinessException("用户名或手机号不能为空");
             }
-            loginUser = sysUserService.getAppUserInfo(null, tenantId, phone);
+            loginUser = sysUserService.getAppUserInfo(null, tenantId, phone, method);
             // 获取部门ID
             LambdaQueryWrapper<SysUser> deptQueryWrapper = Wrappers.lambdaQuery();
             deptQueryWrapper.select(SysUser::getDeptId)
@@ -200,7 +214,7 @@ public class SysLoginService {
             if (!verify.equals(redisHelper.get(qrCode_verify))) {
                 throw new BusinessException("扫码验证码失败");
             }
-            loginUser = sysUserService.getAppUserInfo(username, tenantId, null);
+            loginUser = sysUserService.getAppUserInfo(username, tenantId, null, method);
         }
         // 获取部门ID
         LambdaQueryWrapper<SysUser> deptQueryWrapper = Wrappers.lambdaQuery();
@@ -214,11 +228,13 @@ public class SysLoginService {
             deptId = sysUser.getDeptId().intValue(); // 将Long转换为Integer
         }
         if (UserStatus.DELETED.getCode().equals(loginUser.getDelFlag())) {
-            asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "对不起,您的账号已被删除", null);
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            asyncManager.insertLog(request, tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "对不起,您的账号已被删除", null);
             throw new BusinessException("对不起,您的账号:" + username + " 已被删除");
         }
         if (UserStatus.DISABLE.getCode().equals(loginUser.getStatus())) {
-            asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户已停用,请联系管理员", null);
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            asyncManager.insertLog(request, tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户已停用,请联系管理员", null);
             throw new BusinessException("对不起,您的账号:" + loginUser.getUserName() + " 已停用");
         }
 
@@ -227,13 +243,15 @@ public class SysLoginService {
         if (loginUser != null && loginUser.getDeptId() != null) {
             deptId = loginUser.getDeptId().intValue();
         }
-        asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_SUCCESS, "登录成功", deptId);
+        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+        asyncManager.insertLog(request, tenantId,loginUser.getUserName(), Constants.LOGIN_SUCCESS, "登录成功", deptId);
         return loginUser;
     }
 
 
     public void logout(Integer tenantId,String loginName) {
-        asyncManager.insertLog(tenantId,loginName, Constants.LOGOUT, "退出成功", null);
+        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+        asyncManager.insertLog(request, tenantId,loginName, Constants.LOGOUT, "退出成功", null);
     }
 
     /**
@@ -259,7 +277,8 @@ public class SysLoginService {
         sysUser.setNickName(username);
         sysUser.setPassword(SecurityUtils.encryptPassword(password));
         sysUserService.register(BeanMapperUtils.map(sysUser, SysUser.class));
-        asyncManager.insertLog(SecurityUtils.getTenantId(),username, Constants.REGISTER, "注册成功", null);
+        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+        asyncManager.insertLog(request, SecurityUtils.getTenantId(),username, Constants.REGISTER, "注册成功", null);
     }
 
 

+ 13 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysPersonService.java

@@ -3,6 +3,9 @@ package com.usky.system.service;
 import com.usky.system.domain.SysPerson;
 import com.usky.common.mybatis.core.CrudService;
 
+import java.util.List;
+import java.util.Map;
+
 /**
  * <p>
  * 人员信息 服务类
@@ -18,4 +21,14 @@ public interface SysPersonService extends CrudService<SysPerson> {
      * @return
      */
     SysPerson getsysPerson(Long userid);
+
+    /**
+     * 根据 userId 从 sys_user / 部门 / 岗位 填充人员的 dept、post 展示字段;userId 为空或查无用户时置为 null。
+     */
+    void fillDeptAndPostFromUser(SysPerson person, Long userId);
+
+    /**
+     * 批量填充列表中人员的部门、岗位(personId -> userId 由调用方传入)。
+     */
+    void fillDeptAndPostForList(List<SysPerson> list, Map<Integer, Long> personIdToUserId);
 }

+ 1 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysUserPersonService.java

@@ -13,4 +13,5 @@ import com.usky.common.mybatis.core.CrudService;
  */
 public interface SysUserPersonService extends CrudService<SysUserPerson> {
 
+    public Integer upIsLoginNotify(Long userId, Integer isLoginNotify);
 }

+ 12 - 4
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysUserTenantService.java

@@ -3,6 +3,7 @@ package com.usky.system.service;
 import com.usky.system.domain.SysTenant;
 import com.usky.system.domain.SysUserTenant;
 import com.usky.common.mybatis.core.CrudService;
+import com.usky.system.service.vo.TenantPlatformVo;
 
 import java.util.List;
 
@@ -20,7 +21,7 @@ public interface SysUserTenantService extends CrudService<SysUserTenant> {
      *
      * @param sysUserTenant
      */
-    public void insertInviteUser(SysUserTenant sysUserTenant);
+    void insertInviteUser(SysUserTenant sysUserTenant);
 
     /**
      * 企业解绑用户
@@ -28,15 +29,22 @@ public interface SysUserTenantService extends CrudService<SysUserTenant> {
      * @param tenantId 租户ID
      * @param userId 用户ID
      */
-    public void deleteUserTenant(Integer tenantId,Long userId);
+    void deleteUserTenant(Integer tenantId,Long userId);
 
     /**
      * 根据用户查询企业下拉框
      */
-    public List<SysTenant> getTenantByUser(Long userId);
+    List<SysTenant> getTenantByUser(Long userId);
 
     /**
      * 根据用户查询绑定状态
      */
-    public Boolean getIdByUser(Integer tenantId,Long userId);
+    Boolean getIdByUser(Integer tenantId,Long userId);
+
+    /**
+     * 根据用户查询默认租户ID
+     */
+    Integer getIsDefaultByUser(Long userId);
+
+    void updateUserTenant(SysUserTenant userTenant);
 }

+ 17 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/config/Gzip/GzipConfig.java

@@ -0,0 +1,17 @@
+package com.usky.system.service.config.Gzip;
+
+import com.planetj.servlet.filter.compression.CompressingFilter;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class GzipConfig {
+    @Bean
+    public FilterRegistrationBean<CompressingFilter> gzipFilter() {
+        FilterRegistrationBean<CompressingFilter> bean = new FilterRegistrationBean<>();
+        bean.setFilter(new CompressingFilter());
+        bean.addUrlPatterns("/*");
+        return bean;
+    }
+}

+ 81 - 9
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/MceContentServiceImpl.java

@@ -10,9 +10,12 @@ import com.usky.system.service.MceMbuserService;
 import com.usky.system.service.config.websocket.HttpClientUtils;
 import com.usky.system.service.vo.SendWeChatMessageRequestVO;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
+import com.usky.system.domain.MceRequestVO;
 
 /**
  * <p>
@@ -29,21 +32,24 @@ public class MceContentServiceImpl extends AbstractCrudService<MceContentMapper,
     @Autowired
     private MceMbuserService mceMbuserService;
 
-    //异步多线程调用
-    @Async("asyncServiceExecutor")
-    public void sendApp(JSONObject mceReceiveVO, String cids, Integer mceReceiveId, Integer sendType){
-        if (sendType.equals(0)){
-            String appUrl = "https://fc-mp-85a26092-1305-4bf1-998f-b609512c8f7b.next.bspapp.com/uniPushMessage";
+    @Value("${appUrl}")
+    private String appUrl;
+
+    // 异步多线程调用
+    @Override
+    @Async
+    public void sendApp(JSONObject mceReceiveVO, String cids, Integer mceReceiveId, Integer sendType) {
+        if (sendType.equals(0)) {
             JsonObject jsonObject = new JsonObject();
             JsonObject jsonObject1 = new JsonObject();
             jsonObject1.addProperty("infoType", mceReceiveVO.get("infoType").toString());
-            jsonObject1.addProperty("moduleId", (int)mceReceiveVO.get("id"));
+            jsonObject1.addProperty("moduleId", (int) mceReceiveVO.get("id"));
             jsonObject.addProperty("cids", cids);
             jsonObject.addProperty("title", mceReceiveVO.get("infoTitle").toString());
             jsonObject.addProperty("content", mceReceiveVO.get("infoContent").toString());
-            jsonObject.add("payload",jsonObject1);
-            String resultString = HttpClientUtils.doPostJson(appUrl,jsonObject.toString());
-        }else if (sendType.equals(1)){
+            jsonObject.add("payload", jsonObject1);
+            String resultString = HttpClientUtils.doPostJson(appUrl, jsonObject.toString());
+        } else if (sendType.equals(1)) {
             SendWeChatMessageRequestVO sendWeChatMessageRequestVO = new SendWeChatMessageRequestVO();
             sendWeChatMessageRequestVO.setInfoContent(mceReceiveVO.get("infoContent").toString());
             sendWeChatMessageRequestVO.setInfoTitle(mceReceiveVO.get("infoTitle").toString());
@@ -56,4 +62,70 @@ public class MceContentServiceImpl extends AbstractCrudService<MceContentMapper,
             mceMbuserService.sendWeChatMessage(sendWeChatMessageRequestVO);
         }
     }
+
+    @Override
+    @Async
+    public void sendAppNew(MceRequestVO mceReceiveVO, String cids, Integer mceReceiveId, Integer sendType) {
+        if (sendType.equals(0)) {
+            JsonObject jsonObject = new JsonObject();
+            JsonObject jsonObject1 = new JsonObject();
+            jsonObject1.addProperty("infoType", mceReceiveVO.getInfoType());
+            jsonObject1.addProperty("moduleId", mceReceiveVO.getId());
+            jsonObject.addProperty("cids", cids);
+            jsonObject.addProperty("title", mceReceiveVO.getInfoTitle());
+            if ("3".equals(mceReceiveVO.getInfoType())) {
+                jsonObject.addProperty("content", mceReceiveVO.getInfoContent().split("-")[0]);
+            }
+            jsonObject.addProperty("content", mceReceiveVO.getInfoContent());
+            jsonObject.add("payload", jsonObject1);
+            String resultString = HttpClientUtils.doPostJson(appUrl, jsonObject.toString());
+        } else if (sendType.equals(1)) {
+            SendWeChatMessageRequestVO sendWeChatMessageRequestVO = new SendWeChatMessageRequestVO();
+            sendWeChatMessageRequestVO.setInfoContent(mceReceiveVO.getInfoContent());
+            sendWeChatMessageRequestVO.setInfoTitle(mceReceiveVO.getInfoTitle());
+            sendWeChatMessageRequestVO.setInfoId(mceReceiveId);
+            sendWeChatMessageRequestVO.setOpenId(cids);
+            sendWeChatMessageRequestVO.setInfoType(mceReceiveVO.getInfoType());
+            if (StringUtils.isNotEmpty(mceReceiveVO.getInfoTypeName())) {
+                sendWeChatMessageRequestVO.setInfoTypeName(mceReceiveVO.getInfoTypeName());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getIpAddress())) {
+                sendWeChatMessageRequestVO.setIpAddress(mceReceiveVO.getIpAddress());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getUserName())) {
+                sendWeChatMessageRequestVO.setUserName(mceReceiveVO.getUserName());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getLoginAddress())) {
+                sendWeChatMessageRequestVO.setLoginAddress(mceReceiveVO.getLoginAddress());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getLoginType())) {
+                sendWeChatMessageRequestVO.setLoginType(mceReceiveVO.getLoginType());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getApprovalResult())) {
+                sendWeChatMessageRequestVO.setApprovalResult(mceReceiveVO.getApprovalResult());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getProcessName())) {
+                sendWeChatMessageRequestVO.setProcessName(mceReceiveVO.getProcessName());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getApprovalNode())) {
+                sendWeChatMessageRequestVO.setApprovalNode(mceReceiveVO.getApprovalNode());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getRealName())) {
+                sendWeChatMessageRequestVO.setRealName(mceReceiveVO.getRealName());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getOaType())) {
+                sendWeChatMessageRequestVO.setOaType(mceReceiveVO.getOaType());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getDeviceId())) {
+                sendWeChatMessageRequestVO.setDeviceId(mceReceiveVO.getDeviceId());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getAlarmTime())) {
+                sendWeChatMessageRequestVO.setAlarmTime(mceReceiveVO.getAlarmTime());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getRemark())) {
+                sendWeChatMessageRequestVO.setRemark(mceReceiveVO.getRemark());
+            }
+            mceMbuserService.sendWeChatMessage(sendWeChatMessageRequestVO);
+        }
+    }
 }

+ 144 - 49
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/MceMbuserServiceImpl.java

@@ -7,14 +7,12 @@ import com.usky.common.core.exception.BusinessException;
 import com.usky.common.redis.core.RedisHelper;
 import com.usky.system.domain.MceMbuser;
 import com.usky.system.mapper.MceMbuserMapper;
-import com.usky.system.service.ISysDictDataService;
 import com.usky.system.service.MceMbuserService;
 import com.usky.system.constant.constant;
 import com.usky.common.mybatis.core.AbstractCrudService;
-import com.usky.system.service.vo.SendWeChatMessageRequestVO;
-import com.usky.system.service.vo.TemplateData;
-import com.usky.system.service.vo.TemplateMsgEntityVO;
+import com.usky.system.service.vo.*;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
@@ -61,13 +59,13 @@ public class MceMbuserServiceImpl extends AbstractCrudService<MceMbuserMapper, M
         return null;
     }
 
-    public static long getTimeDifference(String oldTime,String newTime) throws ParseException {
+    public static long getTimeDifference(String oldTime, String newTime) throws ParseException {
 
         SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        long NTime =df.parse(newTime).getTime();
-        //从对象中拿到时间
+        long NTime = df.parse(newTime).getTime();
+        // 从对象中拿到时间
         long OTime = df.parse(oldTime).getTime();
-        long diff=(NTime-OTime)/1000/60;
+        long diff = (NTime - OTime) / 1000 / 60;
         return diff;
     }
 
@@ -78,61 +76,158 @@ public class MceMbuserServiceImpl extends AbstractCrudService<MceMbuserMapper, M
         String infoContent = requestVO.getInfoContent();
         Integer infoId = requestVO.getInfoId();
         String openId = requestVO.getOpenId();
-
-        //access_token时效校验,判断获取access_token获取时间是否超过有效时间,超过就调用更新,保证一直有效
-        if(!redisHelper.hasKey("access_key")){
+        String infoType = requestVO.getInfoType();
+        String infoTypeName = requestVO.getInfoTypeName();
+        String oaType = requestVO.getOaType();
+        // access_token时效校验,判断获取access_token获取时间是否超过有效时间,超过就调用更新,保证一直有效
+        if (!redisHelper.hasKey("access_key")) {
             redisHelper.set("access_time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
-            redisHelper.set("access_key",this.getWeChatAccessToken());
-        }else{
-            try{
-                String access_time = redisHelper.get("access_time").toString();
-                String now_time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
-                long i = getTimeDifference(access_time,now_time);
-                if(i > 115){ //大于115分钟
-                    redisHelper.set("access_time",LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
-                    redisHelper.set("access_key",this.getWeChatAccessToken());
+            redisHelper.set("access_key", this.getWeChatAccessToken());
+        } else {
+            try {
+                String accessTime = redisHelper.get("access_time").toString();
+                String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+                long i = getTimeDifference(accessTime, nowTime);
+                // 大于115分钟
+                if (i > 115) {
+                    redisHelper.set("access_time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+                    redisHelper.set("access_key", this.getWeChatAccessToken());
                 }
-            }catch (Exception e){
+            } catch (Exception e) {
                 throw new BusinessException(e.getMessage());
             }
 
         }
 
         Object obj = redisHelper.get("access_key");
-        if(obj == null){
-            throw new BusinessException("token不能为空");
+        if (obj == null) {
+            log.error("消息接收id:" + requestVO.getInfoId() + ",token为空,发送微信服务号消息失败");
+            return null;
         }
 
-        String token = obj.toString();
+        String tUrl;
+        String templateId = "";
 
-        TemplateMsgEntityVO messageVo=new TemplateMsgEntityVO();
-        messageVo.setTTitle(infoTitle);
-        messageVo.setTKeyword1(infoContent);
-        messageVo.setTKeyword3(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
-        messageVo.setTRemark(infoContent);
-        if(Objects.nonNull(requestVO.getInfoTypeName())){
-            messageVo.setTUrl(String.format(constant.WE_CHAT_CUSTOMER_CALL_URL,requestVO.getInfoType(),requestVO.getInfoTypeName(),infoId));
-            messageVo.setTKeyword2(requestVO.getInfoTypeName());
-        }else{
-            messageVo.setTUrl(String.format(constant.WE_CHAT_CUSTOMER_CALL_URL1,requestVO.getInfoType(),infoId));
-            messageVo.setTKeyword2("");
+        Map<String, TemplateData> data = new HashMap<>();
+        String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+
+        switch (requestVO.getInfoType()) {
+            // 登录成功通知
+            case "0":
+                // 登录时间
+                data.put("time3", new TemplateData(nowTime, "#173177"));
+                // 登录账号 userName
+                data.put("thing6", new TemplateData(requestVO.getUserName(), "#173177"));
+                // 登录IP
+                data.put("character_string8", new TemplateData(requestVO.getIpAddress(), "#173177"));
+                // 登录地点
+                data.put("thing9", new TemplateData(requestVO.getLoginAddress(), "#173177"));
+                // 登录方式
+                data.put("thing10", new TemplateData(requestVO.getLoginType(), "#173177"));
+                // 设置公众号模板消息ID
+                templateId = constant.WE_CHAT_LOGIN_TEMPLATE_ID;
+                break;
+
+            /* 通知公告&工作报告通知(工单已完成通知)
+             * 工单标题{{thing9.DATA}}
+             * 发起人{{thing8.DATA}}
+             * 完成时间{{time12.DATA}}
+             **/
+            case "1":
+                data.put("thing9", new TemplateData("通知公告-" + requestVO.getInfoContent(), "#173177"));
+                data.put("thing8", new TemplateData(requestVO.getRealName(), "#173177"));
+                data.put("time12", new TemplateData(nowTime, "#173177"));
+                templateId = constant.WE_CHAT_WORK_TEMPLATE_ID;
+                break;
+            case "5":
+                data.put("thing9", new TemplateData("报告提醒-" + requestVO.getInfoContent(), "#173177"));
+                data.put("thing8", new TemplateData(requestVO.getRealName(), "#173177"));
+                data.put("time12", new TemplateData(nowTime, "#173177"));
+                // 设置公众号模板消息ID
+                templateId = constant.WE_CHAT_WORK_TEMPLATE_ID;
+                break;
+
+            case "3":
+                /* OA系统流程审批通知
+                 * 流程名称{{thing7.DATA}}
+                 * 审批节点{{thing8.DATA}}
+                 * 发起人{{thing13.DATA}}
+                 * 发起时间{{time10.DATA}}
+                 * 审批结果{{const21.DATA}}
+                 **/
+                data.put("thing7", new TemplateData(requestVO.getProcessName(), "#173177"));
+                data.put("thing8", new TemplateData(requestVO.getApprovalNode(), "#173177"));
+                data.put("thing13", new TemplateData(requestVO.getRealName(), "#173177"));
+                data.put("time10", new TemplateData(nowTime, "#173177"));
+                data.put("const21", new TemplateData(requestVO.getApprovalResult(), "#173177"));
+
+                // 设置公众号模板消息ID
+                templateId = constant.WE_CHAT_OA_TEMPLATE_ID;
+                break;
+
+            case "2":
+                TemplateMsgEntityVO messageVo = new TemplateMsgEntityVO();
+                messageVo.setTTitle(infoTitle);
+                messageVo.setTKeyword1(infoContent);
+                messageVo.setTKeyword2(infoType);
+                messageVo.setTKeyword3(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+                messageVo.setTRemark(infoContent);
+                /* 设备预警信息提醒
+                 * {{first.DATA}}
+                 * 设备号:{{keyword1.DATA}}
+                 * 报警类型:{{keyword2.DATA}}
+                 * 时间:{{keyword3.DATA}}
+                 * 备注:{{remark.DATA}}
+                 **/
+                messageVo.setTemplateId(constant.WE_CHAT_TEMPLATE_ID);
+                data.put("first", new TemplateData(messageVo.getTTitle(), "#44b549"));
+                data.put("keyword1", new TemplateData(messageVo.getTKeyword1(), "#173177"));
+                data.put("keyword2", new TemplateData(messageVo.getTKeyword2(), "#173177"));
+                data.put("keyword3", new TemplateData(messageVo.getTKeyword3(), "#173177"));
+                data.put("remark", new TemplateData(messageVo.getTRemark(), "#173177"));
+
+                templateId = messageVo.getTemplateId();
+                break;
+            case "4":
+                /* 设备预警信息提醒
+                 * {{first.DATA}}
+                 * 设备号:{{keyword1.DATA}}
+                 * 报警类型:{{keyword2.DATA}}
+                 * 时间:{{keyword3.DATA}}
+                 * 备注:{{remark.DATA}}
+                 **/
+                data.put("first", new TemplateData(requestVO.getInfoTitle(), "#44b549"));
+                data.put("keyword1", new TemplateData(requestVO.getDeviceId(), "#173177"));
+                data.put("keyword2", new TemplateData(requestVO.getInfoContent(), "#173177"));
+                data.put("keyword3", new TemplateData(requestVO.getAlarmTime(), "#173177"));
+                data.put("remark", new TemplateData(requestVO.getRemark(), "#173177"));
+
+                // 设置公众号模板消息ID
+                templateId = constant.WE_CHAT_TEMPLATE_ID;
+                break;
         }
 
-        messageVo.setTemplateId(constant.WE_CHAT_TEMPLATE_ID);
+        log.info("oaType:{}", oaType);
+        // 回调地址
+        if ("3".equals(requestVO.getInfoType())) {
+            tUrl = String.format(constant.WE_CHAT_CUSTOMER_CALL_URL3, infoType, infoTypeName, infoId, oaType);
+        } else if (Objects.nonNull(infoTypeName)) {
+            tUrl = String.format(constant.WE_CHAT_CUSTOMER_CALL_URL, infoType, infoTypeName, infoId);
+        } else {
+            tUrl = String.format(constant.WE_CHAT_CUSTOMER_CALL_URL1, infoType, infoId);
+        }
 
-        String requestUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="  + token;
-        Map<String,Object> content=new HashMap<>();
-        Map<String, TemplateData> data = new HashMap<>();
-        data.put("first",new TemplateData(messageVo.getTTitle(),"#44b549"));
-        data.put("keyword1",new TemplateData(messageVo.getTKeyword1(),"#173177"));
-        data.put("keyword2",new TemplateData(messageVo.getTKeyword2(),"#173177"));
-        data.put("keyword3",new TemplateData(messageVo.getTKeyword3(),"#173177"));
-        data.put("remark",new TemplateData(messageVo.getTRemark(),"#173177"));
-
-        content.put("touser",openId);
-        content.put("url",messageVo.getTUrl());
-        content.put("template_id",messageVo.getTemplateId());
-        content.put("data",data);
+        String token = obj.toString();
+        String requestUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + token;
+        Map<String, Object> content = new HashMap<>();
+        content.put("touser", openId);
+        if (!"0".equals(requestVO.getInfoType())) {
+            content.put("url", tUrl);
+        }
+        if (StringUtils.isNotBlank(templateId)) {
+            content.put("template_id", templateId);
+        }
+        content.put("data", data);
         String resp = HttpUtil.post(requestUrl, JSONUtil.parseObj(content).toString());
         System.out.println(content.toString());
         System.out.println(JSONUtil.parseObj(content));

+ 579 - 77
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/MceReceiveServiceImpl.java

@@ -10,22 +10,24 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.datascope.annotation.DataScope;
-import com.ruoyi.common.datascope.context.DataScopeContextHolder;
-import com.usky.common.core.bean.ApiResult;
 import com.usky.common.core.bean.CommonPage;
+import com.usky.common.core.exception.BusinessException;
 import com.usky.common.security.utils.SecurityUtils;
-import com.usky.system.RemoteUserService;
 import com.usky.system.domain.*;
 import com.usky.system.mapper.MceReceiveMapper;
+import com.usky.system.mapper.MceSettingMapper;
 import com.usky.system.mapper.SysUserMapper;
 import com.usky.system.service.*;
 import com.usky.common.mybatis.core.AbstractCrudService;
+import com.usky.system.service.vo.MceReceiveResponseVO;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
 import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -35,6 +37,7 @@ import java.util.*;
  * @author han
  * @since 2024-05-09
  */
+@Slf4j
 @Service
 public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper, MceReceive> implements MceReceiveService {
     @Autowired
@@ -54,47 +57,73 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
 
     @Autowired
     private SysUserMapper userMapper;
+    @Autowired
+    private MceSettingMapper mceSettingMapper;
+
+    @Autowired
+    private MceReceiveMapper mceReceiveMapper;
+
+    @Autowired
+    private SysUserPersonService sysUserPersonService;
 
     @Override
-    public CommonPage<Object> mceList(String infoTitle, String infoType, String startTime, String endTime, Integer id, Integer current, Integer size) {
+    public CommonPage<Object> mceList(String infoTitle, String infoType, String startTime, String endTime, Integer id, Integer infoId, Integer current, Integer size) {
         List<Object> list = new ArrayList<>();
+
+        if (infoId != null) {
+            LambdaQueryWrapper<MceReceive> query = Wrappers.lambdaQuery();
+            query.select(MceReceive::getContentId).eq(MceReceive::getId, infoId);
+            MceReceive mceReceive = mceReceiveMapper.selectOne(query);
+            if (mceReceive != null) {
+                id = mceReceive.getContentId();
+            } else {
+                log.error("消息内容已不存在!消息id:{}", infoId);
+                throw new BusinessException("消息内容已不存在!");
+            }
+        }
+
         LambdaQueryWrapper<MceContent> lambdaQuery1 = Wrappers.lambdaQuery();
         lambdaQuery1.select(MceContent::getId, MceContent::getInfoTitle, MceContent::getInfoContent)
-                .like(StringUtils.isNotBlank(infoTitle),MceContent::getInfoTitle,infoTitle)
-                .eq(id != null,MceContent::getId,id);
+                .like(StringUtils.isNotBlank(infoTitle), MceContent::getInfoTitle, infoTitle)
+                .eq(id != null, MceContent::getId, id)
+                .eq(MceContent::getTenantId, SecurityUtils.getTenantId());
         List<MceContent> list1 = mceContentService.list(lambdaQuery1);
         IPage<MceReceive> page = new Page<>(current, size);
         List<Integer> contentIds = new ArrayList<>();
-        if (CollectionUtils.isNotEmpty(list1)){
-            for(int i=0;i<list1.size();i++){
+        if (CollectionUtils.isNotEmpty(list1)) {
+            for (int i = 0; i < list1.size(); i++) {
                 contentIds.add(list1.get(i).getId());
             }
             Long userId = SecurityUtils.getUserId();
             LambdaQueryWrapper<MceReceive> lambdaQuery = Wrappers.lambdaQuery();
             lambdaQuery.select(MceReceive::getId, MceReceive::getInfoType,
-                    MceReceive::getContentId, MceReceive::getReadFlag, MceReceive::getCreateTime,
-                    MceReceive::getReceiverId,MceReceive::getModuleId)
-                    .between(StringUtils.isNotBlank(startTime)&&StringUtils.isNotBlank(endTime),MceReceive::getCreateTime,
-                            startTime,endTime)
-                    .eq(StringUtils.isNotBlank(infoType),MceReceive::getInfoType, infoType)
+                            MceReceive::getContentId, MceReceive::getReadFlag, MceReceive::getCreateTime,
+                            MceReceive::getReceiverId, MceReceive::getModuleId, MceReceive::getCreateBy, MceReceive::getIssuerName)
+                    .between(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime), MceReceive::getCreateTime,
+                            startTime, endTime)
+                    .eq(StringUtils.isNotBlank(infoType), MceReceive::getInfoType, infoType)
                     .eq(MceReceive::getReceiverId, SecurityUtils.getUserId())
-                    .in(CollectionUtils.isNotEmpty(contentIds),MceReceive::getContentId,contentIds)
+                    .in(CollectionUtils.isNotEmpty(contentIds), MceReceive::getContentId, contentIds)
                     .orderByDesc(MceReceive::getId);
+
 //                .inSql(StringUtils.isNotBlank(infoTitle),MceReceive::getContentId,"SELECT id FROM mce_content WHERE " +
 //                        "info_title like '%" + infoTitle + "%' AND tenant_id = "+SecurityUtils.getTenantId()+"");
-            page = this.page(page,lambdaQuery);
+            page = this.page(page, lambdaQuery);
             if (CollectionUtils.isNotEmpty(page.getRecords())) {
                 for (int i = 0; i < page.getRecords().size(); i++) {
+                    String infoType1 = page.getRecords().get(i).getInfoType();
                     Map<String, Object> map = new HashMap<>();
                     map.put("id", page.getRecords().get(i).getId());
-                    map.put("infoType", page.getRecords().get(i).getInfoType());
+                    map.put("infoType", infoType1);
                     map.put("readFlag", page.getRecords().get(i).getReadFlag());
                     map.put("moduleId", page.getRecords().get(i).getModuleId());
                     map.put("createTime", page.getRecords().get(i).getCreateTime());
+                    map.put("createBy", page.getRecords().get(i).getCreateBy());
+                    map.put("issuerName", page.getRecords().get(i).getIssuerName());
                     if (CollectionUtils.isNotEmpty(list1)) {
                         for (int j = 0; j < list1.size(); j++) {
                             if (page.getRecords().get(i).getContentId().equals(list1.get(j).getId())) {
-                                map.put("contentId",list1.get(j).getId());
+                                map.put("contentId", list1.get(j).getId());
                                 map.put("infoTitle", list1.get(j).getInfoTitle());
                                 map.put("infoContent", list1.get(j).getInfoContent());
                             }
@@ -104,7 +133,7 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
                 }
             }
         }
-        return new CommonPage<>(list,page.getTotal(),page.getCurrent(),page.getSize());
+        return new CommonPage<>(list, page.getTotal(), page.getCurrent(), page.getSize());
     }
 
     @Override
@@ -112,16 +141,16 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
     public CommonPage<Object> mceManageList(String infoTitle, String infoType, String startTime, String endTime, Integer current, Integer size) {
         List<Object> list = new ArrayList<>();
         IPage<MceContent> page = new Page<>(current, size);
-        //查询消息内容
+        // 查询消息内容
         LambdaQueryWrapper<MceContent> lambdaQuery1 = Wrappers.lambdaQuery();
-        lambdaQuery1.select(MceContent::getId, MceContent::getInfoTitle, MceContent::getInfoContent, MceContent::getCreateTime,MceContent::getInfoType)
-                .like(StringUtils.isNotBlank(infoTitle),MceContent::getInfoTitle,infoTitle)
-                .between(StringUtils.isNotBlank(startTime)&&StringUtils.isNotBlank(endTime),MceContent::getCreateTime, startTime,endTime)
-                .eq(StringUtils.isNotBlank(infoType),MceContent::getInfoType, infoType)
+        lambdaQuery1.select(MceContent::getId, MceContent::getInfoTitle, MceContent::getInfoContent, MceContent::getCreateTime, MceContent::getInfoType)
+                .like(StringUtils.isNotBlank(infoTitle), MceContent::getInfoTitle, infoTitle)
+                .between(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime), MceContent::getCreateTime, startTime, endTime)
+                .eq(StringUtils.isNotBlank(infoType), MceContent::getInfoType, infoType)
 //                .apply(DataScopeContextHolder.getDataScopeSql())
-                .eq(MceContent::getTenantId,SecurityUtils.getTenantId())
+                .eq(MceContent::getTenantId, SecurityUtils.getTenantId())
                 .orderByDesc(MceContent::getId);
-        page = mceContentService.page(page,lambdaQuery1);
+        page = mceContentService.page(page, lambdaQuery1);
 
         if (CollectionUtils.isNotEmpty(page.getRecords())) {
             List<Integer> contentIds = new ArrayList<>();
@@ -129,11 +158,11 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
                 contentIds.add(page.getRecords().get(i).getId());
             }
             QueryWrapper<MceReceive> queryWrapper = Wrappers.query();
-            queryWrapper.select("content_id AS contentId","COUNT(read_flag=0 or null) as notReadCount","COUNT" +
-                    "(read_flag=1 or null) as readCount","issuer_name AS issuerName")
-                    .in("content_id",contentIds)
-                    .groupBy("content_id","issuer_name");
-            List<Map<String,Object>> readStatisticList = this.listMaps(queryWrapper);
+            queryWrapper.select("content_id AS contentId", "COUNT(read_flag=0 or null) as notReadCount", "COUNT" +
+                            "(read_flag=1 or null) as readCount", "issuer_name AS issuerName")
+                    .in("content_id", contentIds)
+                    .groupBy("content_id", "issuer_name");
+            List<Map<String, Object>> readStatisticList = this.listMaps(queryWrapper);
             for (int i = 0; i < page.getRecords().size(); i++) {
                 Map<String, Object> map = new HashMap<>();
                 map.put("id", page.getRecords().get(i).getId());
@@ -142,7 +171,7 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
                 map.put("infoType", page.getRecords().get(i).getInfoType());
                 map.put("createTime", page.getRecords().get(i).getCreateTime());
                 for (int j = 0; j < readStatisticList.size(); j++) {
-                    if (page.getRecords().get(i).getId().equals(readStatisticList.get(j).get("contentId"))){
+                    if (page.getRecords().get(i).getId().equals(readStatisticList.get(j).get("contentId"))) {
                         map.put("notReadCount", readStatisticList.get(j).get("notReadCount"));
                         map.put("readCount", readStatisticList.get(j).get("readCount"));
                         map.put("userName", readStatisticList.get(j).get("issuerName"));
@@ -152,15 +181,15 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
             }
         }
 
-        return new CommonPage<>(list,page.getTotal(),page.getCurrent(),page.getSize());
+        return new CommonPage<>(list, page.getTotal(), page.getCurrent(), page.getSize());
     }
 
     @Override
     public CommonPage<MceReceive> mceManageById(Integer id, Integer current, Integer size) {
         IPage<MceReceive> page = new Page<>(current, size);
         LambdaQueryWrapper<MceReceive> lambdaQuery = Wrappers.lambdaQuery();
-        lambdaQuery.eq(MceReceive::getContentId,id);
-        page = this.page(page,lambdaQuery);
+        lambdaQuery.eq(MceReceive::getContentId, id);
+        page = this.page(page, lambdaQuery);
 //        if (CollectionUtils.isNotEmpty(page.getRecords())) {
 //            List<Integer> userIds = new ArrayList<>();
 //            for (int i = 0; i < page.getRecords().size(); i++) {
@@ -183,7 +212,7 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
 //                }
 //            }
 //        }
-        return new CommonPage<>(page.getRecords(),page.getTotal(),page.getCurrent(),page.getSize());
+        return new CommonPage<>(page.getRecords(), page.getTotal(), page.getCurrent(), page.getSize());
     }
 
     @Override
@@ -192,15 +221,15 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
         LocalDateTime oneYearAgo = currentDate.minusYears(1);
         LocalDateTime zeroTime = oneYearAgo.withHour(0).withMinute(0).withSecond(0);
         QueryWrapper<MceReceive> queryWrapper = Wrappers.query();
-        queryWrapper.select("COUNT(read_flag=0 or null) as notReadCount","COUNT(read_flag=1 or null) as readCount"
-                ,"info_type AS infoType")
-                .eq("receiver_id",SecurityUtils.getUserId())
-                .between("create_time",zeroTime,currentDate)
+        queryWrapper.select("COUNT(read_flag=0 or null) as notReadCount", "COUNT(read_flag=1 or null) as readCount"
+                        , "info_type AS infoType")
+                .eq("receiver_id", SecurityUtils.getUserId())
+                .between("create_time", zeroTime, currentDate)
                 .groupBy("info_type");
-        List<Map<String,Object>> readStatisticList = this.listMaps(queryWrapper);
+        List<Map<String, Object>> readStatisticList = this.listMaps(queryWrapper);
         LambdaQueryWrapper<MceReceive> lambdaQuery = Wrappers.lambdaQuery();
-        lambdaQuery.eq(MceReceive::getReceiverId,SecurityUtils.getUserId())
-                .eq(MceReceive::getReadFlag,0);
+        lambdaQuery.eq(MceReceive::getReceiverId, SecurityUtils.getUserId())
+                .eq(MceReceive::getReadFlag, 0);
         Integer notReadCount = this.count(lambdaQuery);
         Map<String, Object> map = new HashMap<>();
         map.put("notReadCount", notReadCount);
@@ -209,19 +238,19 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
     }
 
     @Override
-    public void updateMceReceive(MceReceive mceReceive){
+    public void updateMceReceive(MceReceive mceReceive) {
         LambdaUpdateWrapper<MceReceive> updateWrapper = new UpdateWrapper<MceReceive>().lambda();
-        if (Objects.nonNull(mceReceive.getId())&&!mceReceive.getId().equals(0)){
-            updateWrapper.eq(MceReceive::getId,mceReceive.getId())
-                    .set(MceReceive::getReadFlag,1)
-                    .set(MceReceive::getUpdateBy,SecurityUtils.getUsername())
-                    .set(MceReceive::getUpdateTime,LocalDateTime.now());
-        }else {
-            updateWrapper.eq(MceReceive::getReceiverId,SecurityUtils.getUserId())
-                    .eq(MceReceive::getReadFlag,0)
-                    .set(MceReceive::getReadFlag,1)
-                    .set(MceReceive::getUpdateBy,SecurityUtils.getUsername())
-                    .set(MceReceive::getUpdateTime,LocalDateTime.now());
+        if (Objects.nonNull(mceReceive.getId()) && !mceReceive.getId().equals(0)) {
+            updateWrapper.eq(MceReceive::getId, mceReceive.getId())
+                    .set(MceReceive::getReadFlag, 1)
+                    .set(MceReceive::getUpdateBy, SecurityUtils.getUsername())
+                    .set(MceReceive::getUpdateTime, LocalDateTime.now());
+        } else {
+            updateWrapper.eq(MceReceive::getReceiverId, SecurityUtils.getUserId())
+                    .eq(MceReceive::getReadFlag, 0)
+                    .set(MceReceive::getReadFlag, 1)
+                    .set(MceReceive::getUpdateBy, SecurityUtils.getUsername())
+                    .set(MceReceive::getUpdateTime, LocalDateTime.now());
         }
         this.update(updateWrapper);
     }
@@ -236,21 +265,396 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
         }
     }
 
+    @Async
+    @Override
+    public void addMceReceive(MceRequestVO mceRequestVO) {
+        log.info("本次发送消息内容: {}", mceRequestVO.toString());
+
+        // 补充信息类型名称
+        if (mceRequestVO.getInfoTypeName() == null) {
+            String infoTypeName = sysDictDataService.selectDictLabel("message_type", mceRequestVO.getInfoType());
+            mceRequestVO.setInfoTypeName(infoTypeName);
+        }
+
+        // 获取发送者租户ID
+        Integer tenantId = getUserTenantId(mceRequestVO.getUserName());
+        if (tenantId == null) {
+            log.error("获取用户租户ID失败,未找到用户: {}", mceRequestVO.getUserName());
+            return;
+        }
+
+        // 获取租户所有用户信息
+        List<SysUser> allUsers = userMapper.tenantIdUserList(tenantId);
+        if (CollectionUtils.isEmpty(allUsers)) {
+            log.warn("租户下未找到任何用户,租户ID: {}", tenantId);
+            return;
+        }
+
+        // 构建用户信息映射
+        Map<Long, SysUser> userIdToUserMap = allUsers.stream()
+                .collect(Collectors.toMap(SysUser::getUserId, user -> user));
+
+        Map<String, String> userNameToNickNameMap = allUsers.stream()
+                .collect(Collectors.toMap(SysUser::getUserName, SysUser::getNickName));
+
+
+
+        // 筛选目标用户
+        List<Long> targetUserIds = mceRequestVO.getUserIds();
+        List<Long> validUserIds = allUsers.stream()
+                .map(SysUser::getUserId)
+                .filter(targetUserIds::contains)
+                .collect(Collectors.toList());
+
+        if (CollectionUtils.isEmpty(validUserIds)) {
+            log.error("用户: {} 发送的{},id: {},抄送用户均不存在!消息发送终止",
+                    mceRequestVO.getUserName(), mceRequestVO.getInfoTypeName(), mceRequestVO.getId());
+            return;
+        }
+
+        // 获取用户消息配置
+        List<MceMbuser> mbUserList = mceMbuserService.list(Wrappers.lambdaQuery(MceMbuser.class)
+                .in(MceMbuser::getUserId, validUserIds));
+
+        if (CollectionUtils.isEmpty(mbUserList)) {
+            log.error("消息配置为空!用户id列表为: {},id: {},消息发送终止", validUserIds, mceRequestVO.getId());
+            return;
+        }
+
+        // 构建用户ID到消息配置的映射
+        Map<Long, MceMbuser> userIdToMbUserMap = mbUserList.stream()
+                .collect(Collectors.toMap(MceMbuser::getUserId, mbUser -> mbUser));
+
+        // 获取消息发送设置
+        List<MceSetting> settings = mceSettingService.list(Wrappers.lambdaQuery(MceSetting.class)
+                .eq(MceSetting::getCreateBy, mceRequestVO.getUserName()));
+
+        if (CollectionUtils.isEmpty(settings)) {
+            log.warn("未找到消息发送设置,用户: {}", mceRequestVO.getUserName());
+            return;
+        }
+
+        MceSetting setting = settings.get(0);
+        JSONObject appMode = JSONObject.parseObject(setting.getAppMode());
+        JSONObject wcMode = JSONObject.parseObject(setting.getWcMode());
+
+        // 处理每个目标用户的消息接收和发送
+        for (Long userId : validUserIds) {
+            SysUser user = userIdToUserMap.get(userId);
+            if (user == null) {
+                continue;
+            }
+
+            // 获取用户消息配置
+            MceMbuser mbUser = userIdToMbUserMap.get(userId);
+            if (mbUser == null) {
+                continue;
+            }
+
+            // 登录不需要新增消息记录
+            if ("0".equals(mceRequestVO.getInfoType())) {
+                handleMessageDelivery(mbUser, mceRequestVO, 0, appMode, wcMode);
+                return;
+            }
+
+            // 保存消息内容
+            Integer contentId = saveMessageContent(mceRequestVO, userIdToUserMap);
+            if (contentId == null) {
+                log.error("消息内容保存失败,用户: {}", mceRequestVO.getUserName());
+                return;
+            }
+
+            // 创建消息接收记录
+            MceReceive mceReceive = createMceReceive(user, contentId, mceRequestVO, userNameToNickNameMap);
+            boolean saveResult = this.save(mceReceive);
+            if (!saveResult) {
+                log.error("创建消息接收记录失败,用户ID: {}", userId);
+                continue;
+            }
+
+            // 根据消息类型处理消息发送
+            handleMessageDelivery(mbUser, mceRequestVO, mceReceive.getId(), appMode, wcMode);
+        }
+    }
+
+    /**
+     * 获取用户租户ID
+     */
+    private Integer getUserTenantId(String userName) {
+        try {
+            SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
+                    .eq(SysUser::getUserName, userName)
+                    .select(SysUser::getTenantId));
+            return user != null ? user.getTenantId() : null;
+        } catch (Exception e) {
+            log.error("获取用户租户ID失败,报错信息:{}", e.getMessage(), e);
+            return null;
+        }
+    }
+
+    /**
+     * 保存消息内容
+     */
+    private Integer saveMessageContent(MceRequestVO mceRequestVO, Map<Long, SysUser> userIdToUserMap) {
+        SysUser sender = userIdToUserMap.values().stream()
+                .filter(user -> mceRequestVO.getUserName().equals(user.getUserName()))
+                .findFirst()
+                .orElse(null);
+
+        if (sender == null) {
+            log.error("未找到发送者信息,用户名: {}", mceRequestVO.getUserName());
+            return null;
+        }
+
+        MceContent contentEntity = new MceContent();
+        contentEntity.setInfoTitle(mceRequestVO.getInfoTitle());
+        contentEntity.setInfoContent(mceRequestVO.getInfoContent());
+        contentEntity.setInfoType(mceRequestVO.getInfoType());
+        contentEntity.setCreateBy(sender.getUserName());
+        contentEntity.setCreateTime(LocalDateTime.now());
+        contentEntity.setDeptId(sender.getDeptId().intValue());
+        contentEntity.setTenantId(sender.getTenantId());
+
+        boolean saveResult = mceContentService.save(contentEntity);
+        return saveResult ? contentEntity.getId() : null;
+    }
+
+    /**
+     * 创建消息接收记录
+     */
+    private MceReceive createMceReceive(SysUser user, Integer contentId, MceRequestVO mceRequestVO,
+                                        Map<String, String> userNameToNickNameMap) {
+        MceReceive mceReceive = new MceReceive();
+        mceReceive.setReceiverId(user.getUserId().intValue());
+        mceReceive.setContentId(contentId);
+        mceReceive.setReadFlag(0);
+        mceReceive.setInfoType(mceRequestVO.getInfoType());
+        mceReceive.setModuleId(mceRequestVO.getId());
+        mceReceive.setIssuerName(userNameToNickNameMap.get(mceRequestVO.getUserName()));
+        mceReceive.setReceiverName(user.getUserName());
+        mceReceive.setCreateBy(mceRequestVO.getUserName());
+        mceReceive.setCreateTime(LocalDateTime.now());
+        mceReceive.setTenantId(user.getTenantId());
+        mceReceive.setDeptId(Math.toIntExact(user.getDeptId()));
+        return mceReceive;
+    }
+
+    /**
+     * 处理消息发送
+     */
+    private void handleMessageDelivery(MceMbuser mbUser, MceRequestVO mceRequestVO,
+                                       Integer mceReceiveId, JSONObject appMode, JSONObject wcMode) {
+        String infoType = mceRequestVO.getInfoType();
+
+        // 登录成功通知只给登录用户发送微信公众号消息
+        if ("0".equals(infoType)) {
+            SysUserPerson one = sysUserPersonService.lambdaQuery().select(SysUserPerson::getIsLoginNotify).eq(SysUserPerson::getUserId, mbUser.getUserId()).one();
+            Integer isLoginNotify = one.getIsLoginNotify();
+            if (isLoginNotify == 1) {
+                sendWeChatMessage(mbUser, mceRequestVO, wcMode, infoType, mceReceiveId);
+            } else {
+                log.info("用户{}未开启登录通知", mbUser.getUserId());
+            }
+            return;
+        }
+
+        // 处理告警消息
+        if ("4".equals(infoType)) {
+            handleAlarmMessage(mbUser, mceRequestVO, mceReceiveId, appMode, wcMode, infoType);
+            return;
+        }
+
+        // 处理普通消息(默认APP和微信都通知)
+        handleNormalMessage(mbUser, mceRequestVO, mceReceiveId, appMode, wcMode, infoType);
+    }
+
+    /**
+     * 处理告警消息
+     */
+    private void handleAlarmMessage(MceMbuser mbUser, MceRequestVO mceRequestVO, Integer mceReceiveId,
+                                    JSONObject appMode, JSONObject wcMode, String infoType) {
+        String alarmSendType = mceRequestVO.getAlarmSendType();
+        switch (alarmSendType) {
+            case "1":
+                sendAppMessage(mbUser, mceRequestVO, appMode, infoType);
+                break;
+            case "2":
+                sendWeChatMessage(mbUser, mceRequestVO, wcMode, infoType, mceReceiveId);
+                break;
+            default:
+                log.error("未知的告警发送类型: {}", alarmSendType);
+                break;
+        }
+    }
+
+    /**
+     * 发送普通消息
+     */
+    private void handleNormalMessage(MceMbuser mbUser, MceRequestVO mceRequestVO, Integer mceReceiveId,
+                                     JSONObject appMode, JSONObject wcMode, String infoType) {
+        sendAppMessage(mbUser, mceRequestVO, appMode, infoType);
+        sendWeChatMessage(mbUser, mceRequestVO, wcMode, infoType, mceReceiveId);
+    }
+
+    /**
+     * 发送APP消息
+     */
+    private void sendAppMessage(MceMbuser mbUser, MceRequestVO mceRequestVO, JSONObject mode, String infoType) {
+        if (mode.getBoolean(infoType) && mbUser.getCids() != null) {
+            try {
+                mceContentService.sendAppNew(mceRequestVO, mbUser.getCids(), 0, 0);
+            } catch (Exception e) {
+                log.error("为用户ID: {} 发送应用消息失败,错误信息: {}", mbUser.getUserId(), e.getMessage(), e);
+            }
+        }
+    }
+
+    /**
+     * 推送微信消息
+     */
+    private void sendWeChatMessage(MceMbuser mbUser, MceRequestVO mceRequestVO, JSONObject mode,
+                                   String infoType, Integer mceReceiveId) {
+
+        if (mbUser.getOpenid() == null) {
+            return;
+        }
+
+        if ("0".equals(infoType) || mode.getBoolean(infoType)) {
+            try {
+                mceContentService.sendAppNew(mceRequestVO, mbUser.getOpenid(), mceReceiveId, 1);
+            } catch (Exception e) {
+                log.error("为用户ID: {} 发送微信消息失败,错误信息: {}", mbUser.getUserId(), e.getMessage(), e);
+            }
+        }
+    }
+
+
+    /*
+    @Async
     @Override
-    public void add(String mceReceive){
+    public void addMceReceive(MceRequestVO mceRequestVO) {
+        if (mceRequestVO.getInfoTypeName() == null) {
+            String infoTypeName = sysDictDataService.selectDictLabel("message_type", mceRequestVO.getInfoType());
+            mceRequestVO.setInfoTypeName(infoTypeName);
+        }
+
+        List<SysUser> userList = userMapper.tenantIdUserList(SecurityUtils.getTenantId());
+        // 获取用户昵称与真实姓名Map
+        Map<String, String> userNameNickNameMap = userList.stream().collect(Collectors.toMap(SysUser::getUserName, SysUser::getNickName));
+
+        if (CollectionUtils.isNotEmpty(userList)) {
+            LocalDateTime currentTime = LocalDateTime.now();
+            List<Integer> userIdList = new ArrayList<>();
+            MceContent contentEntity = new MceContent();
+            Integer generatedContentId = 0;
+            for (SysUser user : userList) {
+                userIdList.add(user.getUserId().intValue());
+                if (mceRequestVO.getUserName().equals(user.getUserName())) {
+                    contentEntity.setInfoTitle(mceRequestVO.getInfoTitle());
+                    contentEntity.setInfoContent(mceRequestVO.getInfoContent());
+                    contentEntity.setInfoType(mceRequestVO.getInfoType());
+                    contentEntity.setCreateBy(user.getUserName());
+                    contentEntity.setCreateTime(currentTime);
+                    contentEntity.setDeptId(user.getDeptId().intValue());
+                    contentEntity.setTenantId(user.getTenantId());
+                    mceContentService.save(contentEntity);
+                    generatedContentId = contentEntity.getId();
+                }
+            }
+
+            List<Long> userIds1;
+            userIds1 = mceRequestVO.getUserIds();
+            userList.retainAll(userIds1);
+
+            LambdaQueryWrapper<MceMbuser> lambdaQuery3 = Wrappers.lambdaQuery();
+            lambdaQuery3.in(MceMbuser::getUserId, userList);
+            List<MceMbuser> list3 = mceMbuserService.list(lambdaQuery3);
+
+            for (int i = 0; i < userList.size(); i++) {
+                if (CollectionUtils.isNotEmpty(list3)) {
+                    for (int j = 0; j < list3.size(); j++) {
+                        if (userList.get(i).getUserId().equals(list3.get(j).getUserId())) {
+                            MceReceive mceReceive1 = new MceReceive();
+                            mceReceive1.setReceiverId(userList.get(i).getUserId().intValue());
+                            mceReceive1.setContentId(generatedContentId);
+                            mceReceive1.setReadFlag(0);
+                            mceReceive1.setInfoType(mceRequestVO.getInfoType());
+                            mceReceive1.setModuleId(mceRequestVO.getId());
+
+                            String userName = mceRequestVO.getUserName();
+                            String nickName = userNameNickNameMap.get(userName);
+                            mceReceive1.setIssuerName(nickName);
+
+                            mceReceive1.setReceiverName(userList.get(i).getUserName());
+                            mceReceive1.setCreateBy(mceRequestVO.getUserName());
+                            mceReceive1.setCreateTime(LocalDateTime.now());
+                            mceReceive1.setTenantId(userList.get(i).getTenantId());
+                            mceReceive1.setDeptId(Math.toIntExact(userList.get(i).getDeptId()));
+                            this.save(mceReceive1);
+                            Integer mceReceiveId = mceReceive1.getId();
+
+                            LambdaQueryWrapper<MceSetting> lambdaQuery = Wrappers.lambdaQuery();
+                            lambdaQuery.eq(MceSetting::getCreateBy, userList.get(i).getUserName());
+                            List<MceSetting> list1 = mceSettingService.list(lambdaQuery);
+
+                            if (CollectionUtils.isNotEmpty(list1)) {
+                                JSONObject appMode = JSONObject.parseObject(list1.get(0).getAppMode());
+                                JSONObject wcMode = JSONObject.parseObject(list1.get(0).getWcMode());
+
+                                if (appMode.get(mceRequestVO.getInfoType()).equals(true)) {
+                                    if (userList.get(i).getUserId().equals(list3.get(j).getUserId()) && StringUtils.isNotBlank(list3.get(j).getCids())) {
+                                        try {
+                                            mceContentService.sendAppNew(mceRequestVO, list3.get(j).getCids(), 0, 0);
+                                        } catch (Exception e) {
+                                            log.error("为用户ID: {} 发送应用消息失败,错误信息: {}", list3.get(j).getUserId(), e.getMessage(), e);
+                                        }
+                                    }
+                                }
+
+                                if (wcMode.get(mceRequestVO.getInfoType()).equals(true)) {
+                                    if (userList.get(i).getUserId().equals(list3.get(j).getUserId()) && StringUtils.isNotBlank(list3.get(j).getOpenid())) {
+                                        try {
+                                            mceContentService.sendAppNew(mceRequestVO, list3.get(j).getOpenid(), mceReceiveId, 1);
+                                        } catch (Exception e) {
+                                            log.error("为用户ID: {} 发送微信消息失败,错误信息: {}", list3.get(j).getUserId(), e.getMessage(), e);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    */
+
+    @Async
+    @Override
+    public void add(String mceReceive) {
         JSONObject mceReceiveVO = JSONObject.parseObject(mceReceive);
-        String infoTypeName = sysDictDataService.selectDictLabel("message_type",mceReceiveVO.get("infoType").toString());
+        String infoTypeName = sysDictDataService.selectDictLabel("message_type", mceReceiveVO.get("infoType").toString());
         if (!mceReceiveVO.containsKey("infoTypeName")) {
-            mceReceiveVO.put("infoTypeName",infoTypeName);
+            mceReceiveVO.put("infoTypeName", infoTypeName);
+        }
+
+        Integer tenantId = null;
+        try {
+            tenantId = userMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, mceReceiveVO.get("userName")).select(SysUser::getTenantId)).getTenantId();
+        } catch (Exception e) {
+            log.error("获取用户租户ID失败,报错信息:{}, 未找到用户-{}-的租户", e.getMessage(), mceReceiveVO.get("userName"));
         }
-        List<SysUser> list = userMapper.tenantIdUserList(SecurityUtils.getTenantId());
+        List<SysUser> list = userMapper.tenantIdUserList(tenantId);
+        // 获取用户昵称与真实姓名Map
+        Map<String, String> userNameNickNameMap = list.stream().collect(Collectors.toMap(SysUser::getUserName, SysUser::getNickName));
         MceContent mceContent = new MceContent();
         Integer contentId = 0;
+
         if (CollectionUtils.isNotEmpty(list)) {
             List<Integer> userIds = new ArrayList<>();
             for (int g = 0; g < list.size(); g++) {
                 userIds.add(list.get(g).getUserId().intValue());
-                if (mceReceiveVO.get("userName").equals(list.get(g).getUserName())){
+                if (mceReceiveVO.get("userName").equals(list.get(g).getUserName())) {
                     mceContent.setInfoTitle(mceReceiveVO.get("infoTitle").toString());
                     mceContent.setInfoContent(mceReceiveVO.get("infoContent").toString());
                     mceContent.setInfoType(mceReceiveVO.get("infoType").toString());
@@ -262,50 +666,65 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
                     contentId = mceContent.getId();
                 }
             }
+
             List<Integer> userIds1;
             if (mceReceiveVO.containsKey("userIds")) {
                 userIds1 = convertObjectToList(mceReceiveVO.get("userIds"));
                 userIds.retainAll(userIds1);
             }
+
             LambdaQueryWrapper<MceMbuser> lambdaQuery3 = Wrappers.lambdaQuery();
-            lambdaQuery3.in(MceMbuser::getUserId,userIds);
+            lambdaQuery3.in(MceMbuser::getUserId, userIds);
             List<MceMbuser> list3 = mceMbuserService.list(lambdaQuery3);
+
             for (int i = 0; i < list.size(); i++) {
-                if (CollectionUtils.isNotEmpty(list3)){
+                if (CollectionUtils.isNotEmpty(list3)) {
                     for (int j = 0; j < list3.size(); j++) {
-                        if (list.get(i).getUserId().equals(list3.get(j).getUserId())){
+                        if (list.get(i).getUserId().equals(list3.get(j).getUserId())) {
                             MceReceive mceReceive1 = new MceReceive();
                             mceReceive1.setReceiverId(list.get(i).getUserId().intValue());
                             mceReceive1.setContentId(contentId);
                             mceReceive1.setReadFlag(0);
                             mceReceive1.setInfoType(mceReceiveVO.get("infoType").toString());
-                            mceReceive1.setModuleId((int)mceReceiveVO.get("id"));
+                            mceReceive1.setModuleId((int) mceReceiveVO.get("id"));
                             if (mceReceiveVO.containsKey("userName")) {
-                                mceReceive1.setIssuerName(mceReceiveVO.get("userName").toString());
+                                String userName = mceReceiveVO.get("userName").toString();
+                                String nickName = userNameNickNameMap.get(userName);
+                                mceReceive1.setIssuerName(nickName);
                             }
                             mceReceive1.setReceiverName(list.get(i).getUserName());
                             mceReceive1.setCreateBy(mceReceiveVO.get("userName").toString());
                             mceReceive1.setCreateTime(LocalDateTime.now());
                             mceReceive1.setTenantId(list.get(i).getTenantId());
-                            if (mceReceiveVO.get("userName").equals(list.get(i).getUserName())){
-                                mceReceive1.setDeptId(list.get(i).getDeptId().intValue());
-                            }
+                            mceReceive1.setDeptId(list.get(i).getDeptId().intValue());
                             this.save(mceReceive1);
                             Integer mceReceiveId = mceReceive1.getId();
+
                             LambdaQueryWrapper<MceSetting> lambdaQuery = Wrappers.lambdaQuery();
-                            lambdaQuery.eq(MceSetting::getCreateBy,list.get(i).getUserName());
+                            lambdaQuery.eq(MceSetting::getCreateBy, list.get(i).getUserName());
                             List<MceSetting> list1 = mceSettingService.list(lambdaQuery);
-                            if (CollectionUtils.isNotEmpty(list1)){
+
+                            if (CollectionUtils.isNotEmpty(list1)) {
                                 JSONObject appMode = JSONObject.parseObject(list1.get(0).getAppMode());
                                 JSONObject wcMode = JSONObject.parseObject(list1.get(0).getWcMode());
-                                if (appMode.get(mceReceiveVO.get("infoType").toString()).equals(true)){
-                                    if (list.get(i).getUserId().equals(list3.get(j).getUserId()) && StringUtils.isNotBlank(list3.get(j).getCids())){
-                                        mceContentService.sendApp(mceReceiveVO,list3.get(j).getCids(),0,0);
+
+                                if (appMode.get(mceReceiveVO.get("infoType").toString()).equals(true)) {
+                                    if (list.get(i).getUserId().equals(list3.get(j).getUserId()) && StringUtils.isNotBlank(list3.get(j).getCids())) {
+                                        try {
+                                            mceContentService.sendApp(mceReceiveVO, list3.get(j).getCids(), 0, 0);
+                                        } catch (Exception e) {
+                                            log.error("为用户ID: {} 发送应用消息失败,错误信息: {}", list3.get(j).getUserId(), e.getMessage(), e);
+                                        }
                                     }
                                 }
-                                if (wcMode.get(mceReceiveVO.get("infoType").toString()).equals(true)){
-                                    if (list.get(i).getUserId().equals(list3.get(j).getUserId()) && StringUtils.isNotBlank(list3.get(j).getOpenid())){
-                                        mceContentService.sendApp(mceReceiveVO,list3.get(j).getOpenid(),mceReceiveId,1);
+
+                                if (wcMode.get(mceReceiveVO.get("infoType").toString()).equals(true)) {
+                                    if (list.get(i).getUserId().equals(list3.get(j).getUserId()) && StringUtils.isNotBlank(list3.get(j).getOpenid())) {
+                                        try {
+                                            mceContentService.sendApp(mceReceiveVO, list3.get(j).getOpenid(), mceReceiveId, 1);
+                                        } catch (Exception e) {
+                                            log.error("为用户ID: {} 发送微信消息失败,错误信息: {}", list3.get(j).getUserId(), e.getMessage(), e);
+                                        }
                                     }
                                 }
                             }
@@ -319,8 +738,91 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
     @Override
     public boolean removeById(Integer id) {
         LambdaQueryWrapper<MceReceive> lambdaQuery = Wrappers.lambdaQuery();
-        lambdaQuery.eq(MceReceive::getContentId,id);
+        lambdaQuery.eq(MceReceive::getContentId, id);
         this.remove(lambdaQuery);
         return mceContentService.removeById(id);
     }
+
+    @Override
+    public boolean deleteById(Integer id) {
+        boolean f;
+        Integer userId = SecurityUtils.getUserId().intValue();
+        MceReceive mceReceive = mceReceiveMapper.selectOne(new LambdaQueryWrapper<MceReceive>().eq(MceReceive::getId, id));
+        if (mceReceive != null) {
+            if (userId.equals(mceReceive.getReceiverId())) {
+                mceReceiveMapper.deleteById(id);
+                f = true;
+            } else {
+                throw new BusinessException("您无权删除该条记录!");
+            }
+        } else {
+            throw new BusinessException("记录不存在,删除失败!");
+        }
+        return f;
+    }
+
+    @Override
+    public CommonPage<MceReceiveResponseVO> getMceReceiveResponseVOList(Integer pageNumber, Integer pageSize) {
+        IPage<MceReceive> page = new Page<>(pageNumber, pageSize);
+        Long userId = SecurityUtils.getUserId();
+        List<MceReceiveResponseVO> returnList = new ArrayList<>();
+
+        LambdaQueryWrapper<MceReceive> lambdaQuery = Wrappers.lambdaQuery();
+        lambdaQuery.eq(MceReceive::getReceiverId, userId).orderByDesc(MceReceive::getId);
+        page = this.page(page, lambdaQuery);
+        List<MceReceive> mceReceiveList = page.getRecords();
+        List<Integer> contentIdList = mceReceiveList.stream().map(MceReceive::getContentId).distinct().collect(Collectors.toList());
+
+        List<MceContent> mceContentList = mceContentService.list(new LambdaQueryWrapper<MceContent>().in(MceContent::getId, contentIdList));
+
+        for (MceContent mceContent : mceContentList) {
+            MceReceive mceReceive = mceReceiveList.stream().filter(mceReceive1 -> mceReceive1.getContentId().equals(mceContent.getId())).findFirst().get();
+            MceReceiveResponseVO mceReceiveResponseVO = new MceReceiveResponseVO();
+            mceReceiveResponseVO.setMceId(mceReceive.getId());
+            mceReceiveResponseVO.setInfoType(mceContent.getInfoType());
+            mceReceiveResponseVO.setInfoTitle(mceContent.getInfoTitle());
+            mceReceiveResponseVO.setContentId(mceContent.getId());
+            mceReceiveResponseVO.setInfoContent(mceContent.getInfoContent());
+            mceReceiveResponseVO.setCreateTime(mceContent.getCreateTime());
+            mceReceiveResponseVO.setCreateBy(mceContent.getCreateBy());
+            mceReceiveResponseVO.setModuleId(mceReceive.getModuleId());
+            returnList.add(mceReceiveResponseVO);
+        }
+
+        return new CommonPage<>(returnList, page.getTotal(), page.getSize(), page.getCurrent());
+    }
+
+    /**
+     * 新增消息-无需token
+     * @param mceNoToken
+     */
+    @Override
+    public void addNoToken(String mceNoToken) {
+        JSONObject json = JSONObject.parseObject(mceNoToken);
+        String infoTypeName = sysDictDataService.selectDictLabel("message_type", json.get("infoType").toString());
+        if (!json.containsKey("infoTypeName")) {
+            json.put("infoTypeName", infoTypeName);
+        }
+        List<String> userNames = JSONObject.parseArray(json.get("userNames").toString(), String.class);
+
+        LambdaQueryWrapper<SysUser> lambdaQuery = Wrappers.lambdaQuery();
+        lambdaQuery.select(SysUser::getUserId)
+                .in(SysUser::getUserName, userNames);
+        List<Long> userIdList = userMapper.selectList(lambdaQuery).stream().map(SysUser::getUserId).collect(Collectors.toList());
+
+        MceRequestVO mceRequestVO = new MceRequestVO();
+        mceRequestVO.setUserIds(userIdList);
+        mceRequestVO.setInfoTitle(json.get("infoTitle").toString());
+        mceRequestVO.setInfoContent(json.get("infoContent").toString());
+        mceRequestVO.setInfoType(json.get("infoType").toString());
+        mceRequestVO.setInfoTypeName(json.get("infoTypeName").toString());
+        mceRequestVO.setId((Integer) json.get("id"));
+        mceRequestVO.setUserName(json.get("userName").toString());
+        mceRequestVO.setApprovalResult(json.get("approvalResult").toString());
+        mceRequestVO.setProcessName(json.get("processName").toString());
+        mceRequestVO.setApprovalNode(json.get("approvalNode").toString());
+        mceRequestVO.setRealName(json.get("realName").toString());
+        mceRequestVO.setOaType(json.get("oaType").toString());
+        addMceReceive(mceRequestVO);
+    }
 }

+ 15 - 8
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysDeptServiceImpl.java

@@ -1,8 +1,6 @@
 package com.usky.system.service.impl;
 
 
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.ruoyi.common.datascope.annotation.DataScope;
 import com.usky.common.mybatis.core.AbstractCrudService;
 import com.usky.common.security.utils.SecurityUtils;
@@ -12,7 +10,6 @@ import com.usky.common.core.util.StringUtils;
 import com.usky.system.domain.SysDept;
 import com.usky.system.domain.SysRole;
 import com.usky.system.domain.SysUser;
-import com.usky.system.domain.SysUserPost;
 import com.usky.system.domain.constants.UserConstants;
 import com.usky.system.mapper.SysDeptMapper;
 import com.usky.system.mapper.SysRoleMapper;
@@ -21,13 +18,10 @@ import com.usky.system.service.ISysDeptService;
 import com.usky.system.service.vo.TreeNode;
 import com.usky.system.service.vo.TreeSelect;
 import com.usky.system.service.vo.UserPostVo;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.*;
-import java.util.function.Function;
 import java.util.stream.Collectors;
 
 
@@ -39,8 +33,6 @@ import java.util.stream.Collectors;
 @Service
 public class SysDeptServiceImpl extends AbstractCrudService<SysDeptMapper, SysDept> implements ISysDeptService {
 
-    private static final Logger log = LoggerFactory.getLogger(SysDeptServiceImpl.class);//还原代码
-
     @Autowired
     private SysDeptMapper deptMapper;
 
@@ -63,6 +55,13 @@ public class SysDeptServiceImpl extends AbstractCrudService<SysDeptMapper, SysDe
         return deptMapper.selectDeptList(dept);
     }
 
+    // 查询租户下部门信,无数据权限
+    @Override
+    public List<SysDept> selectDept(SysDept dept) {
+        dept.setTenantId(SecurityUtils.getTenantId());
+        return deptMapper.selectDeptList(dept);
+    }
+
     @Override
     public List<SysDept> deptList(SysDept dept) {
         dept.setTenantId(SecurityUtils.getTenantId());
@@ -209,6 +208,14 @@ public class SysDeptServiceImpl extends AbstractCrudService<SysDeptMapper, SysDe
         return deptMapper.selectDeptById(deptId);
     }
 
+    @Override
+    public List<SysDept> selectDeptByIds(List<Long> deptIds) {
+        if (deptIds == null || deptIds.isEmpty()) {
+            return Collections.emptyList();
+        }
+        return deptMapper.selectDeptByIds(deptIds);
+    }
+
     /**
      * 根据ID查询所有子部门(正常状态)
      *

+ 165 - 243
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysMenuServiceImpl.java

@@ -28,8 +28,7 @@ import java.util.stream.Collectors;
  * @author yq
  */
 @Service
-public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMenu> implements ISysMenuService
-{
+public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMenu> implements ISysMenuService {
     public static final String PREMISSION_STRING = "perms[\"{0}\"]";
 
     @Autowired
@@ -69,8 +68,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 菜单列表
      */
     @Override
-    public List<SysMenu> selectMenuList(Long userId)
-    {
+    public List<SysMenu> selectMenuList(Long userId) {
         return selectMenuList(new SysMenu(), userId);
     }
 
@@ -81,16 +79,12 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 菜单列表
      */
     @Override
-    public List<SysMenu> selectMenuList(SysMenu menu, Long userId)
-    {
+    public List<SysMenu> selectMenuList(SysMenu menu, Long userId) {
         List<SysMenu> menuList = null;
         // 管理员显示所有菜单信息
-        if (SysUserVO.isAdmin(userId))
-        {
+        if (SysUserVO.isAdmin(userId)) {
             menuList = menuMapper.selectMenuList(menu);
-        }
-        else
-        {
+        } else {
             menu.getParams().put("userId", userId);
             menuList = menuMapper.selectMenuListByUserId(menu);
         }
@@ -98,24 +92,21 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
     }
 
     @Override
-    public List<SysMenu> selectMenuListTwo(SysMenu menu)
-    {
-        List<SysMenu> menuList = menuMapper.selectMenuListOne(SecurityUtils.getTenantId(),menu.getMenuName());
+    public List<SysMenu> selectMenuListTwo(SysMenu menu) {
+        List<SysMenu> menuList = menuMapper.selectMenuListOne(SecurityUtils.getTenantId(), menu.getMenuName());
         return menuList;
     }
 
 
     @Override
-    public List<SysMenu> selectMenuListOne(Long userId)
-    {
+    public List<SysMenu> selectMenuListOne(Long userId) {
         List<SysMenu> menuList = menuMapper.selectMenuListByUserIdOne(userId);
         return menuList;
     }
 
 
     @Override
-    public List<SysMobileMenu> selectMobileMenuListOne(Long userId)
-    {
+    public List<SysMobileMenu> selectMobileMenuListOne(Long userId) {
         List<SysMobileMenu> menuList = menuMapper.selectMobileMenuListByUserIdOne(userId);
         return menuList;
     }
@@ -127,14 +118,11 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 权限列表
      */
     @Override
-    public Set<String> selectMenuPermsByUserId(Long userId)
-    {
+    public Set<String> selectMenuPermsByUserId(Long userId) {
         List<String> perms = menuMapper.selectMenuPermsByUserId(userId);
         Set<String> permsSet = new HashSet<>();
-        for (String perm : perms)
-        {
-            if (StringUtils.isNotEmpty(perm))
-            {
+        for (String perm : perms) {
+            if (StringUtils.isNotEmpty(perm)) {
                 permsSet.addAll(Arrays.asList(perm.trim().split(",")));
             }
         }
@@ -148,14 +136,11 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 权限列表
      */
     @Override
-    public Set<String> selectMenuPermsByUserIdOne(Integer tenantId)
-    {
+    public Set<String> selectMenuPermsByUserIdOne(Integer tenantId) {
         List<String> perms = menuMapper.selectMenuPermsByUserIdOne(tenantId);
         Set<String> permsSet = new HashSet<>();
-        for (String perm : perms)
-        {
-            if (StringUtils.isNotEmpty(perm))
-            {
+        for (String perm : perms) {
+            if (StringUtils.isNotEmpty(perm)) {
                 permsSet.addAll(Arrays.asList(perm.trim().split(",")));
             }
         }
@@ -170,15 +155,11 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 菜单列表
      */
     @Override
-    public List<SysMenu> selectMenuTreeByUserId(Long userId)
-    {
+    public List<SysMenu> selectMenuTreeByUserId(Long userId) {
         List<SysMenu> menus = null;
-        if (1L == userId)
-        {
+        if (1L == userId) {
             menus = menuMapper.selectMenuTreeAll();
-        }
-        else
-        {
+        } else {
             menus = menuMapper.selectMenuTreeByUserId(userId);
         }
         return getChildPerms(menus, 0);
@@ -191,33 +172,29 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 菜单列表
      */
     @Override
-    public List<SysMenu> selectMenuTreeByUserId1(Long userId,Long platformId)
-    {
+    public List<SysMenu> selectMenuTreeByUserId1(Long userId, Long platformId, Integer tenantId) {
         List<SysMenu> menus = null;
-        if (1L == userId)
-        {
+        if (1L == userId) {
             menus = menuMapper.selectMenuTreeAll();
-        }
-        else
-        {
-            menus = menuMapper.selectMenuTreeByUserId1(userId,platformId);
+        } else {
+            menus = menuMapper.selectMenuTreeByUserId1(userId, platformId, tenantId);
         }
         return getChildPerms(menus, 0);
     }
 
 
-    public List<SysMenu> selectMenuTreeByUserIdOne(Integer tenantId){
+    public List<SysMenu> selectMenuTreeByUserIdOne(Integer tenantId) {
         List<SysMenu> menus = menuMapper.selectMenuTreeByUserIdOne(tenantId);
         return getChildPerms(menus, 0);
     }
 
-    public List<SysMenu> selectMenuTreeByUserIdOne1(Integer tenantId,Integer platformId){
-        List<SysMenu> menus = menuMapper.selectMenuTreeByUserIdOne1(tenantId,platformId);
+    public List<SysMenu> selectMenuTreeByUserIdOne1(Integer tenantId, Integer platformId) {
+        List<SysMenu> menus = menuMapper.selectMenuTreeByUserIdOne1(tenantId, platformId);
         return getChildPerms(menus, 0);
     }
 
     @Override
-    public List<SysTenantMenu> selectTenantMenuList(Integer tenantId){
+    public List<SysTenantMenu> selectTenantMenuList(Integer tenantId) {
         List<SysTenantMenu> menus = tenantMenuMapper.selectTenantMenuList(tenantId);
         return menus;
     }
@@ -229,8 +206,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 选中菜单列表
      */
     @Override
-    public List<Integer> selectMenuListByRoleId(Long roleId)
-    {
+    public List<Integer> selectMenuListByRoleId(Long roleId) {
         SysRole role = roleMapper.selectRoleById(roleId);
         return menuMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly());
     }
@@ -242,47 +218,43 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 路由列表
      */
     @Override
-    public List<RouterVo> buildMenus(List<SysMenu> menus)
-    {
+    public List<RouterVo> buildMenus(List<SysMenu> menus) {
         List<RouterVo> routers = new LinkedList<RouterVo>();
-        for (SysMenu menu : menus)
-        {
+        for (SysMenu menu : menus) {
             RouterVo router = new RouterVo();
             router.setHidden("1".equals(menu.getVisible()));
             router.setName(getRouteName(menu));
             router.setPath(getRouterPath(menu));
             router.setComponent(getComponent(menu));
-            router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+            router.setOrderNum(menu.getOrderNum());
+            router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
             List<SysMenu> cMenus = menu.getChildren();
-            if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
-            {
+            if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType())) {
                 router.setAlwaysShow(true);
                 router.setRedirect("noRedirect");
                 router.setChildren(buildMenus(cMenus));
-            }
-            else if (isMenuFrame(menu))
-            {
+            } else if (isMenuFrame(menu)) {
                 router.setMeta(null);
                 List<RouterVo> childrenList = new ArrayList<RouterVo>();
                 RouterVo children = new RouterVo();
                 children.setPath(menu.getPath());
                 children.setComponent(menu.getComponent());
                 children.setName(StringUtils.capitalize(menu.getPath()));
-                children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                children.setOrderNum(menu.getOrderNum());
+                children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                 childrenList.add(children);
                 router.setChildren(childrenList);
-            }
-            else if (menu.getParentId().intValue() == 0 && isInnerLink(menu))
-            {
-                router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+            } else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) {
+                router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                 router.setPath("/inner");
                 List<RouterVo> childrenList = new ArrayList<RouterVo>();
                 RouterVo children = new RouterVo();
-                String routerPath = StringUtils.replaceEach(menu.getPath(), new String[] { Constants.HTTP, Constants.HTTPS }, new String[] { "", "" });
+                String routerPath = StringUtils.replaceEach(menu.getPath(), new String[]{Constants.HTTP, Constants.HTTPS}, new String[]{"", ""});
                 children.setPath(routerPath);
                 children.setComponent(UserConstants.INNER_LINK);
                 children.setName(StringUtils.capitalize(routerPath));
-                children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                children.setOrderNum(menu.getOrderNum());
+                children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                 childrenList.add(children);
                 router.setChildren(childrenList);
             }
@@ -296,59 +268,61 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 路由列表
      */
     @Override
-    public List<PlatformRouterVo> buildPlatformMenus()
-    {
+    public List<PlatformRouterVo> buildPlatformMenus() {
         List<PlatformRouterVo> platformRouterVos = new LinkedList<PlatformRouterVo>();
-        if (SecurityUtils.getLoginUser().getSysUser().getUserType().equals("01")){
-            List<SysPlatformVo> sysPlatformVos = sysPlatformMapper.getTenantPlatformList(SecurityUtils.getTenantId());
-            if (CollectionUtils.isNotEmpty(sysPlatformVos)){
-                for (SysPlatformVo platformVo : sysPlatformVos)
-                {
+        Long userId = SecurityUtils.getUserId();
+        Integer tenantId = SecurityUtils.getTenantId();
+        String userType = SecurityUtils.getLoginUser().getSysUser().getUserType();
+        if ("01".equals(userType)) {
+            List<SysPlatformVo> sysPlatformVos = sysPlatformMapper.getTenantPlatformList(tenantId);
+            if (CollectionUtils.isNotEmpty(sysPlatformVos)) {
+                for (SysPlatformVo platformVo : sysPlatformVos) {
                     PlatformRouterVo platformRouterVo = new PlatformRouterVo();
                     platformRouterVo.setPlatformId(platformVo.getId());
                     platformRouterVo.setPlatformName(platformVo.getPlatformName());
                     platformRouterVo.setIcon(platformVo.getIcon());
-                    List<SysMenu> menus1 = this.selectMenuTreeByUserIdOne1(SecurityUtils.getTenantId(),
+                    platformRouterVo.setOrderNum(platformVo.getOrderNum());
+                    platformRouterVo.setPlatformType(platformVo.getPlatformType());
+                    List<SysMenu> menus1 = this.selectMenuTreeByUserIdOne1(tenantId,
                             platformVo.getId());
                     List<RouterVo> routers = new LinkedList<RouterVo>();
-                    for (SysMenu menu : menus1)
-                    {
+                    for (SysMenu menu : menus1) {
                         RouterVo router = new RouterVo();
                         router.setHidden("1".equals(menu.getVisible()));
                         router.setName(getRouteName(menu));
                         router.setPath(getRouterPath(menu));
                         router.setComponent(getComponent(menu));
-                        router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                        router.setOrderNum(menu.getOrderNum());
+                        router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(),
+                                StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(),
+                                menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                         List<SysMenu> cMenus = menu.getChildren();
-                        if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
-                        {
+                        if (!cMenus.isEmpty() && UserConstants.TYPE_DIR.equals(menu.getMenuType())) {
                             router.setAlwaysShow(true);
                             router.setRedirect("noRedirect");
                             router.setChildren(buildMenus(cMenus));
-                        }
-                        else if (isMenuFrame(menu))
-                        {
+                        } else if (isMenuFrame(menu)) {
                             router.setMeta(null);
                             List<RouterVo> childrenList = new ArrayList<RouterVo>();
                             RouterVo children = new RouterVo();
                             children.setPath(menu.getPath());
                             children.setComponent(menu.getComponent());
                             children.setName(StringUtils.capitalize(menu.getPath()));
-                            children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                            children.setOrderNum(menu.getOrderNum());
+                            children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                             childrenList.add(children);
                             router.setChildren(childrenList);
-                        }
-                        else if (menu.getParentId().intValue() == 0 && isInnerLink(menu))
-                        {
-                            router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                        } else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) {
+                            router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                             router.setPath("/inner");
                             List<RouterVo> childrenList = new ArrayList<RouterVo>();
                             RouterVo children = new RouterVo();
-                            String routerPath = StringUtils.replaceEach(menu.getPath(), new String[] { Constants.HTTP, Constants.HTTPS }, new String[] { "", "" });
+                            String routerPath = StringUtils.replaceEach(menu.getPath(), new String[]{Constants.HTTP, Constants.HTTPS}, new String[]{"", ""});
                             children.setPath(routerPath);
                             children.setComponent(UserConstants.INNER_LINK);
                             children.setName(StringUtils.capitalize(routerPath));
-                            children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                            children.setOrderNum(menu.getOrderNum());
+                            children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                             childrenList.add(children);
                             router.setChildren(childrenList);
                         }
@@ -358,61 +332,63 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
                     platformRouterVos.add(platformRouterVo);
                 }
             }
-        }else {
+        } else {
             LambdaQueryWrapper<SysUserRole> queryWrapper = Wrappers.lambdaQuery();
-            queryWrapper.in(SysUserRole::getUserId,SecurityUtils.getUserId());
+            queryWrapper.eq(SysUserRole::getUserId, userId)
+                    .eq(SysUserRole::getTenantId, tenantId);
             List<SysUserRole> userRoleList = sysUserRoleMapper.selectList(queryWrapper);
-            if (CollectionUtils.isNotEmpty(userRoleList)){
-                List<SysPlatformVo> sysPlatformVos = sysPlatformMapper.getRolePlatformList(SecurityUtils.getTenantId(),
-                        userRoleList.get(0).getRoleId().intValue());
-                if (CollectionUtils.isNotEmpty(sysPlatformVos)){
-                    for (SysPlatformVo platformVo : sysPlatformVos)
-                    {
+            if (CollectionUtils.isNotEmpty(userRoleList)) {
+                List<SysPlatformVo> sysPlatformVos = userRoleList.stream()
+                        .map(userRole -> sysPlatformMapper.getRolePlatformList(tenantId, Math.toIntExact(userRole.getRoleId())))
+                        .flatMap(Collection::stream)
+                        .distinct()
+                        .collect(Collectors.toList());
+                if (CollectionUtils.isNotEmpty(sysPlatformVos)) {
+                    for (SysPlatformVo platformVo : sysPlatformVos) {
                         PlatformRouterVo platformRouterVo = new PlatformRouterVo();
                         platformRouterVo.setPlatformId(platformVo.getId());
                         platformRouterVo.setPlatformName(platformVo.getPlatformName());
                         platformRouterVo.setIcon(platformVo.getIcon());
-                        List<SysMenu> menus1 = this.selectMenuTreeByUserId1(SecurityUtils.getUserId(),
-                                platformVo.getId().longValue());
+                        platformRouterVo.setOrderNum(platformVo.getOrderNum());
+                        platformRouterVo.setPlatformType(platformVo.getPlatformType());
+                        List<SysMenu> menus1 = this.selectMenuTreeByUserId1(userId,
+                                platformVo.getId().longValue(), tenantId);
                         List<RouterVo> routers = new LinkedList<RouterVo>();
-                        for (SysMenu menu : menus1)
-                        {
+                        for (SysMenu menu : menus1) {
                             RouterVo router = new RouterVo();
                             router.setHidden("1".equals(menu.getVisible()));
                             router.setName(getRouteName(menu));
                             router.setPath(getRouterPath(menu));
                             router.setComponent(getComponent(menu));
-                            router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                            router.setOrderNum(menu.getOrderNum());
+                            router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                             List<SysMenu> cMenus = menu.getChildren();
-                            if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
-                            {
+                            if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType())) {
                                 router.setAlwaysShow(true);
                                 router.setRedirect("noRedirect");
                                 router.setChildren(buildMenus(cMenus));
-                            }
-                            else if (isMenuFrame(menu))
-                            {
+                            } else if (isMenuFrame(menu)) {
                                 router.setMeta(null);
                                 List<RouterVo> childrenList = new ArrayList<RouterVo>();
                                 RouterVo children = new RouterVo();
                                 children.setPath(menu.getPath());
                                 children.setComponent(menu.getComponent());
                                 children.setName(StringUtils.capitalize(menu.getPath()));
-                                children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                                children.setOrderNum(menu.getOrderNum());
+                                children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                                 childrenList.add(children);
                                 router.setChildren(childrenList);
-                            }
-                            else if (menu.getParentId().intValue() == 0 && isInnerLink(menu))
-                            {
-                                router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                            } else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) {
+                                router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                                 router.setPath("/inner");
                                 List<RouterVo> childrenList = new ArrayList<RouterVo>();
                                 RouterVo children = new RouterVo();
-                                String routerPath = StringUtils.replaceEach(menu.getPath(), new String[] { Constants.HTTP, Constants.HTTPS }, new String[] { "", "" });
+                                String routerPath = StringUtils.replaceEach(menu.getPath(), new String[]{Constants.HTTP, Constants.HTTPS}, new String[]{"", ""});
                                 children.setPath(routerPath);
                                 children.setComponent(UserConstants.INNER_LINK);
                                 children.setName(StringUtils.capitalize(routerPath));
-                                children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                                children.setOrderNum(menu.getOrderNum());
+                                children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                                 childrenList.add(children);
                                 router.setChildren(childrenList);
                             }
@@ -434,26 +410,21 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 树结构列表
      */
     @Override
-    public List<SysMenu> buildMenuTree(List<SysMenu> menus)
-    {
+    public List<SysMenu> buildMenuTree(List<SysMenu> menus) {
         List<SysMenu> returnList = new ArrayList<SysMenu>();
         List<Long> tempList = new ArrayList<Long>();
-        for (SysMenu dept : menus)
-        {
+        for (SysMenu dept : menus) {
             tempList.add(dept.getMenuId());
         }
-        for (Iterator<SysMenu> iterator = menus.iterator(); iterator.hasNext();)
-        {
+        for (Iterator<SysMenu> iterator = menus.iterator(); iterator.hasNext(); ) {
             SysMenu menu = (SysMenu) iterator.next();
             // 如果是顶级节点, 遍历该父节点的所有子节点
-            if (!tempList.contains(menu.getParentId()))
-            {
+            if (!tempList.contains(menu.getParentId())) {
                 recursionFn(menus, menu);
                 returnList.add(menu);
             }
         }
-        if (returnList.isEmpty())
-        {
+        if (returnList.isEmpty()) {
             returnList = menus;
         }
         return returnList;
@@ -466,26 +437,21 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 树结构列表
      */
     @Override
-    public List<SysMobileMenu> buildMobileMenuTree(List<SysMobileMenu> menus)
-    {
+    public List<SysMobileMenu> buildMobileMenuTree(List<SysMobileMenu> menus) {
         List<SysMobileMenu> returnList = new ArrayList<SysMobileMenu>();
         List<Long> tempList = new ArrayList<Long>();
-        for (SysMobileMenu dept : menus)
-        {
+        for (SysMobileMenu dept : menus) {
             tempList.add(dept.getMenuId());
         }
-        for (Iterator<SysMobileMenu> iterator = menus.iterator(); iterator.hasNext();)
-        {
+        for (Iterator<SysMobileMenu> iterator = menus.iterator(); iterator.hasNext(); ) {
             SysMobileMenu menu = (SysMobileMenu) iterator.next();
             // 如果是顶级节点, 遍历该父节点的所有子节点
-            if (!tempList.contains(menu.getParentId()))
-            {
+            if (!tempList.contains(menu.getParentId())) {
                 recursionMobileFn(menus, menu);
                 returnList.add(menu);
             }
         }
-        if (returnList.isEmpty())
-        {
+        if (returnList.isEmpty()) {
             returnList = menus;
         }
         return returnList;
@@ -498,8 +464,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 下拉树结构列表
      */
     @Override
-    public List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus)
-    {
+    public List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus) {
         List<SysMenu> menuTrees = buildMenuTree(menus);
         return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
     }
@@ -511,8 +476,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 下拉树结构列表
      */
     @Override
-    public List<TreeMobileSelect> buildMobileMenuTreeSelect(List<SysMobileMenu> menus)
-    {
+    public List<TreeMobileSelect> buildMobileMenuTreeSelect(List<SysMobileMenu> menus) {
         List<SysMobileMenu> menuTrees = buildMobileMenuTree(menus);
         return menuTrees.stream().map(TreeMobileSelect::new).collect(Collectors.toList());
     }
@@ -524,8 +488,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 菜单信息
      */
     @Override
-    public SysMenu selectMenuById(Long menuId)
-    {
+    public SysMenu selectMenuById(Long menuId) {
         return menuMapper.selectMenuById(menuId);
     }
 
@@ -536,8 +499,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 结果
      */
     @Override
-    public boolean hasChildByMenuId(Long menuId)
-    {
+    public boolean hasChildByMenuId(Long menuId) {
         int result = menuMapper.hasChildByMenuId(menuId);
         return result > 0 ? true : false;
     }
@@ -549,8 +511,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 结果
      */
     @Override
-    public boolean checkMenuExistRole(Long menuId)
-    {
+    public boolean checkMenuExistRole(Long menuId) {
         int result = roleMenuMapper.checkMenuExistRole(menuId);
         return result > 0 ? true : false;
     }
@@ -562,8 +523,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 结果
      */
     @Override
-    public int insertMenu(SysMenu menu)
-    {
+    public int insertMenu(SysMenu menu) {
         return menuMapper.insertMenu(menu);
     }
 
@@ -574,55 +534,53 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 结果
      */
     @Override
-    public int updateMenu(SysMenu menu)
-    {
+    public int updateMenu(SysMenu menu) {
         return menuMapper.updateMenu(menu);
     }
 
     @Override
-    public void updateTenantMenu(SysTenantMenu tenantMenu){
+    public void updateTenantMenu(SysTenantMenu tenantMenu) {
         UpdateWrapper<SysTenantMenu> updateWrapper = Wrappers.update();
-        updateWrapper.set("menu_alias_name",tenantMenu.getMenuAliasName())
-                .eq("tenant_id",tenantMenu.getTenantId())
-                .eq("menu_id",tenantMenu.getMenuId());
+        updateWrapper.set("menu_alias_name", tenantMenu.getMenuAliasName())
+                .eq("tenant_id", tenantMenu.getTenantId())
+                .eq("menu_id", tenantMenu.getMenuId());
         tenantMenuService.update(updateWrapper);
 
 
-
         LambdaQueryWrapper<SysUser> queryWrapper1 = Wrappers.lambdaQuery();
         queryWrapper1.select(SysUser::getUserId)
-                .eq(SysUser::getStatus,0)
-                .eq(SysUser::getDelFlag,0)
-                .eq(SysUser::getTenantId,SecurityUtils.getTenantId());
+                .eq(SysUser::getStatus, 0)
+                .eq(SysUser::getDelFlag, 0)
+                .eq(SysUser::getTenantId, SecurityUtils.getTenantId());
         List<SysUser> list = sysUserMapper.selectList(queryWrapper1);
         List<Long> userIdList = new ArrayList<>();
-        if(CollectionUtils.isNotEmpty(list)){
+        if (CollectionUtils.isNotEmpty(list)) {
             for (int i = 0; i < list.size(); i++) {
                 userIdList.add(list.get(i).getUserId());
             }
         }
 
-        if(userIdList.size() > 0){
+        if (userIdList.size() > 0) {
             LambdaQueryWrapper<SysUserRole> queryWrapper = Wrappers.lambdaQuery();
-            queryWrapper.in(SysUserRole::getUserId,userIdList);
+            queryWrapper.in(SysUserRole::getUserId, userIdList);
             List<SysUserRole> userRoleList = sysUserRoleMapper.selectList(queryWrapper);
             List<Long> roleIdList = new ArrayList<>();
-            if(userRoleList.size() > 0){
+            if (userRoleList.size() > 0) {
                 for (int i = 0; i < userRoleList.size(); i++) {
-                    if(roleIdList.contains(userRoleList.get(i).getRoleId())){
+                    if (roleIdList.contains(userRoleList.get(i).getRoleId())) {
 
-                    }else{
+                    } else {
                         roleIdList.add(userRoleList.get(i).getRoleId());
                     }
                 }
             }
 
-            if(roleIdList.size() > 0){
+            if (roleIdList.size() > 0) {
                 UpdateWrapper<SysRoleMenu> updateWrapper1 = Wrappers.update();
-                updateWrapper1.set("menu_alias_name",tenantMenu.getMenuAliasName())
-                        .in("role_id",roleIdList)
-                        .eq("menu_id",tenantMenu.getMenuId());
-                sysRoleMenuMapper.update(null,updateWrapper1);
+                updateWrapper1.set("menu_alias_name", tenantMenu.getMenuAliasName())
+                        .in("role_id", roleIdList)
+                        .eq("menu_id", tenantMenu.getMenuId());
+                sysRoleMenuMapper.update(null, updateWrapper1);
             }
 
         }
@@ -636,8 +594,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 结果
      */
     @Override
-    public int deleteMenuById(Long menuId)
-    {
+    public int deleteMenuById(Long menuId) {
         return menuMapper.deleteMenuById(menuId);
     }
 
@@ -648,12 +605,10 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 结果
      */
     @Override
-    public String checkMenuNameUnique(SysMenu menu)
-    {
+    public String checkMenuNameUnique(SysMenu menu) {
         Long menuId = Objects.isNull(menu.getMenuId()) ? -1L : menu.getMenuId();
         SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId());
-        if (Objects.nonNull(info) && info.getMenuId().longValue() != menuId.longValue())
-        {
+        if (Objects.nonNull(info) && info.getMenuId().longValue() != menuId.longValue()) {
             return UserConstants.NOT_UNIQUE;
         }
         return UserConstants.UNIQUE;
@@ -665,12 +620,10 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param menu 菜单信息
      * @return 路由名称
      */
-    public String getRouteName(SysMenu menu)
-    {
+    public String getRouteName(SysMenu menu) {
         String routerName = StringUtils.capitalize(menu.getPath());
         // 非外链并且是一级目录(类型为目录)
-        if (isMenuFrame(menu))
-        {
+        if (isMenuFrame(menu)) {
             routerName = StringUtils.EMPTY;
         }
         return routerName;
@@ -682,23 +635,19 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param menu 菜单信息
      * @return 路由地址
      */
-    public String getRouterPath(SysMenu menu)
-    {
+    public String getRouterPath(SysMenu menu) {
         String routerPath = menu.getPath();
         // 内链打开外网方式
-        if (menu.getParentId().intValue() != 0 && isInnerLink(menu))
-        {
-            routerPath = StringUtils.replaceEach(routerPath, new String[] { Constants.HTTP, Constants.HTTPS }, new String[] { "", "" });
+        if (menu.getParentId().intValue() != 0 && isInnerLink(menu)) {
+            routerPath = StringUtils.replaceEach(routerPath, new String[]{Constants.HTTP, Constants.HTTPS}, new String[]{"", ""});
         }
         // 非外链并且是一级目录(类型为目录)
         if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType())
-                && UserConstants.NO_FRAME.equals(menu.getIsFrame()))
-        {
+                && UserConstants.NO_FRAME.equals(menu.getIsFrame())) {
             routerPath = "/" + menu.getPath();
         }
         // 非外链并且是一级目录(类型为菜单)
-        else if (isMenuFrame(menu))
-        {
+        else if (isMenuFrame(menu)) {
             routerPath = "/";
         }
         return routerPath;
@@ -710,19 +659,13 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param menu 菜单信息
      * @return 组件信息
      */
-    public String getComponent(SysMenu menu)
-    {
+    public String getComponent(SysMenu menu) {
         String component = UserConstants.LAYOUT;
-        if (StringUtils.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu))
-        {
+        if (StringUtils.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu)) {
             component = menu.getComponent();
-        }
-        else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu))
-        {
+        } else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu)) {
             component = UserConstants.INNER_LINK;
-        }
-        else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu))
-        {
+        } else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu)) {
             component = UserConstants.PARENT_VIEW;
         }
         return component;
@@ -734,8 +677,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param menu 菜单信息
      * @return 结果
      */
-    public boolean isMenuFrame(SysMenu menu)
-    {
+    public boolean isMenuFrame(SysMenu menu) {
         return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType())
                 && menu.getIsFrame().equals(UserConstants.NO_FRAME);
     }
@@ -746,8 +688,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param menu 菜单信息
      * @return 结果
      */
-    public boolean isInnerLink(SysMenu menu)
-    {
+    public boolean isInnerLink(SysMenu menu) {
         return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS);
     }
 
@@ -757,8 +698,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param menu 菜单信息
      * @return 结果
      */
-    public boolean isParentView(SysMenu menu)
-    {
+    public boolean isParentView(SysMenu menu) {
         return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType());
     }
 
@@ -769,15 +709,12 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param parentId 传入的父节点ID
      * @return String
      */
-    public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId)
-    {
+    public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId) {
         List<SysMenu> returnList = new ArrayList<SysMenu>();
-        for (Iterator<SysMenu> iterator = list.iterator(); iterator.hasNext();)
-        {
+        for (Iterator<SysMenu> iterator = list.iterator(); iterator.hasNext(); ) {
             SysMenu t = (SysMenu) iterator.next();
             // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
-            if (t.getParentId() == parentId)
-            {
+            if (t.getParentId() == parentId) {
                 recursionFn(list, t);
                 returnList.add(t);
             }
@@ -791,15 +728,12 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param list
      * @param t
      */
-    private void recursionFn(List<SysMenu> list, SysMenu t)
-    {
+    private void recursionFn(List<SysMenu> list, SysMenu t) {
         // 得到子节点列表
         List<SysMenu> childList = getChildList(list, t);
         t.setChildren(childList);
-        for (SysMenu tChild : childList)
-        {
-            if (hasChild(list, tChild))
-            {
+        for (SysMenu tChild : childList) {
+            if (hasChild(list, tChild)) {
                 recursionFn(list, tChild);
             }
         }
@@ -811,15 +745,12 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param list
      * @param t
      */
-    private void recursionMobileFn(List<SysMobileMenu> list, SysMobileMenu t)
-    {
+    private void recursionMobileFn(List<SysMobileMenu> list, SysMobileMenu t) {
         // 得到子节点列表
         List<SysMobileMenu> childList = getChildMobileList(list, t);
         t.setChildren(childList);
-        for (SysMobileMenu tChild : childList)
-        {
-            if (hasMobileChild(list, tChild))
-            {
+        for (SysMobileMenu tChild : childList) {
+            if (hasMobileChild(list, tChild)) {
                 recursionMobileFn(list, tChild);
             }
         }
@@ -828,15 +759,12 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
     /**
      * 得到子节点列表
      */
-    private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t)
-    {
+    private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t) {
         List<SysMenu> tlist = new ArrayList<SysMenu>();
         Iterator<SysMenu> it = list.iterator();
-        while (it.hasNext())
-        {
+        while (it.hasNext()) {
             SysMenu n = (SysMenu) it.next();
-            if (n.getParentId().longValue() == t.getMenuId().longValue())
-            {
+            if (n.getParentId().longValue() == t.getMenuId().longValue()) {
                 tlist.add(n);
             }
         }
@@ -846,15 +774,12 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
     /**
      * 得到移动端子节点列表
      */
-    private List<SysMobileMenu> getChildMobileList(List<SysMobileMenu> list, SysMobileMenu t)
-    {
+    private List<SysMobileMenu> getChildMobileList(List<SysMobileMenu> list, SysMobileMenu t) {
         List<SysMobileMenu> tlist = new ArrayList<SysMobileMenu>();
         Iterator<SysMobileMenu> it = list.iterator();
-        while (it.hasNext())
-        {
+        while (it.hasNext()) {
             SysMobileMenu n = (SysMobileMenu) it.next();
-            if (n.getParentId().longValue() == t.getMenuId())
-            {
+            if (n.getParentId().longValue() == t.getMenuId()) {
                 tlist.add(n);
             }
         }
@@ -864,30 +789,27 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
     /**
      * 判断是否有子节点
      */
-    private boolean hasChild(List<SysMenu> list, SysMenu t)
-    {
+    private boolean hasChild(List<SysMenu> list, SysMenu t) {
         return getChildList(list, t).size() > 0 ? true : false;
     }
 
     /**
      * 判断移动端是否有子节点
      */
-    private boolean hasMobileChild(List<SysMobileMenu> list, SysMobileMenu t)
-    {
+    private boolean hasMobileChild(List<SysMobileMenu> list, SysMobileMenu t) {
         return getChildMobileList(list, t).size() > 0 ? true : false;
     }
 
     @Override
-    public List<TenantPlatformMenuVo> selectRolePlatformMenu()
-    {
+    public List<TenantPlatformMenuVo> selectRolePlatformMenu() {
         List<TenantPlatformMenuVo> list1 = new ArrayList<>();
         List<SysPlatformVo> list = sysPlatformMapper.getTenantPlatformList(SecurityUtils.getTenantId());
-        if (CollectionUtils.isNotEmpty(list)){
-            for(int i=0;i<list.size();i++){
+        if (CollectionUtils.isNotEmpty(list)) {
+            for (int i = 0; i < list.size(); i++) {
                 TenantPlatformMenuVo tenantPlatformMenuVo = new TenantPlatformMenuVo();
                 tenantPlatformMenuVo.setId(list.get(i).getId());
                 tenantPlatformMenuVo.setLabel(list.get(i).getPlatformName());
-                List<SysMenu> menus = baseMapper.getTenantPlatformMenuList(SecurityUtils.getTenantId(),list.get(i).getId());
+                List<SysMenu> menus = baseMapper.getTenantPlatformMenuList(SecurityUtils.getTenantId(), list.get(i).getId());
                 tenantPlatformMenuVo.setChildren(this.buildMenuTreeSelect(menus));
                 list1.add(tenantPlatformMenuVo);
             }

+ 1 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysMobileMenuServiceImpl.java

@@ -238,7 +238,7 @@ public class SysMobileMenuServiceImpl extends AbstractCrudService<SysMobileMenuM
         }
         else
         {
-            menus = sysMobileMenuMapper.selectMenuTreeByUserId(userId);
+            menus = sysMobileMenuMapper.selectMenuTreeByUserId1(userId,SecurityUtils.getTenantId());
         }
         return getChildPerms(menus, 0);
     }

+ 71 - 31
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysNoticeServiceImpl.java

@@ -1,111 +1,151 @@
 package com.usky.system.service.impl;
 
 
-import com.google.gson.JsonObject;
-import com.usky.common.core.bean.ApiResult;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.usky.common.core.exception.BusinessException;
 import com.usky.common.mybatis.core.AbstractCrudService;
+import com.usky.common.security.utils.SecurityUtils;
+import com.usky.system.domain.MceRequestVO;
 import com.usky.system.domain.SysNotice;
+import com.usky.system.domain.SysUser;
 import com.usky.system.mapper.SysNoticeMapper;
+import com.usky.system.mapper.SysUserMapper;
 import com.usky.system.service.ISysNoticeService;
 import com.usky.system.service.MceReceiveService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.util.HashMap;
+import java.util.Arrays;
 import java.util.List;
-import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 公告 服务层实现
- * 
+ *
  * @author ruoyi
  */
 @Service
-public class SysNoticeServiceImpl extends AbstractCrudService<SysNoticeMapper, SysNotice> implements ISysNoticeService
-{
+public class SysNoticeServiceImpl extends AbstractCrudService<SysNoticeMapper, SysNotice> implements ISysNoticeService {
     @Autowired
     private SysNoticeMapper noticeMapper;
 
     @Autowired
     private MceReceiveService mceReceiveService;
 
+    @Autowired
+    private SysUserMapper sysUserMapper;
+
     /**
      * 查询公告信息
-     * 
+     *
      * @param noticeId 公告ID
      * @return 公告信息
      */
     @Override
-    public SysNotice selectNoticeById(Long noticeId)
-    {
+    public SysNotice selectNoticeById(Long noticeId) {
         return noticeMapper.selectNoticeById(noticeId);
     }
 
     /**
      * 查询公告列表
-     * 
+     *
      * @param notice 公告信息
      * @return 公告集合
      */
     @Override
-    public List<SysNotice> selectNoticeList(SysNotice notice)
-    {
+    public List<SysNotice> selectNoticeList(SysNotice notice) {
+        notice.setTenantId(SecurityUtils.getTenantId());
+        String deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId().toString();
+        notice.setDeptId(deptId);
         return noticeMapper.selectNoticeList(notice);
     }
 
     /**
      * 新增公告
-     * 
+     *
      * @param notice 公告信息
      * @return 结果
      */
     @Override
-    public int insertNotice(SysNotice notice)
-    {
+    public int insertNotice(SysNotice notice) {
+        notice.setTenantId(SecurityUtils.getTenantId());
         noticeMapper.insertNotice(notice);
         int insertId = notice.getNoticeId();
-        JsonObject jsonObject = new JsonObject();
-        jsonObject.addProperty("infoTitle", notice.getNoticeTitle());
-        jsonObject.addProperty("infoContent",notice.getNoticeContent());
-        jsonObject.addProperty("infoType",1);
-        jsonObject.addProperty("id",insertId);
-        mceReceiveService.add(jsonObject.toString());
+
+        String deptId = notice.getDeptId();
+        List<Long> deptIds = Arrays.stream(deptId.split(",")).map(Long::parseLong).collect(Collectors.toList());
+        List<Long> usersIds = sysUserMapper.selectList(Wrappers.lambdaQuery(SysUser.class).select(SysUser::getUserId).in(SysUser::getDeptId, deptIds)).stream().map(SysUser::getUserId).collect(Collectors.toList());
+
+        if (!deptIds.isEmpty()) {
+            sendNotice(notice.getNoticeTitle(), insertId, notice.getCreateBy(), usersIds);
+        }
+
         return insertId;
     }
 
+    /**
+     * 发送消息
+     * @param infoContent 消息内容
+     * @param id 通知公告id
+     * @param userName 发布人
+     * @param userIds 接收人
+     */
+    private void sendNotice(String infoContent, Integer id, String userName, List<Long> userIds) {
+
+        // JSONObject jsonObject = new JSONObject();
+        // jsonObject.put("infoTitle", "通知公告");
+        // jsonObject.put("infoContent", infoContent);
+        // jsonObject.put("infoType", 1);
+        // jsonObject.put("id", id);
+        // jsonObject.put("userName", userName);
+        // jsonObject.put("userIds", userIds);
+        MceRequestVO mceRequestVO = new MceRequestVO();
+        mceRequestVO.setInfoTitle("通知公告");
+        mceRequestVO.setInfoContent(infoContent);
+        mceRequestVO.setInfoType("1");
+        mceRequestVO.setId(id);
+        mceRequestVO.setUserName(userName);
+        mceRequestVO.setUserIds(userIds);
+        mceRequestVO.setRealName(SecurityUtils.getLoginUser().getSysUser().getNickName());
+        try {
+            // mceReceiveService.add(jsonObject.toString());
+            mceReceiveService.addMceReceive(mceRequestVO);
+        } catch (Exception e) {
+            log.error(String.format("公告:%d,消息发送失败:%s", id, e.getMessage()));
+        }
+    }
+
     /**
      * 修改公告
-     * 
+     *
      * @param notice 公告信息
      * @return 结果
      */
     @Override
-    public int updateNotice(SysNotice notice)
-    {
+    public int updateNotice(SysNotice notice) {
         return noticeMapper.updateNotice(notice);
     }
 
     /**
      * 删除公告对象
-     * 
+     *
      * @param noticeId 公告ID
      * @return 结果
      */
     @Override
-    public int deleteNoticeById(Long noticeId)
-    {
+    public int deleteNoticeById(Long noticeId) {
         return noticeMapper.deleteNoticeById(noticeId);
     }
 
     /**
      * 批量删除公告信息
-     * 
+     *
      * @param noticeIds 需要删除的公告ID
      * @return 结果
      */
     @Override
-    public int deleteNoticeByIds(Long[] noticeIds)
-    {
+    public int deleteNoticeByIds(Long[] noticeIds) {
         return noticeMapper.deleteNoticeByIds(noticeIds);
     }
 }

+ 129 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysPersonServiceImpl.java

@@ -4,16 +4,27 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.usky.common.mybatis.core.AbstractCrudService;
-import com.usky.common.security.utils.SecurityUtils;
+import com.usky.system.domain.SysDept;
 import com.usky.system.domain.SysPerson;
+import com.usky.system.domain.SysPost;
+import com.usky.system.domain.SysUser;
 import com.usky.system.domain.SysUserPerson;
 import com.usky.system.mapper.SysPersonMapper;
+import com.usky.system.service.ISysDeptService;
+import com.usky.system.service.ISysPostService;
+import com.usky.system.service.ISysUserService;
 import com.usky.system.service.SysPersonService;
 import com.usky.system.service.SysUserPersonService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -27,6 +38,12 @@ import java.util.List;
 public class SysPersonServiceImpl extends AbstractCrudService<SysPersonMapper, SysPerson> implements SysPersonService {
     @Autowired
     private SysUserPersonService sysUserPersonService;
+    @Autowired
+    private ISysUserService sysUserService;
+    @Autowired
+    private ISysDeptService sysDeptService;
+    @Autowired
+    private ISysPostService sysPostService;
 
     @Override
     public SysPerson getsysPerson(Long userid) {
@@ -38,7 +55,118 @@ public class SysPersonServiceImpl extends AbstractCrudService<SysPersonMapper, S
             LambdaQueryWrapper<SysPerson> query = Wrappers.lambdaQuery();
             query.eq(SysPerson::getId, userPersonList.get(0).getPersonId());
             sysPerson = this.getOne(query);
+            if (sysPerson != null) {
+                fillDeptAndPostFromUser(sysPerson, userid);
+            }
         }
         return sysPerson;
     }
+
+    @Override
+    public void fillDeptAndPostFromUser(SysPerson person, Long userId) {
+        if (person == null) {
+            return;
+        }
+        if (userId == null) {
+            clearPersonDeptPost(person);
+            return;
+        }
+        SysUser user = sysUserService.selectUserById(userId);
+        if (user == null) {
+            clearPersonDeptPost(person);
+            return;
+        }
+        person.setDeptId(user.getDeptId());
+        if (user.getDeptId() != null) {
+            SysDept dept = sysDeptService.selectDeptById(user.getDeptId());
+            person.setDeptName(dept != null ? dept.getDeptName() : null);
+        } else {
+            person.setDeptName(null);
+        }
+        List<Integer> postIds = sysPostService.selectPostListByUserId(userId);
+        if (postIds == null || postIds.isEmpty()) {
+            person.setPostId(null);
+            person.setPostName(null);
+        } else {
+            Long pid = postIds.get(0).longValue();
+            person.setPostId(pid);
+            SysPost post = sysPostService.selectPostById(pid);
+            person.setPostName(post != null ? post.getPostName() : null);
+        }
+    }
+
+    @Override
+    public void fillDeptAndPostForList(List<SysPerson> list, Map<Integer, Long> personIdToUserId) {
+        if (list == null || list.isEmpty()) {
+            return;
+        }
+        if (personIdToUserId == null || personIdToUserId.isEmpty()) {
+            list.forEach(this::clearPersonDeptPost);
+            return;
+        }
+        Set<Long> userIds = new HashSet<>(personIdToUserId.values());
+        if (userIds.isEmpty()) {
+            list.forEach(this::clearPersonDeptPost);
+            return;
+        }
+        List<SysUser> users = sysUserService.list(Wrappers.<SysUser>lambdaQuery().in(SysUser::getUserId, userIds));
+        Map<Long, SysUser> userById = users.stream()
+                .collect(Collectors.toMap(SysUser::getUserId, u -> u, (a, b) -> a));
+
+        List<Long> deptIdList = users.stream()
+                .map(SysUser::getDeptId)
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+        Map<Long, String> deptNameMap = new HashMap<>();
+        if (!deptIdList.isEmpty()) {
+            List<SysDept> depts = sysDeptService.selectDeptByIds(deptIdList);
+            if (depts != null) {
+                for (SysDept d : depts) {
+                    deptNameMap.put(d.getDeptId(), d.getDeptName());
+                }
+            }
+        }
+
+        Map<Long, Long> userFirstPostId = new HashMap<>();
+        for (Long uid : userIds) {
+            List<Integer> pids = sysPostService.selectPostListByUserId(uid);
+            if (pids != null && !pids.isEmpty()) {
+                userFirstPostId.put(uid, pids.get(0).longValue());
+            }
+        }
+        Set<Long> postIdSet = new HashSet<>(userFirstPostId.values());
+        Map<Long, String> postNameMap = new HashMap<>();
+        for (Long pid : postIdSet) {
+            SysPost post = sysPostService.selectPostById(pid);
+            if (post != null) {
+                postNameMap.put(pid, post.getPostName());
+            }
+        }
+
+        for (SysPerson p : list) {
+            Long uid = personIdToUserId.get(p.getId());
+            if (uid == null) {
+                clearPersonDeptPost(p);
+                continue;
+            }
+            SysUser u = userById.get(uid);
+            if (u == null) {
+                clearPersonDeptPost(p);
+                continue;
+            }
+            p.setDeptId(u.getDeptId());
+            p.setDeptName(u.getDeptId() != null ? deptNameMap.get(u.getDeptId()) : null);
+            Long pid = userFirstPostId.get(uid);
+            p.setPostId(pid);
+            p.setPostName(pid != null ? postNameMap.get(pid) : null);
+        }
+    }
+
+    private void clearPersonDeptPost(SysPerson person) {
+        person.setDeptId(null);
+        person.setDeptName(null);
+        person.setPostId(null);
+        person.setPostName(null);
+    }
 }

+ 17 - 7
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysPlatformMenuServiceImpl.java

@@ -1,14 +1,12 @@
 package com.usky.system.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.usky.common.mybatis.core.AbstractCrudService;
-import com.usky.system.domain.SysMenu;
-import com.usky.system.domain.SysMobileMenu;
-import com.usky.system.domain.SysPlatformMenu;
-import com.usky.system.domain.SysTenantMenu;
-import com.usky.system.domain.SysMobileTenantMenu;
+import com.usky.system.domain.*;
 import com.usky.system.mapper.SysPlatformMenuMapper;
+import com.usky.system.mapper.SysTenantPlatformMapper;
 import com.usky.system.service.SysMobileTenantMenuService;
 import com.usky.system.service.SysPlatformMenuService;
 import com.usky.system.service.SysTenantMenuService;
@@ -36,6 +34,9 @@ public class SysPlatformMenuServiceImpl extends AbstractCrudService<SysPlatformM
     @Autowired
     private SysTenantMenuService sysTenantMenuService;
 
+    @Autowired
+    private SysTenantPlatformMapper sysTenantPlatformMapper;
+
     @Autowired
     private SysMobileTenantMenuService sysMobileTenantMenuService;
 
@@ -43,8 +44,17 @@ public class SysPlatformMenuServiceImpl extends AbstractCrudService<SysPlatformM
         return baseMapper.getMenuList(platformId, null);
     }
 
-    public List<SysMobileMenu> getMobilePlatformMenuList(Integer platformId){
-        return baseMapper.getMobileMenuList(platformId, null);
+    public List<SysMobileMenu> getMobilePlatformMenuList(Integer tenantId){
+        LambdaQueryWrapper<SysTenantPlatform> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(SysTenantPlatform::getTenantId,tenantId);
+        List<SysTenantPlatform> list = sysTenantPlatformMapper.selectList(queryWrapper);
+        List<Integer> platformIds = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(list)) {
+            for (int j = 0; j < list.size(); j++) {
+                platformIds.add(list.get(j).getPlatformId());
+            }
+        }
+        return baseMapper.getMobileMenuList(platformIds, null);
     }
 
     public Long[] selectPlatformMenu(Integer tenantId){

+ 2 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysPlatformServiceImpl.java

@@ -98,6 +98,8 @@ public class SysPlatformServiceImpl extends AbstractCrudService<SysPlatformMappe
         SysPlatform sysPlatform = new SysPlatform();
         sysPlatform.setPlatformName(platformMenuVo.getPlatformName());
         sysPlatform.setIcon(platformMenuVo.getIcon());
+        sysPlatform.setOrderNum(platformMenuVo.getOrderNum());
+        sysPlatform.setPlatformType(platformMenuVo.getPlatformType());
         if (platformMenuVo.getPlatformId().intValue() == 0) {
             sysPlatform.setCreateBy(SecurityUtils.getUsername());
             sysPlatform.setCreateTime(LocalDateTime.now());

+ 7 - 4
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysRoleServiceImpl.java

@@ -125,9 +125,9 @@ public class SysRoleServiceImpl extends AbstractCrudService<SysRoleMapper, SysRo
      * @return 选中角色ID列表
      */
     @Override
-    public List<Integer> selectRoleListByUserId(Long userId)
+    public List<Integer> selectRoleListByUserId(Long userId, Integer tenantId)
     {
-        return roleMapper.selectRoleListByUserId(userId);
+        return roleMapper.selectRoleListByUserId(userId,tenantId);
     }
 
     /**
@@ -201,7 +201,7 @@ public class SysRoleServiceImpl extends AbstractCrudService<SysRoleMapper, SysRo
     @Override
     public int countUserRoleByRoleId(Long roleId)
     {
-        return userRoleMapper.countUserRoleByRoleId(roleId);
+        return userRoleMapper.countUserRoleByRoleId(roleId,SecurityUtils.getTenantId());
     }
 
     /**
@@ -395,7 +395,8 @@ public class SysRoleServiceImpl extends AbstractCrudService<SysRoleMapper, SysRo
     @Override
     public int deleteAuthUsers(Long roleId, Long[] userIds)
     {
-        return userRoleMapper.deleteUserRoleInfos(roleId, userIds);
+        Integer tenantId = SecurityUtils.getTenantId();
+        return userRoleMapper.deleteUserRoleInfos(roleId, userIds, tenantId);
     }
 
     /**
@@ -410,11 +411,13 @@ public class SysRoleServiceImpl extends AbstractCrudService<SysRoleMapper, SysRo
     {
         // 新增用户与角色管理
         List<SysUserRole> list = new ArrayList<SysUserRole>();
+        Integer tenantId = SecurityUtils.getTenantId();
         for (Long userId : userIds)
         {
             SysUserRole ur = new SysUserRole();
             ur.setUserId(userId);
             ur.setRoleId(roleId);
+            ur.setTenantId(tenantId);
             list.add(ur);
         }
         return userRoleMapper.batchUserRole(list);

+ 2 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysUserOnlineServiceImpl.java

@@ -90,6 +90,8 @@ public class SysUserOnlineServiceImpl implements ISysUserOnlineService
         sysUserOnline.setIpaddr(user.getIpaddr());
         sysUserOnline.setLoginTime(user.getLoginTime());
         sysUserOnline.setExpireTime(user.getExpireTime());
+        sysUserOnline.setOs(user.getOs());
+        sysUserOnline.setBrowser(user.getBrowser());
         return sysUserOnline;
     }
 }

+ 35 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysUserPersonServiceImpl.java

@@ -1,11 +1,17 @@
 package com.usky.system.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.usky.common.core.exception.BusinessException;
+import com.usky.common.security.utils.SecurityUtils;
 import com.usky.system.domain.SysUserPerson;
 import com.usky.system.mapper.SysUserPersonMapper;
 import com.usky.system.service.SysUserPersonService;
 import com.usky.common.mybatis.core.AbstractCrudService;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.Objects;
+
 /**
  * <p>
  * 用户人员关联 服务实现类
@@ -17,4 +23,33 @@ import org.springframework.stereotype.Service;
 @Service
 public class SysUserPersonServiceImpl extends AbstractCrudService<SysUserPersonMapper, SysUserPerson> implements SysUserPersonService {
 
+    @Autowired
+    private SysUserPersonMapper sysUserPersonMapper;
+
+    @Override
+    public Integer upIsLoginNotify(Long userId, Integer isLoginNotify) {
+
+        // 判断 isLoginNotify 是否为 0 或 1
+        if (isLoginNotify != 0 && isLoginNotify != 1) {
+            throw new BusinessException("参数设置错误");
+        }
+        // 判断要修改的用户是否为登录用户
+        if (!Objects.equals(userId, SecurityUtils.getUserId())) {
+            throw new BusinessException("你不能修改非本人的登录通知设置!");
+        }
+
+        // 更新登录通知设置
+        LambdaUpdateWrapper<SysUserPerson> wrapper = new LambdaUpdateWrapper<>();
+        wrapper.eq(SysUserPerson::getUserId, userId)
+                .set(SysUserPerson::getIsLoginNotify, isLoginNotify);
+        int result = sysUserPersonMapper.update(null, wrapper);
+
+        //  更新失败
+        if (result <= 0) {
+            log.error("用户:{},操作登录通知开关操作失败!");
+            throw new BusinessException("登录通知开关操作失败!请重试");
+        }
+
+        return result;
+    }
 }

Неке датотеке нису приказане због велике количине промена