Compare commits

...

213 Commits
master ... zyj

Author SHA1 Message Date
sj a27b0c8deb 修复导出 2 years ago
sj c424bc0ca8 优化微信用户优化名 2 years ago
sj 010132f237 优化商品分类及子集查询 2 years ago
sj 91188fe1a0 优化优惠券显示并运行最小优惠券设置为无门槛 2 years ago
sj a5cdf202f1 下单时候自动选择优惠金额最大的优惠券 2 years ago
sj a30fb508de 修复优惠券被删除是用户券包报错 2 years ago
sj aa792a10b1 增加品牌搜索 2 years ago
sj bcdd99eb4a 增加商品id搜索,修复规格太长时,数据库报错 2 years ago
sj 50c1f73901 优惠券增加商品图片展示 2 years ago
sj 0d93550e43 增加拼团及砍价活动通知 2 years ago
sj 3b05b235bc 优化榜单排序及定时任务 2 years ago
sj 2fa9950933 修复榜单绑定商品删除问题 2 years ago
sj 76bd360e92 商品修改 2 years ago
sj f459579768 修改榜单页面 2 years ago
sj cb388c8e85 增加品牌馆滚动条 2 years ago
sj b26c158c84 修复专家排序及用户消息修改 2 years ago
sj 26f6a38c6b 领券增加消息推送,修复首页图 2 years ago
sj e80ff782e7 热榜增加时间字段配置 2 years ago
sj 44110bd059 商品增加无理由退款等配置 2 years ago
sj 9bc5869abd 修改订单支付及退款消息通知 2 years ago
sj 2b25c63f4e 品牌排序修改及商品删除下架时判断 2 years ago
sj 5f259398a2 修复订单生成 2 years ago
sj ddc1cddcb9 商品增加商品参数字段 2 years ago
sj a0a6040437 评测去除多余字段 2 years ago
sj f46f56e5b0 微信登录修复及品牌评测优化 2 years ago
sj b6a9c87e2a 会员等级增加成长值 2 years ago
sj ddb28dc5c8 修复优惠券部分 2 years ago
1304317391@qq.com 92e2c99b89 修复依赖错误 2 years ago
1304317391@qq.com a6cf439160 修复依赖错误 2 years ago
sj b0a0785501 优化流程 2 years ago
sj a22fa10cb8 增加评测收藏及订单支付成功群机器人 2 years ago
sj 200346ee71 修复物流状态查询 2 years ago
sj efa1a331bb 修复优惠券发布权限 2 years ago
sj 49d46c391a 修复专家和评测模块 2 years ago
Loki 69c9c00c16 👎 删除代码 2 years ago
sj 226518b3a4 跳过maven测试 2 years ago
sj e265d9620b 合并眼界甄选 2 years ago
sj 4180aa5567 修复因购物车改变引起的订单流程 2 years ago
sj e7bc4f312a 增加商品热榜设置,并购物车按品牌区分 2 years ago
sj 6d15e1fa32 修复小程序登录问题 2 years ago
sj aa8a171ccc 修复营销活动及会员等级 2 years ago
sj 6e7adc20cb 修改评测获取方法 2 years ago
sj 5bb10fe988 增加小程序请求商品词条接口 2 years ago
sj 37acc6ebae 修复小程序请求商品接口 2 years ago
sj ac911e41e1 增加小程序获取评测列表接口 2 years ago
sj 4f69fb5d3a 增加评测模块 2 years ago
sj 61eb0c7177 增加小程序端的专家和品牌查询接口 2 years ago
sj 1f07dde9d2 优惠券时间限制修改 2 years ago
sj 822d5e8207 完善专家模块 2 years ago
sj 0125a6598c 商品品牌修改 2 years ago
sj 173a6145af 修复商品品牌 2 years ago
sj 8d66f53be5 更改配置 2 years ago
Loki 0c83d79684 增加默认主页 修改线上地址 2 years ago
Loki 91741b3224 修复缓存 2 years ago
Loki 4a7e7c2595 菜单增加隐藏 2 years ago
Loki 49c3e34b23 新增租户初始化切面事件 2 years ago
Loki 4686861ad2 准备新租户创建切面 用于同步一些比如七牛,默认轮播,店铺设置等。 2 years ago
zhanyunjiu 10a6b8fc57 报错修复 2 years ago
zhanyunjiu 92a7db0031 dubbo远程调用erp异常处理 2 years ago
zhanyunjiu 2072a3cbc9 处理dubbo没有provider 2 years ago
zhanyunjiu c903ff31e3 dubbo注册到nacos 2 years ago
zhanyunjiu 8f96db1483 消息退送信息 2 years ago
zhanyunjiu 13323608a9 项目、任务 没有成员选择 暂时不发送消息 2 years ago
zhanyunjiu 6a88008a51 dubbo 2 years ago
zhanyunjiu 0b96c77838 项目定时任务注释 2 years ago
zhanyunjiu a2e22e1478 提交代码 2 years ago
zhanyunjiu 18928deb2e 修改流程 3 years ago
zhanyunjiu e44e0e662e 流程优化 3 years ago
zhanyunjiu eaf7faa12b 新增、修改取消任务状态选择,定时检查任务状态 3 years ago
zhanyunjiu 6b2c8ec70c 流程优化 3 years ago
zhanyunjiu 126251e113 优化 3 years ago
zhanyunjiu 04814bbd89 实体类字段优化 3 years ago
zhanyunjiu dc52c30581 业务流程调整 3 years ago
zhanyunjiu 32250adc85 活动新增 工时、采收数量、参与人、执行时间 4个字段 3 years ago
zhanyunjiu afcecc3c73 项目新增字段 , 3 years ago
zhanyunjiu 333c63bb62 采收 作物 同步到ERP 3 years ago
Loki bc6c88d89d 增加出入拦截 3 years ago
Loki f1b8d3b47d 增加dubbo配置和调用案例 3 years ago
zhanyunjiu 4453f13b37 活动 新增作物记录 3 years ago
zhanyunjiu 53316b0b71 权限 3 years ago
zhanyunjiu 1697bd8fef 资源保管人 3 years ago
zhanyunjiu f034ce1b1a 任务创建人和负责人才可以新增修改活动 3 years ago
zhanyunjiu 21a3f1e166 优化提示 3 years ago
zhanyunjiu a3555407a1 问题修复 3 years ago
zhanyunjiu 711bf01e62 删除无效引用 3 years ago
WIN-IDGBLFHC1K6\Administrator 27ba31bf4f 任务 和 项目 actions权限 3 years ago
WIN-IDGBLFHC1K6\Administrator a71bc7d6b2 统计图优化 3 years ago
WIN-IDGBLFHC1K6\Administrator d4c7fa2fc1 问题修复 3 years ago
WIN-IDGBLFHC1K6\Administrator ab09d4a524 资源 占用 库存扣减 3 years ago
WIN-IDGBLFHC1K6\Administrator 8ec6f213d4 一个田区不可以同事被两个进行中的项目占用, 项目更改完成前提下面任务都完成 3 years ago
WIN-IDGBLFHC1K6\Administrator bebca3004d 区域新增 占用字段 3 years ago
WIN-IDGBLFHC1K6\Administrator 103837e0f3 任务通知消息 新增内容 3 years ago
WIN-IDGBLFHC1K6\Administrator 4d011a2a51 问题修复 3 years ago
WIN-IDGBLFHC1K6\Administrator 4011874184 农场 任务列表 根据projectId显示任务所在日期 3 years ago
Loki cd55670218 部分权限 3 years ago
小久哥 59c86e3aca 日期有任务的显示 3 years ago
小久哥 f1232e7981 Merge branch 'zyh' into zyj 3 years ago
Loki 4d7af16b05 给项目增加权限字典,用于小程序展示按钮。 3 years ago
小久哥 510fb3814f 微信登录 3 years ago
小久哥 8d89747fe4 消息 成员同步 3 years ago
小久哥 6063523f30 后台项目搜索 3 years ago
小久哥 e9fe435aef 后台任务列表搜索 3 years ago
小久哥 1a88fca5b6 企业微信小程序消息卡片 3 years ago
小久哥 658663c61a 消息 及bug修复 3 years ago
小久哥 e8a5668da4 消息发送 3 years ago
小久哥 7380a37431 修复 错误 3 years ago
小久哥 cc80a97dba Merge branch 'zyh' into zyj 3 years ago
小久哥 41dd169a97 修改区域 3 years ago
Loki 5dd48e50a0 修改farmmsg注解 3 years ago
Loki f77d753264 fix log 3 years ago
小久哥 fe84dea084 小程序权限访问 3 years ago
Loki 8fc86bebff dict 3 years ago
小久哥 73a8bf4a35 优化农场日志记录 3 years ago
小久哥 d662c8dec1 修复bug 3 years ago
小久哥 4e8c2178ba 项目、任务查看未删除的 3 years ago
小久哥 9e3968cbda 接口新增:查看任务详情 显示活动时长 3 years ago
小久哥 44fee2cf6e 接口:根据taskId查询累计的任务时长 3 years ago
小久哥 13610a7bb6 项目状态枚举 3 years ago
小久哥 f29fa0b508 task新加 unit单位字段,删除不用的projectId 3 years ago
小久哥 79b5eb0836 我参与项目 排序 3 years ago
小久哥 b36951a4fb 时区 3 years ago
小久哥 97901204b7 日志信息和项目 倒序 3 years ago
小久哥 c43bf99629 农场 project/resource/resourceType/task/taskCate/workHour 假删除 3 years ago
小久哥 0ea7bf55b3 农场 area、crop、crop_record、discuss、event 假删除 3 years ago
小久哥 c0e6c171a6 删除无效 任务方法 3 years ago
小久哥 b75d12cb83 优化代码 3 years ago
小久哥 9bc848dd96 企业用户 注册 系统用户 并给权限 3 years ago
小久哥 d18238dbab 企业微信同步 3 years ago
小久哥 63761c9d3a 我的项目 3 years ago
小久哥 ca489012f5 农场日志信息 3 years ago
小久哥 14439a203b 项目 我参与的 3 years ago
小久哥 92e340ae09 权限 3 years ago
小久哥 3de354c111 cpuser表不存在的用户 用test登录 3 years ago
小久哥 e67f42f033 账号密码错误修复 3 years ago
小久哥 8589fd38e0 删除wxcp.farmSecret 3 years ago
小久哥 99eb3bcb7f 添加agentId 3 years ago
小久哥 09eb23318e 删除微信code登录 3 years ago
小久哥 f0084754ca 查看我的项目, 修改配置 3 years ago
小久哥 cc0c7f374e 修改配置 3 years ago
小久哥 f42644e836 修復錯誤 3 years ago
小久哥 d4dc0a25c7 修改 3 years ago
小久哥 b4fc7db6d0 统计接口, prod-erp 3 years ago
小久哥 69a53a5f2a mysql 3 years ago
小久哥 84c53c545f prod mysql name 3 years ago
小久哥 cbfec821da pro 3 years ago
小久哥 d26d0a4ae5 pro mysql ip 3 years ago
小久哥 6d9be42340 pro 数据库 3 years ago
小久哥 71bc4b45dc cj 3 years ago
小久哥 35abd199bc redis 3 years ago
小久哥 e7cc44c502 mysql 驱动 3 years ago
小久哥 d96de82d5f mysql 3 years ago
小久哥 6745fecc6f mysql 3 years ago
小久哥 b188e3dcb9 mysql pom 3 years ago
小久哥 ccada6c25d mysql驱动 3 years ago
小久哥 83c78c96dd mysql 密码 3 years ago
小久哥 2bf333cc90 mysql 3 years ago
小久哥 f51ae91df0 prod.mysql 3 years ago
小久哥 51a987670c prod,redis 3 years ago
小久哥 dff81402bb 活动结构更改 3 years ago
小久哥 672f0e7514 项目、任务草稿 3 years ago
小久哥 a3ff0accb6 项目筛选 3 years ago
小久哥 c14f984d89 Merge branch 'zyh' into zyj 3 years ago
小久哥 8503e7a69f 优化 3 years ago
Loki aceb2811ef 删除多数据源配置 3 years ago
小久哥 e3843fdad8 id int改long 3 years ago
小久哥 49c4ba8652 Merge branch 'zyh' into zyj 3 years ago
小久哥 e80a44320a 小程序 首页 项目 完成任务最新一条 3 years ago
小久哥 e3098cf8d9 登录返回工时 3 years ago
Loki 7a6f346404 统计接口 3 years ago
小久哥 612e4a428c 实体字段改变 3 years ago
小久哥 fbfaea3926 test删除resouce 3 years ago
小久哥 7ee83372b6 删除项目 resouce字段 3 years ago
小久哥 db52846a6c 删除项目 resouce字段 3 years ago
小久哥 8105b62737 Merge branch 'zyh' into zyj 3 years ago
小久哥 a2d00e3ab7 项目更改 3 years ago
Loki 09b9e92585 任务活动接口-任务状态枚举 3 years ago
小久哥 243b9066cf 任务DO优化 3 years ago
小久哥 461e4e6457 Merge branch 'zyh' into zyj 3 years ago
小久哥 e4d90c4252 农场任务 新增区域 3 years ago
小久哥 4cead507ae 新增:区域二级 3 years ago
Loki e6b21e3a49 适配进销存接口 增加p6spy日志 3 years ago
小久哥 d434b2084f 优化任务 3 years ago
小久哥 c55aa8f97a 任务类型 3 years ago
Loki a059ab9e00 删除了服务端的admin-ui 3 years ago
小久哥 80e0289e4b Merge branch 'zyh' into zyj 3 years ago
小久哥 66489db865 工时 3 years ago
Loki 7a1f3c787f 增加任务分类 3 years ago
小久哥 0174e14455 项目 任务 3 years ago
Loki e01f90088f 修复进销存合并 3 years ago
小久哥 9f394d71a1 农场任务 3 years ago
小久哥 1273f011b4 登录返回信息 3 years ago
小久哥 67eb497114 农场项目 3 years ago
小久哥 54772ded8f Merge branch 'zyh' into zyj 3 years ago
小久哥 94eb1b7141 新增:erp、erp-spi 3 years ago
小久哥 7b742c1701 作物出入关联作物库存 3 years ago
Loki 2d23f468df 修改第三方登录 修改企业微信小程序登录 3 years ago
小久哥 d18ce96c45 新增:作物、作物出入记录 3 years ago
小久哥 04bed3ba3d wxcp配置 3 years ago
小久哥 70623c5712 Merge branch 'zyh' into zyj 3 years ago
Loki 73877d675a 测试微信登录 3 years ago
Loki e9d29ef2df 企业微信成员新增 3 years ago
Loki 186feb98da fix 3 years ago
Loki 4d3b8caf21 宝象购修复 3 years ago
Loki a89a69b145 基本完成 3 years ago
Loki 50fa31c6ad app端调整 3 years ago
Loki b1e3fabea3 页面和权限规则调整 3 years ago
小久哥 ac70ccf30f Merge branch 'zyh' into zyj 3 years ago
小久哥 211afafeaf 农场任务事件搜索 3 years ago
Loki 01ab4d2b4f 增加电商带吗 3 years ago
小久哥 1971f3031c 农场任务搜索实现 3 years ago
小久哥 a746c1be84 农场项目管理 搜索条件实现 3 years ago
小久哥 fba23a61e7 农场作业区域 3 years ago
小久哥 2ab2593f45 add redis config 3 years ago
  1. 3
      .gitignore
  2. 1
      bin/sync.sh
  3. 6
      package-lock.json
  4. 12
      pom.xml
  5. BIN
      poster.jpg
  6. BIN
      simsunb.ttf
  7. 5
      yudao-dependencies/pom.xml
  8. 6
      yudao-framework/yudao-common/pom.xml
  9. 126
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/ApiCode.java
  10. 59
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/YshopException.java
  11. 3
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/GlobalErrorCodeConstants.java
  12. 23
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/page/PageDTO.java
  13. 98
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/page/PageUtil.java
  14. 45
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/page/PageVO.java
  15. 231
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/ApiResult.java
  16. 4
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/PageParam.java
  17. 4
      yudao-framework/yudao-spring-boot-starter-biz-data-permission/pom.xml
  18. 19
      yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRule.java
  19. 2
      yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/service/DeptDataPermissionFrameworkService.java
  20. 4
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java
  21. 12
      yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/context/TenantContextHolder.java
  22. 31
      yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml
  23. 40
      yudao-framework/yudao-spring-boot-starter-biz-weixin/src/main/java/cn/iocoder/yudao/config/WxCpConfigure.java
  24. 42
      yudao-framework/yudao-spring-boot-starter-biz-weixin/src/main/java/cn/iocoder/yudao/config/WxMaConfiguration.java
  25. 3
      yudao-framework/yudao-spring-boot-starter-biz-weixin/src/main/resources/META-INF/spring.factories
  26. 2
      yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientTest.java
  27. 15
      yudao-framework/yudao-spring-boot-starter-flowable/pom.xml
  28. 69
      yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/JdbcStoreTypeConfiguration.java
  29. 3
      yudao-framework/yudao-spring-boot-starter-job/src/main/resources/META-INF/spring.factories
  30. 8
      yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml
  31. 102
      yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java
  32. 3
      yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseDO.java
  33. 39
      yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseDomain.java
  34. 90
      yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java
  35. 68
      yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/ListIntToListLongTypeHandler.java
  36. 28
      yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoRedisAutoConfiguration.java
  37. 2
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/SecurityProperties.java
  38. 6
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java
  39. 7
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
  40. 26
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/annotations/AuthCheck.java
  41. 7
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/MultiUserDetailsAuthenticationProvider.java
  42. 1
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JWTAuthenticationTokenFilter.java
  43. 6
      yudao-framework/yudao-spring-boot-starter-web/pom.xml
  44. 4
      yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java
  45. 95
      yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java
  46. 23
      yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java
  47. 13
      yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/doc/DbDocController.java
  48. 36
      yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/security/config/SecurityConfiguration.java
  49. 6
      yudao-module-infra/yudao-module-infra-impl/src/main/resources/mapper/test/TestDemoMapper.xml
  50. 2
      yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java
  51. 17
      yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/weixin/TestConfigure.java
  52. 10
      yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java
  53. 274
      yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImplTest.java
  54. 2
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
  55. 15
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/wxcp/WxCpMsgTypeEnum.java
  56. 5
      yudao-module-system/yudao-module-system-impl/pom.xml
  57. 100
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/CpUserController.java
  58. 44
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/dto/CpMessageDto.java
  59. 49
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/vo/CpUserBaseVO.java
  60. 14
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/vo/CpUserCreateReqVO.java
  61. 53
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/vo/CpUserExcelVO.java
  62. 52
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/vo/CpUserExportReqVO.java
  63. 54
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/vo/CpUserPageReqVO.java
  64. 19
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/vo/CpUserRespVO.java
  65. 18
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/vo/CpUserUpdateReqVO.java
  66. 102
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
  67. 15
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/param/WxCpLoginDto.java
  68. 4
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthLoginReqVO.java
  69. 5
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthLoginRespVO.java
  70. 3
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthMenuRespVO.java
  71. 2
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthSocialLogin2ReqVO.java
  72. 2
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuBaseVO.java
  73. 3
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserBaseVO.java
  74. 2
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java
  75. 37
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/CpUser/CpUserConvert.java
  76. 13
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java
  77. 2
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/user/UserConvert.java
  78. 67
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/CpUser/CpUserDO.java
  79. 2
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/MenuDO.java
  80. 4
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/UserRoleDO.java
  81. 5
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/AdminUserDO.java
  82. 50
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/CpUser/CpUserMapper.java
  83. 15
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictMapper.java
  84. 43
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dict/Dict.java
  85. 327
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dict/DictAspect.java
  86. 52
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dict/DictModel.java
  87. 4
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java
  88. 25
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/job/cpuser/CpWeixinUserSyncJob.java
  89. 79
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/CpUser/CpUserService.java
  90. 164
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/CpUser/CpUserServiceImpl.java
  91. 11
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java
  92. 19
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
  93. 3
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java
  94. 23
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java
  95. 10
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java
  96. 13
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java
  97. 6
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java
  98. 83
      yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
  99. 12
      yudao-module-system/yudao-module-system-impl/src/main/java/resources/mapper/CpUser/CpUserMapper.xml
  100. 17
      yudao-module-system/yudao-module-system-impl/src/main/java/resources/mapper/dict/DictMapper.xml
  101. Some files were not shown because too many files have changed in this diff Show More

3
.gitignore vendored

@ -1,10 +1,11 @@
######################################################################
# Build Tools
/logs
.gradle
/build/
!gradle/wrapper/gradle-wrapper.jar
.DS_Store
target/
!.mvn/wrapper/maven-wrapper.jar

1
bin/sync.sh

@ -0,0 +1 @@
rsync yudao-server/target/yudao-server.jar root@39.105.46.0:/root/project/zen/yudao.jar

6
package-lock.json generated

@ -0,0 +1,6 @@
{
"name": "zsw-farm",
"lockfileVersion": 2,
"requires": true,
"packages": {}
}

12
pom.xml

@ -19,6 +19,9 @@
<module>yudao-module-infra</module>
<module>yudao-module-pay</module>
<module>zsw-farm</module>
<module>zsw-bxg</module>
<module>zsw-erp</module>
<module>zsw-spi</module>
</modules>
<name>${project.artifactId}</name>
@ -48,6 +51,12 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.7.4</version>
<optional>true</optional>
</dependency>
</dependencies>
</dependencyManagement>
@ -60,6 +69,9 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<!-- maven-compiler-plugin 插件,解决 Lombok + MapStruct 组合 -->
<plugin>

BIN
poster.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
simsunb.ttf

Binary file not shown.

5
yudao-dependencies/pom.xml

@ -14,6 +14,7 @@
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
<properties>
<skipTest>true</skipTest>
<revision>1.6.2-snapshot</revision>
<!-- 统一依赖管理 -->
<spring.boot.version>2.5.10</spring.boot.version>
@ -22,7 +23,7 @@
<swagger-annotations.version>1.5.22</swagger-annotations.version>
<servlet.versoin>2.5</servlet.versoin>
<!-- DB 相关 -->
<mysql.version>5.1.46</mysql.version>
<mysql.version>8.0.23</mysql.version>
<druid.version>1.2.8</druid.version>
<mybatis-plus.version>3.4.3.4</mybatis-plus.version>
<dynamic-datasource.version>3.5.0</dynamic-datasource.version>
@ -47,7 +48,7 @@
<!-- 工具类相关 -->
<lombok.version>1.18.20</lombok.version>
<mapstruct.version>1.4.1.Final</mapstruct.version>
<hutool.version>5.6.1</hutool.version>
<hutool.version>5.8.0.M1</hutool.version>
<easyexcel.verion>2.2.7</easyexcel.verion>
<velocity.version>2.2</velocity.version>
<screw.version>1.0.5</screw.version>

6
yudao-framework/yudao-common/pom.xml

@ -127,6 +127,12 @@
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.0</version>
<scope>compile</scope>
</dependency>
</dependencies>

126
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/ApiCode.java

@ -0,0 +1,126 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
* 注意
* 本软件为www.yixiang.co开发研制未经购买不得使用
* 购买后可获得全部源代码禁止转卖分享上传到码云github等开源平台
* 一经发现盗用分享等行为将追究法律责任后果自负
*/
package cn.iocoder.yudao.framework.common.exception;
/**
* API 响应码
* @author hupeng
* @date 2020-04-30
*/
public enum ApiCode {
/**
* 操作成功
**/
SUCCESS(200, "操作成功"),
/**
* 登录状态失效 请重新登录
**/
UNAUTHORIZED(401, "登录状态失效 请重新登录"),
/**
* 没有权限
**/
NOT_PERMISSION(403, "没有权限"),
/**
* 你请求的资源不存在
**/
NOT_FOUND(404, "你请求的资源不存在"),
/**
* 操作失败
**/
FAIL(500, "操作失败"),
/**
* 登录失败
**/
LOGIN_EXCEPTION(4000, "登录失败"),
/**
* 系统异常
**/
SYSTEM_EXCEPTION(5000, "系统异常"),
/**
* 请求参数校验异常
**/
PARAMETER_EXCEPTION(5001, "请求参数校验异常"),
/**
* 请求参数解析异常
**/
PARAMETER_PARSE_EXCEPTION(5002, "请求参数解析异常"),
/**
* HTTP内容类型异常
**/
HTTP_MEDIA_TYPE_EXCEPTION(5003, "HTTP内容类型异常"),
/**
* 系统处理异常
**/
YSHOP_SYSTEM_EXCEPTION(5100, "系统处理异常"),
/**
* 业务处理异常
**/
BUSINESS_EXCEPTION(5101, "业务处理异常"),
/**
* 数据库处理异常
**/
DAO_EXCEPTION(5102, "数据库处理异常"),
/**
* 验证码校验异常
**/
VERIFICATION_CODE_EXCEPTION(5103, "验证码校验异常"),
/**
* 登录授权异常
**/
AUTHENTICATION_EXCEPTION(5104, "登录授权异常"),
/**
* 没有访问权限
**/
UNAUTHENTICATED_EXCEPTION(5105, "没有访问权限"),
/**
* 没有访问权限
**/
UNAUTHORIZED_EXCEPTION(5106, "没有访问权限"),
/**
* JWT Token解析异常
**/
JWTDECODE_EXCEPTION(5107, "Token解析异常"),
HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION(5108, "METHOD NOT SUPPORTED"),
/**
* 访问次数受限制
**/
BAD_LIMIT_EXCEPTION(5109, "访问次数受限制"),
;
private final int code;
private final String message;
ApiCode(final int code, final String message) {
this.code = code;
this.message = message;
}
public static ApiCode getApiCode(int code) {
ApiCode[] ecs = ApiCode.values();
for (ApiCode ec : ecs) {
if (ec.getCode() == code) {
return ec;
}
}
return SUCCESS;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}

59
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/YshopException.java

@ -0,0 +1,59 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
* 注意
* 本软件为www.yixiang.co开发研制未经购买不得使用
* 购买后可获得全部源代码禁止转卖分享上传到码云github等开源平台
* 一经发现盗用分享等行为将追究法律责任后果自负
*/
package cn.iocoder.yudao.framework.common.exception;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 自定义异常
* @author hupeng
* @date 2020-04-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class YshopException extends RuntimeException{
private static final long serialVersionUID = -2470461654663264392L;
private Integer errorCode;
private String message;
public YshopException() {
super();
}
public YshopException(String message) {
super(message);
this.errorCode = ApiCode.FAIL.getCode();
this.message = message;
}
public YshopException(Integer errorCode, String message) {
super(message);
this.errorCode = errorCode;
this.message = message;
}
public YshopException(ApiCode apiCode) {
super(apiCode.getMessage());
this.errorCode = apiCode.getCode();
this.message = apiCode.getMessage();
}
public YshopException(String message, Throwable cause) {
super(message, cause);
}
public YshopException(Throwable cause) {
super(cause);
}
}

3
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/GlobalErrorCodeConstants.java

@ -36,6 +36,9 @@ public interface GlobalErrorCodeConstants {
ErrorCode UNKNOWN = new ErrorCode(999, "未知错误");
//农作物出入管理
ErrorCode CROP_RECORD_CANT_NEGATIVE = new ErrorCode(10001, "出库失败,农作物库存小于出库数量");
static boolean isMatch(Integer code) {
return code != null
&& code >= SUCCESS.getCode() && code <= UNKNOWN.getCode();

23
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/page/PageDTO.java

@ -0,0 +1,23 @@
package cn.iocoder.yudao.framework.common.page;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel(value = "PageDTO", description = "分页对象")
public class PageDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("页码")
private Integer pageNum = 1;
@ApiModelProperty("每页数量")
private Integer pageSize = 10;
@ApiModelProperty("搜索关键字")
private String searchKey;
}

98
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/page/PageUtil.java

@ -0,0 +1,98 @@
package cn.iocoder.yudao.framework.common.page;
import cn.hutool.core.bean.BeanUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.experimental.UtilityClass;
import java.util.ArrayList;
import java.util.List;
/**
* 分页工具类
*
* @author xggz <yyimba@qq.com>
* @since 2021/6/4 11:50
*/
@UtilityClass
public class PageUtil<T> {
/**
* 转换PageHelper插件的分页数据
*
* @param pageInfo
* @param <T>
* @return
*/
public <T> PageVO<T> convertPageInfo(PageInfo<T> pageInfo) {
return BeanUtil.copyProperties(pageInfo, PageVO.class);
}
/**
* 转换PageHelper插件的分页数据
*
* @param list
* @param <T>
* @return
*/
public <T> PageVO<T> convertPageInfo(List<T> list) {
return BeanUtil.copyProperties(new PageInfo<T>(list), PageVO.class);
}
/**
* 复制分页数据
*
* @param sourcePage
* @param results
* @param <T>
* @return
*/
public <T> PageVO<T> copyPage(Object sourcePage, List<T> results) {
PageVO<T> targetPage = BeanUtil.copyProperties(sourcePage, PageVO.class);
targetPage.setList(results);
return targetPage;
}
/**
* 返回空白的分页对象
*
* @param pageNum
* @param pageSize
* @param dataClass
* @param <T>
* @return
*/
public <T> PageVO<T> emptyPage(Integer pageNum, Integer pageSize, Class<T> dataClass) {
PageVO page = new PageVO<>();
page.setPageNum(pageNum);
page.setPageSize(pageSize);
page.setSize(0);
page.setPages(0);
page.setTotal(0);
page.setHasNextPage(false);
page.setHasPreviousPage(false);
page.setList(new ArrayList());
return page;
}
/**
* 返回空白的分页对象
*
* @param pageDTO
* @param dataClass
* @param <T>
* @return
*/
public <T> PageVO<T> emptyPage(PageDTO pageDTO, Class<T> dataClass) {
return emptyPage(pageDTO.getPageNum(), pageDTO.getPageSize(), dataClass);
}
/**
* 使用PageHelper设置分页参数
*
* @param pageDTO
*/
public void startPage(PageDTO pageDTO) {
PageHelper.startPage(pageDTO.getPageNum(), pageDTO.getPageSize());
}
}

45
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/page/PageVO.java

@ -0,0 +1,45 @@
package cn.iocoder.yudao.framework.common.page;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 分页结果
*
* @author xggz <yyimba@qq.com>
* @since 2021/6/4 10:53
*/
@Data
@ApiModel(value = "PageVO", description = "分页结果")
public class PageVO<T> implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("当前页")
private int pageNum;
@ApiModelProperty("每页的数量")
private int pageSize;
@ApiModelProperty("当前页的数量")
private int size;
@ApiModelProperty("总页数")
private int pages;
@ApiModelProperty("是否有前一页")
private boolean hasPreviousPage = false;
@ApiModelProperty("是否有后一页")
private boolean hasNextPage = false;
@ApiModelProperty("总记录数")
private long total;
@ApiModelProperty("结果集")
private List<T> list;
}

231
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/ApiResult.java

@ -0,0 +1,231 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
* 注意
* 本软件为www.yixiang.co开发研制未经购买不得使用
* 购买后可获得全部源代码禁止转卖分享上传到码云github等开源平台
* 一经发现盗用分享等行为将追究法律责任后果自负
*/
package cn.iocoder.yudao.framework.common.pojo;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.exception.ApiCode;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* API 返回结果
* @author hupeng
* @date 2020-04-30
*/
@Data
@Accessors(chain = true)
@Builder
@AllArgsConstructor
public class ApiResult<T> implements Serializable {
private static final long serialVersionUID = 8004487252556526569L;
/**
* 响应码
*/
@ApiModelProperty(value = "响应码")
private int status;
/**
* 是否成功
*/
@ApiModelProperty(value = "是否成功:成功true,失败false")
private boolean success;
/**
* 响应消息
*/
@ApiModelProperty(value = "响应消息")
private String msg;
/**
* 总条数
*/
@ApiModelProperty(value = "总条数")
private Integer total;
/**
* 总页数
*/
@ApiModelProperty(value = "总页数")
private Integer totalPage;
/**
* 响应数据
*/
@ApiModelProperty(value = "响应数据")
private T data;
/**
* 响应时间
*/
@ApiModelProperty(value = "响应时间")
//@JSONField(format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date time;
public ApiResult() {
time = new Date();
}
public static ApiResult<Boolean> result(boolean flag){
if (flag){
return ok();
}
return fail();
}
public static ApiResult<Boolean> result(ApiCode apiCode){
return result(apiCode,null);
}
public static <T> ApiResult<T> result(ApiCode apiCode, T data){
return result(apiCode,null,data);
}
public static <T> ApiResult<T> resultPage(Integer total, Integer totalPage, T data){
return (ApiResult<T>) ApiResult.builder()
.total(total)
.totalPage(totalPage)
.status(200)
.msg(null)
.data(data)
.success(true)
.time(new Date())
.build();
}
public static <T> ApiResult<T> result(ApiCode apiCode, String message, T data){
boolean success = false;
if (apiCode.getCode() == ApiCode.SUCCESS.getCode()){
success = true;
}
if (StrUtil.isBlank(message)){
message = apiCode.getMessage();
}
return (ApiResult<T>) ApiResult.builder()
.status(apiCode.getCode())
.msg(message)
.data(data)
.success(success)
.time(new Date())
.build();
}
public static ApiResult<Boolean> ok(){
return ok(null);
}
public static <T> ApiResult<T> ok(T data){
return result(ApiCode.SUCCESS,data);
}
public static <T> ApiResult<T> ok(T data, String message){
return result(ApiCode.SUCCESS,message,data);
}
public static ApiResult<Map<String,Object>> okMap(String key, Object value){
Map<String,Object> map = new HashMap<>(1);
map.put(key,value);
return ok(map);
}
public static ApiResult<Boolean> fail(ApiCode apiCode){
return result(apiCode,null);
}
public static ApiResult<String> fail(String message){
return result(ApiCode.FAIL,message,null);
}
public static <T> ApiResult<T> fail(ApiCode apiCode, T data){
if (ApiCode.SUCCESS == apiCode){
throw new RuntimeException("失败结果状态码不能为" + ApiCode.SUCCESS.getCode());
}
return result(apiCode,data);
}
public static ApiResult<String> fail(Integer errorCode, String message){
return new ApiResult<String>()
.setSuccess(false)
.setStatus(errorCode)
.setMsg(message);
}
public static ApiResult<Map<String,Object>> fail(String key, Object value){
Map<String,Object> map = new HashMap<>(1);
map.put(key,value);
return result(ApiCode.FAIL,map);
}
public static <T> ApiResult<T> resultPage(T t, int limit){
List<Object> list = (List<Object>) t;
int count = list.size() / limit;
if (list.size() == 0) {
return (ApiResult<T>) ApiResult.builder()
.total(0)
.totalPage(0)
.status(200)
.msg(null)
.data(list)
.success(true)
.time(new Date())
.build();
}
if (list.size() <= limit) {
return (ApiResult<T>) ApiResult.builder()
.total(list.size())
.totalPage(1)
.status(200)
.msg(null)
.data(list)
.success(true)
.time(new Date())
.build();
} else if (count % limit == 0) {
return (ApiResult<T>) ApiResult.builder()
.total(list.size())
.totalPage(count)
.status(200)
.msg(null)
.data(list)
.success(true)
.time(new Date())
.build();
} else {
return (ApiResult<T>) ApiResult.builder()
.total(list.size())
.totalPage(count+1)
.status(200)
.msg(null)
.data(list)
.success(true)
.time(new Date())
.build();
}
}
public static ApiResult<Boolean> fail() {
return fail(ApiCode.FAIL);
}
}

4
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/PageParam.java

@ -21,10 +21,10 @@ public class PageParam implements Serializable {
@Min(value = 1, message = "页码最小值为 1")
private Integer pageNo = PAGE_NO;
@ApiModelProperty(value = "每页条数,最大值为 100", required = true, example = "10")
@ApiModelProperty(value = "每页条数,最大值为 500", required = true, example = "10")
@NotNull(message = "每页条数不能为空")
@Min(value = 1, message = "页码最小值为 1")
@Max(value = 100, message = "页码最大值为 100")
@Max(value = 500, message = "页码最大值为 500")
private Integer pageSize = PAGE_SIZE;
}

4
yudao-framework/yudao-spring-boot-starter-biz-data-permission/pom.xml

@ -40,6 +40,10 @@
<artifactId>yudao-spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
</dependencies>
</project>

19
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRule.java

@ -2,10 +2,10 @@ package cn.iocoder.yudao.framework.datapermission.core.dept.rule;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService;
import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService;
import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.framework.datapermission.core.rule.DataPermissionRule;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
@ -13,7 +13,7 @@ import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Expression;
@ -23,6 +23,7 @@ import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import java.util.HashMap;
import java.util.HashSet;
@ -146,6 +147,7 @@ public class DeptDataPermissionRule implements DataPermissionRule {
new ExpressionList(CollectionUtils.convertList(deptIds, LongValue::new)));
}
@SneakyThrows
private Expression buildUserExpression(String tableName, Alias tableAlias, Boolean self, Long userId) {
// 如果不查看自己,则无需作为条件
if (Boolean.FALSE.equals(self)) {
@ -155,6 +157,17 @@ public class DeptDataPermissionRule implements DataPermissionRule {
if (StrUtil.isEmpty(columnName)) {
return null;
}
Long cpUserId = deptDataPermissionService.getCpUserIdBySystemUserId(userId);
if (tableName.equals("farm_project")){
Expression projectSql = CCJSqlParserUtil.parseCondExpression("(creator = " + userId + " or JSON_CONTAINS(members, '"+ cpUserId +"'))");
return projectSql;
}
if (tableName.equals("farm_task")){
Expression taskSql = CCJSqlParserUtil.parseCondExpression(" (creator = " + userId + " or JSON_CONTAINS(executor_person, '"+ cpUserId +"')" +
" or main_person = " + cpUserId +")");
return taskSql;
}
// 拼接条件
return new EqualsTo(MyBatisUtils.buildColumn(tableName, tableAlias, columnName), new LongValue(userId));
}

2
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/service/DeptDataPermissionFrameworkService.java

@ -19,4 +19,6 @@ public interface DeptDataPermissionFrameworkService {
*/
DeptDataPermissionRespDTO getDeptDataPermission(LoginUser loginUser);
Long getCpUserIdBySystemUserId(Long id);
}

4
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java

@ -49,7 +49,9 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
*/
public final void init() {
doInit();
log.info("[init][配置({}) 初始化完成]", config);
// PayClientConfig
// log.info("[init][配置({}) 初始化完成]", config);
log.info("[init][配置({}) 初始化完成]", PayClientConfig.class);
}
/**

12
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/context/TenantContextHolder.java

@ -2,6 +2,8 @@ package cn.iocoder.yudao.framework.tenant.core.context;
import com.alibaba.ttl.TransmittableThreadLocal;
import java.util.function.Supplier;
/**
* 多租户上下文 Holder
*
@ -58,6 +60,16 @@ public class TenantContextHolder {
return Boolean.TRUE.equals(IGNORE.get());
}
public static <T> T apply(Long tenantId, Supplier<T> func){
Long oldTenant = TenantContextHolder.getTenantId();
try {
TenantContextHolder.setTenantId(tenantId);
return func.get();
}finally {
TenantContextHolder.setTenantId(oldTenant);
}
}
public static void clear() {
TENANT_ID.remove();
IGNORE.remove();

31
yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml

@ -12,7 +12,8 @@
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>微信拓展
<description>
微信拓展
1. 基于 weixin-java-mp 库,对接微信公众号平台。目前主要解决微信公众号的支付场景。
</description>
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
@ -31,13 +32,33 @@
</dependency>
<!-- 三方云服务相关 -->
<!-- https://mvnrepository.com/artifact/com.github.binarywang/weixin-java-mp -->
<dependency>
<groupId>com.github.binarywang</groupId>
<!-- <artifactId>weixin-java-mp</artifactId>-->
<artifactId>wx-java-mp-spring-boot-starter</artifactId>
<version>4.1.9.B</version>
<artifactId>weixin-java-mp</artifactId>
<version>4.3.0</version>
</dependency>
<!-- TODO 芋艿:清理 -->
<!-- https://mvnrepository.com/artifact/com.github.binarywang/weixin-java-miniapp -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
<version>4.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.binarywang/weixin-java-cp -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-cp</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-extension</artifactId>
<version>${revision}</version>
</dependency>
</dependencies>
</project>

40
yudao-framework/yudao-spring-boot-starter-biz-weixin/src/main/java/cn/iocoder/yudao/config/WxCpConfigure.java

@ -0,0 +1,40 @@
package cn.iocoder.yudao.config;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
@Slf4j
public class WxCpConfigure {
@Value("${wxcp.corpId}")
private String corpId;
@Value("${wxcp.secret}")
private String secret;
@Value("${wxcp.agentId}")
private Integer agentId;
@Bean
@Scope("prototype")
public WxCpService wxCpService(){
WxCpDefaultConfigImpl config = new WxCpDefaultConfigImpl();
config.setCorpId(corpId);
config.setCorpSecret(secret);
config.setAgentId(agentId);
WxCpServiceImpl wxCpService = new WxCpServiceImpl();
wxCpService.setWxCpConfigStorage(config);
log.info("企业微信初始化:{}",wxCpService);
return wxCpService;
}
}

42
yudao-framework/yudao-spring-boot-starter-biz-weixin/src/main/java/cn/iocoder/yudao/config/WxMaConfiguration.java

@ -0,0 +1,42 @@
package cn.iocoder.yudao.config;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
/**
* Created by kellen on 2020/5/3. 微信小程序服务配置
*/
@Configuration
@Slf4j
public class WxMaConfiguration {
@Value("${wxma.app_id}")
private String appId;
@Value("${wxma.app_secret}")
private String appSecret;
@Bean
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public WxMaService wxMaService() {
WxMaDefaultConfigImpl wxMaDefaultConfig = new WxMaDefaultConfigImpl();
wxMaDefaultConfig.setAppid(appId);
wxMaDefaultConfig.setSecret(appSecret);
WxMaServiceImpl wxMaService = new WxMaServiceImpl();
wxMaService.setWxMaConfig(wxMaDefaultConfig);
return wxMaService;
}
}

3
yudao-framework/yudao-spring-boot-starter-biz-weixin/src/main/resources/META-INF/spring.factories

@ -0,0 +1,3 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.iocoder.yudao.config.WxCpConfigure,\
cn.iocoder.yudao.config.WxMaConfiguration

2
yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientTest.java

@ -17,7 +17,7 @@ public class S3FileClientTest {
// 配置成你自己的
config.setAccessKey("admin");
config.setAccessSecret("password");
config.setBucket("yudaoyuanma");
config.setBucket("zsw");
config.setDomain(null);
// 默认 9000 endpoint
config.setEndpoint("http://127.0.0.1:9000");

15
yudao-framework/yudao-spring-boot-starter-flowable/pom.xml

@ -12,6 +12,21 @@
<artifactId>yudao-spring-boot-starter-flowable</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-full</artifactId> <!--注意-->
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-common</artifactId>

69
yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/JdbcStoreTypeConfiguration.java

@ -0,0 +1,69 @@
package cn.iocoder.yudao.framework.quartz.config;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.autoconfigure.quartz.*;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.ResourceLoader;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionManager;
import javax.sql.DataSource;
@Configuration
@ConditionalOnProperty(prefix = "spring.quartz", name = "job-store-type", havingValue = "jdbc")
@Import(DatabaseInitializationDependencyConfigurer.class)
@EnableConfigurationProperties(QuartzProperties.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
LiquibaseAutoConfiguration.class, FlywayAutoConfiguration.class })
public class JdbcStoreTypeConfiguration {
@Bean
@Order(0)
public SchedulerFactoryBeanCustomizer dataSourceCustomizer(QuartzProperties properties,
DataSource dataSource,
@QuartzDataSource ObjectProvider<DataSource> quartzDataSource,
TransactionManager transactionManager
) {
return (schedulerFactoryBean) -> {
DataSource dataSourceToUse = getDataSource(dataSource, quartzDataSource);
schedulerFactoryBean.setDataSource(dataSourceToUse);
schedulerFactoryBean.setTransactionManager((PlatformTransactionManager) transactionManager);
};
}
private DataSource getDataSource(DataSource dataSource, ObjectProvider<DataSource> quartzDataSource) {
DataSource dataSourceIfAvailable = quartzDataSource.getIfAvailable();
return (dataSourceIfAvailable != null) ? dataSourceIfAvailable : dataSource;
}
private PlatformTransactionManager getTransactionManager(
ObjectProvider<PlatformTransactionManager> transactionManager,
ObjectProvider<PlatformTransactionManager> quartzTransactionManager) {
PlatformTransactionManager transactionManagerIfAvailable = quartzTransactionManager.getIfAvailable();
return (transactionManagerIfAvailable != null) ? transactionManagerIfAvailable
: transactionManager.getIfUnique();
}
@Bean
@ConditionalOnMissingBean
public QuartzDataSourceInitializer quartzDataSourceInitializer(DataSource dataSource,
@QuartzDataSource ObjectProvider<DataSource> quartzDataSource, ResourceLoader resourceLoader,
QuartzProperties properties) {
DataSource dataSourceToUse = getDataSource(dataSource, quartzDataSource);
return new QuartzDataSourceInitializer(dataSourceToUse, resourceLoader, properties);
}
}

3
yudao-framework/yudao-spring-boot-starter-job/src/main/resources/META-INF/spring.factories

@ -1,3 +1,4 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.iocoder.yudao.framework.quartz.config.YudaoQuartzAutoConfiguration,\
cn.iocoder.yudao.framework.quartz.config.YudaoAsyncAutoConfiguration
cn.iocoder.yudao.framework.quartz.config.YudaoAsyncAutoConfiguration,\
cn.iocoder.yudao.framework.quartz.config.JdbcStoreTypeConfiguration

8
yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml

@ -16,7 +16,7 @@
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
<properties>
<mysql.version>5.1.46</mysql.version>
<mysql.version>8.0.23</mysql.version>
</properties>
<dependencies>
@ -46,10 +46,8 @@
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId> <!-- 多数据源 -->
</dependency>
</dependencies>
</project>

102
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java

@ -1,22 +1,52 @@
package cn.iocoder.yudao.framework.mybatis.config;
import cn.iocoder.yudao.framework.mybatis.core.handler.DefaultDBFieldHandler;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.stat.DruidDataSourceStatManager;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.annotation.MapperScans;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.quartz.QuartzDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionManager;
import javax.sql.DataSource;
import java.util.Arrays;
import java.util.Map;
/**
* MyBaits 配置类
*
* @author 芋道源码
*/
@MapperScans({
@MapperScan(basePackages ={"co.yixiang.**.service.mapper", "co.yixiang.config"},sqlSessionFactoryRef = "shangcheng"),
@MapperScan(basePackages = {"com.zsw.erp.datasource.mappers"},sqlSessionFactoryRef = "erp"),
@MapperScan(basePackages = {"${yudao.info.base-package}", "cn.iocoder.yudao"}, annotationClass = Mapper.class,
lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅用于单元测试
})
@Configuration
@MapperScan(value = "${yudao.info.base-package}", annotationClass = Mapper.class,
lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅用于单元测试
@Slf4j
public class YudaoMybatisAutoConfiguration {
@Bean
@ -31,4 +61,72 @@ public class YudaoMybatisAutoConfiguration {
return new DefaultDBFieldHandler(); // 自动填充参数类
}
@Bean("dataSource")
@QuartzDataSource
@ConfigurationProperties("spring.datasource.dynamic.datasource.master")
public DataSource masterDataSource(){
return new DruidDataSource();
}
@Bean
@Primary
public SqlSessionFactory sqlSessionFactoryMaster(@Qualifier("dataSource") DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
factory.setTypeEnumsPackage("cn.iocoder.yudao.module.farm.enums");
factory.setDataSource(dataSource);
return getSqlSessionFactory(factory);
}
@Bean("bxgDataSource")
@ConfigurationProperties("spring.datasource.dynamic.datasource.bxg")
public DataSource bxgDataSource(){
return new DruidDataSource();
}
@Bean("shangcheng")
public SqlSessionFactory sqlSessionFactory(@Qualifier("bxgDataSource") DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
factory.setDataSource(dataSource);
return getSqlSessionFactory(factory);
}
@Bean("erpDataSource")
@ConfigurationProperties("spring.datasource.dynamic.datasource.erp")
public DataSource erpDataSource(){
return new DruidDataSource();
}
@Bean("erp")
public SqlSessionFactory erpSqlSessionFactory(@Qualifier("erpDataSource") DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath*:/erp_mapper/*.xml");
Arrays.stream(resources).forEach(resource -> {
log.info("erp mapper:{}",resource.getFilename());
});
factory.setMapperLocations(resources);
factory.setDataSource(dataSource);
return getSqlSessionFactory(factory);
}
private SqlSessionFactory getSqlSessionFactory(MybatisSqlSessionFactoryBean factory) throws Exception {
GlobalConfig globalConfig = new GlobalConfig();
GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();
dbConfig.setIdType(IdType.AUTO);
globalConfig.setDbConfig(dbConfig);
globalConfig.setMetaObjectHandler(defaultMetaObjectHandler());
Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper/*/*.xml");
Arrays.stream(resources).forEach(resource -> {
log.info("master mapper:{}",resource.getFilename());
});
factory.setMapperLocations(resources);
factory.setPlugins(mybatisPlusInterceptor());
factory.setGlobalConfig(globalConfig);
return factory.getObject();
}
@Bean
public TransactionManager transactionManager(DataSource dataSource){
DataSourceTransactionManager manager = new DataSourceTransactionManager();
manager.setDataSource(dataSource);
return manager;
}
}

3
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseDO.java

@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.mybatis.core.dataobject;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Builder;
import lombok.Data;
@ -21,11 +22,13 @@ public abstract class BaseDO implements Serializable {
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 最后更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/**
* 创建者目前使用 SysUser id 编号

39
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseDomain.java

@ -0,0 +1,39 @@
package cn.iocoder.yudao.framework.mybatis.core.dataobject;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.Date;
/**
* @ClassName 公共模型
* @Author hupeng <610796224@qq.com>
* @Date 2020/6/13
**/
@Getter
@Setter
public class BaseDomain implements Serializable {
private static final long serialVersionUID = 1L;
@TableField(fill= FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date createTime;
@TableField(fill= FieldFill.UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date updateTime;
@TableLogic
@JsonIgnore
@TableField(fill= FieldFill.INSERT)
private Integer isDel;
}

90
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java

@ -1,10 +1,13 @@
package cn.iocoder.yudao.framework.mybatis.core.handler;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Objects;
@ -15,33 +18,61 @@ import java.util.Objects;
*
* @author hexiaowu
*/
@Slf4j
public class DefaultDBFieldHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseDO) {
BaseDO baseDO = (BaseDO) metaObject.getOriginalObject();
Date current = new Date();
// 创建时间为空,则以当前时间为插入时间
if (Objects.isNull(baseDO.getCreateTime())) {
baseDO.setCreateTime(current);
}
// 更新时间为空,则以当前时间为更新时间
if (Objects.isNull(baseDO.getUpdateTime())) {
baseDO.setUpdateTime(current);
}
Long userId = WebFrameworkUtils.getLoginUserId();
// 当前登录用户不为空,创建人为空,则当前登录用户为创建人
if (Objects.nonNull(userId) && Objects.isNull(baseDO.getCreator())) {
baseDO.setCreator(userId.toString());
}
// 当前登录用户不为空,更新人为空,则当前登录用户为更新人
if (Objects.nonNull(userId) && Objects.isNull(baseDO.getUpdater())) {
baseDO.setUpdater(userId.toString());
}
// if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseDO) {
// BaseDO baseDO = (BaseDO) metaObject.getOriginalObject();
//
// Date current = new Date();
// // 创建时间为空,则以当前时间为插入时间
// if (Objects.isNull(baseDO.getCreateTime())) {
// baseDO.setCreateTime(current);
// }
// // 更新时间为空,则以当前时间为更新时间
// if (Objects.isNull(baseDO.getUpdateTime())) {
// baseDO.setUpdateTime(current);
// }
//
//
// }
Long userId = WebFrameworkUtils.getLoginUserId();
// 当前登录用户不为空,创建人为空,则当前登录用户为创建人
if (metaObject.hasSetter("creator") && ObjectUtil.isNotEmpty(userId)) {
this.setFieldValByName("creator", userId.toString(), metaObject);
}
if (metaObject.hasSetter("updater") && ObjectUtil.isNotEmpty(userId)) {
this.setFieldValByName("updater", userId.toString(), metaObject);
}
Timestamp time=new Timestamp(System.currentTimeMillis());
if (metaObject.hasSetter("createTime")) {
this.setFieldValByName("createTime", time, metaObject);
}
if (metaObject.hasSetter("updateTime")) {
this.setFieldValByName("updateTime", time, metaObject);
}
if (metaObject.hasSetter("createDate")) {
this.setFieldValByName("createDate", time, metaObject);
}
if (metaObject.hasSetter("updateDate")) {
this.setFieldValByName("updateDate", time, metaObject);
}
if (metaObject.hasSetter("delFlag")) {
this.setFieldValByName("delFlag", false, metaObject);
}
if (metaObject.hasSetter("isDel")) {
this.setFieldValByName("isDel", 0, metaObject);
}
if (metaObject.hasSetter("addTime")) {
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
this.setFieldValByName("addTime", Integer.valueOf(timestamp), metaObject);
}
}
@Override
@ -58,5 +89,20 @@ public class DefaultDBFieldHandler implements MetaObjectHandler {
if (Objects.nonNull(userId) && Objects.isNull(modifier)) {
setFieldValByName("updater", userId.toString(), metaObject);
}
Timestamp time=new Timestamp(System.currentTimeMillis());
if (metaObject.hasSetter("updateTime")) {
this.setFieldValByName("updateTime", time, metaObject);
}
if (metaObject.hasSetter("updateDate")) {
this.setFieldValByName("updateDate", time, metaObject);
}
if (metaObject.hasSetter("delFlag")) {
this.setFieldValByName("delFlag", null, metaObject);
}
if (metaObject.hasSetter("createTime")) {
this.setFieldValByName("createTime", null, metaObject);
}
}
}

68
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/ListIntToListLongTypeHandler.java

@ -0,0 +1,68 @@
package cn.iocoder.yudao.framework.mybatis.core.handler;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* zyj
*/
@MappedJdbcTypes(JdbcType.VARCHAR) // 数据库中该字段存储的类型
@MappedTypes(List.class) // 需要转换的对象
public class ListIntToListLongTypeHandler extends BaseTypeHandler<List<Long>> {
private static ObjectMapper mObjectMapper = new ObjectMapper();
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, List<Long> longs, JdbcType jdbcType) throws SQLException {
String json = JSONUtil.toJsonStr(longs);
preparedStatement.setObject(i, json);
}
@Override
public List<Long> getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
String value = resultSet.getString(columnName);
return getLongs(value);
}
@Override
public List<Long> getNullableResult(ResultSet resultSet, int i) throws SQLException {
String value = resultSet.getString(i);
return getLongs(value);
}
@Override
public List<Long> getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
String value = callableStatement.getString(i);
return getLongs(value);
}
private List<Long> getLongs(String value) {
if (ObjectUtil.isNotEmpty(value)) {
try {
CollectionType type = mObjectMapper.getTypeFactory().constructCollectionType(ArrayList.class, Long.class);
List<Long> longs = mObjectMapper.readValue(value , type);
return longs;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
return null;
}
}

28
yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoRedisAutoConfiguration.java

@ -15,19 +15,19 @@ public class YudaoRedisAutoConfiguration {
/**
* 创建 RedisTemplate Bean使用 JSON 序列化方式
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
// 创建 RedisTemplate 对象
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 设置 RedisConnection 工厂。😈 它就是实现多种 Java Redis 客户端接入的秘密工厂。感兴趣的胖友,可以自己去撸下。
template.setConnectionFactory(factory);
// 使用 String 序列化方式,序列化 KEY 。
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
// 使用 JSON 序列化方式(库是 Jackson ),序列化 VALUE 。
template.setValueSerializer(RedisSerializer.json());
template.setHashValueSerializer(RedisSerializer.json());
return template;
}
// @Bean
// public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
// // 创建 RedisTemplate 对象
// RedisTemplate<String, Object> template = new RedisTemplate<>();
// // 设置 RedisConnection 工厂。😈 它就是实现多种 Java Redis 客户端接入的秘密工厂。感兴趣的胖友,可以自己去撸下。
// template.setConnectionFactory(factory);
// // 使用 String 序列化方式,序列化 KEY 。
// template.setKeySerializer(RedisSerializer.string());
// template.setHashKeySerializer(RedisSerializer.string());
// // 使用 JSON 序列化方式(库是 Jackson ),序列化 VALUE 。
// template.setValueSerializer(RedisSerializer.json());
// template.setHashValueSerializer(RedisSerializer.json());
// return template;
// }
}

2
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/SecurityProperties.java

@ -41,6 +41,6 @@ public class SecurityProperties {
* 一定要配置密钥保证安全性
*/
@NotEmpty(message = "mock 模式的密钥不能为空") // 这里设置了一个默认值,因为实际上只有 mockEnable 为 true 时才需要配置。
private String mockSecret = "yudaoyuanma";
private String mockSecret = "zsw";
}

6
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java

@ -22,6 +22,7 @@ import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
@ -86,8 +87,11 @@ public class YudaoSecurityAutoConfiguration {
* Token 认证过滤器 Bean
*/
@Bean
public JWTAuthenticationTokenFilter authenticationTokenFilter(MultiUserDetailsAuthenticationProvider authenticationProvider,
public JWTAuthenticationTokenFilter authenticationTokenFilter(
HttpServletRequest request,
MultiUserDetailsAuthenticationProvider authenticationProvider,
GlobalExceptionHandler globalExceptionHandler) {
return new JWTAuthenticationTokenFilter(securityProperties, authenticationProvider, globalExceptionHandler);
}

7
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java

@ -130,6 +130,10 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
// 设置 App API 无需认证
.antMatchers(buildAppApi("/**")).permitAll()
.antMatchers("/common/**").permitAll()
// 忽略宝享购全部
.antMatchers("/bxgApp/**").permitAll()
// ②:每个项目的自定义规则
.and().authorizeRequests(registry -> // 下面,循环设置自定义规则
authorizeRequestsCustomizers.forEach(customizer -> customizer.customize(registry)))
@ -138,7 +142,8 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
.anyRequest().authenticated()
;
// 添加 JWT Filter
// // 添加 JWT Filter
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
}

26
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/annotations/AuthCheck.java

@ -0,0 +1,26 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
* 注意
* 本软件为www.yixiang.co开发研制未经购买不得使用
* 购买后可获得全部源代码禁止转卖分享上传到码云github等开源平台
* 一经发现盗用分享等行为将追究法律责任后果自负
*/
package cn.iocoder.yudao.framework.security.core.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @ClassName 自定义权限注解
* @Author hupeng <610796224@qq.com>
* @Date 2020/4/30
**/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthCheck {
int value() default 4;
}

7
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/MultiUserDetailsAuthenticationProvider.java

@ -140,7 +140,12 @@ public class MultiUserDetailsAuthenticationProvider extends AbstractUserDetailsA
private UserTypeEnum getUserType(HttpServletRequest request) {
// log.error("URI:{}",request.getRequestURI());
if (request.getRequestURI().startsWith(properties.getAdminApi().getPrefix()) || request.getRequestURI().startsWith("/common/")) {
if (request.getRequestURI().startsWith(properties.getAdminApi().getPrefix())
|| request.getRequestURI().startsWith("/common/")
|| request.getRequestURI().startsWith("/bxg")
|| request.getRequestURI().startsWith("/erp")
|| request.getRequestURI().startsWith("/api/upload")
) {
return UserTypeEnum.ADMIN;
}
if (request.getRequestURI().startsWith(properties.getAppApi().getPrefix())) {

1
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JWTAuthenticationTokenFilter.java

@ -36,6 +36,7 @@ public class JWTAuthenticationTokenFilter extends OncePerRequestFilter {
@SuppressWarnings("NullableProblems")
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader());
if (StrUtil.isNotEmpty(token)) {
try {

6
yudao-framework/yudao-spring-boot-starter-web/pom.xml

@ -59,6 +59,12 @@
<artifactId>resilience4j-ratelimiter</artifactId>
<scope>provided</scope> <!-- 设置为 provided,主要是 GlobalExceptionHandler 使用 -->
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>3.0.9</version>
<scope>compile</scope>
</dependency>
</dependencies>

4
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java

@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeDeserialize
import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeSerializer;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
@ -38,7 +39,8 @@ public class YudaoJacksonAutoConfiguration {
.addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
objectMapper.registerModules(simpleModule);
// 序列化枚举
objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true);
JsonUtils.init(objectMapper);
log.info("初始化 jackson 自动配置");
return bean;

95
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java

@ -8,16 +8,15 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ExampleBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestParameterBuilder;
import springfox.documentation.builders.*;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -50,6 +49,7 @@ public class YudaoSwaggerAutoConfiguration {
return new Docket(DocumentationType.SWAGGER_2)
// 用来创建该 API 的基本信息,展示在文档的页面中(自定义展示的信息)
.apiInfo(apiInfo(properties))
.groupName("管理系统")
// 设置扫描指定 package 包下的
.select()
.apis(basePackage(properties.getBasePackage()))
@ -61,6 +61,93 @@ public class YudaoSwaggerAutoConfiguration {
.securityContexts(securityContexts());
}
@Bean("SWAGGER_ADMIN")
@SuppressWarnings("all")
public Docket createRestApi1() {
SwaggerProperties properties = swaggerProperties();
ParameterBuilder ticketPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<>();
ticketPar.name("token").description("token")
.modelRef(new ModelRef("string"))
.parameterType("header")
.defaultValue("token " + " ")
.required(true)
.build();
pars.add(ticketPar.build());
return new Docket(DocumentationType.SWAGGER_2)
.groupName("商城后台")
.enable(true)
.apiInfo(apiInfo(properties))
.select()
.apis(RequestHandlerSelectors.basePackage("co.yixiang.modules"))
.paths(PathSelectors.regex("/error.*").negate())
.build()
.globalOperationParameters(pars)
//添加登陆认证
.securitySchemes(securitySchemes())
.globalRequestParameters(globalRequestParameters())
.securityContexts(securityContexts());
}
@Bean("SWAGGER_APP")
@SuppressWarnings("all")
public Docket createAppApi() {
SwaggerProperties properties = swaggerProperties();
ParameterBuilder ticketPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<>();
ticketPar.name("token").description("token")
.modelRef(new ModelRef("string"))
.parameterType("header")
.defaultValue("token" + " ")
.required(true)
.build();
pars.add(ticketPar.build());
return new Docket(DocumentationType.SWAGGER_2)
.groupName("商城前台")
.enable(true)
.apiInfo(apiInfo(properties))
.select()
.apis(RequestHandlerSelectors.basePackage("co.yixiang.app.modules"))
.paths(PathSelectors.regex("/error.*").negate())
.build()
.globalOperationParameters(pars)
//添加登陆认证
.securitySchemes(securitySchemes())
.globalRequestParameters(globalRequestParameters())
.securityContexts(securityContexts());
}
@Bean("SWAGGER_TOOL")
@SuppressWarnings("all")
public Docket createToolApi() {
SwaggerProperties properties = swaggerProperties();
ParameterBuilder ticketPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<>();
ticketPar.name("token").description("token")
.modelRef(new ModelRef("string"))
.parameterType("header")
.defaultValue("token" + " ")
.required(true)
.build();
pars.add(ticketPar.build());
return new Docket(DocumentationType.SWAGGER_2)
.groupName("电商工具")
.enable(true)
.apiInfo(apiInfo(properties))
.select()
.apis(RequestHandlerSelectors.basePackage("co.yixiang.tools"))
.paths(PathSelectors.regex("/error.*").negate())
.build()
.globalOperationParameters(pars)
//添加登陆认证
.securitySchemes(securitySchemes())
.globalRequestParameters(globalRequestParameters())
.securityContexts(securityContexts());
}
// ========== apiInfo ==========
/**

23
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java

@ -3,18 +3,21 @@ package cn.iocoder.yudao.framework.web.core.handler;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService;
import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateReqDTO;
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.exception.YshopException;
import cn.iocoder.yudao.framework.common.pojo.ApiResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import io.github.resilience4j.ratelimiter.RequestNotPermitted;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.dubbo.rpc.RpcException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.util.Assert;
import org.springframework.validation.BindException;
@ -92,6 +95,11 @@ public class GlobalExceptionHandler {
if (ex instanceof AccessDeniedException) {
return accessDeniedExceptionHandler(request, (AccessDeniedException) ex);
}
if (ex instanceof RpcException){
log.error("dubbo错误", ex);
return null;
}
return defaultExceptionHandler(request, ex);
}
@ -215,6 +223,13 @@ public class GlobalExceptionHandler {
return CommonResult.error(ex.getCode(), ex.getMessage());
}
@ExceptionHandler(value = YshopException.class)
public ApiResult<?> yshopException(YshopException ex){
log.info("[YshopException]",ex);
return ApiResult.fail(ex.getErrorCode(),ex.getMessage());
//return CommonResult.error(ex.getErrorCode(), ex.getMessage());
}
/**
* 处理系统异常兜底处理所有的一切
*/

13
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/doc/DbDocController.java

@ -9,8 +9,6 @@ import cn.smallbun.screw.core.engine.EngineFileType;
import cn.smallbun.screw.core.engine.EngineTemplateType;
import cn.smallbun.screw.core.execute.DocumentationExecute;
import cn.smallbun.screw.core.process.ProcessConfig;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import io.swagger.annotations.Api;
@ -32,9 +30,6 @@ import java.util.Arrays;
@RequestMapping("/infra/db-doc")
public class DbDocController {
@Resource
private DynamicDataSourceProperties dynamicDataSourceProperties;
private static final String FILE_OUTPUT_DIR = System.getProperty("java.io.tmpdir") + File.separator
+ "db-doc";
private static final String DOC_FILE_NAME = "数据库文档";
@ -119,13 +114,11 @@ public class DbDocController {
// TODO 芋艿:screw 暂时不支持 druid,尴尬
private HikariDataSource buildDataSource() {
// 获得 DataSource 数据源,目前只支持首个
String primary = dynamicDataSourceProperties.getPrimary();
DataSourceProperty dataSourceProperty = dynamicDataSourceProperties.getDatasource().get(primary);
// 创建 HikariConfig 配置类
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setJdbcUrl(dataSourceProperty.getUrl());
hikariConfig.setUsername(dataSourceProperty.getUsername());
hikariConfig.setPassword(dataSourceProperty.getPassword());
hikariConfig.setJdbcUrl("");
hikariConfig.setUsername("");
hikariConfig.setPassword("");
hikariConfig.addDataSourceProperty("useInformationSchema", "true"); // 设置可以获取 tables remarks 信息
// 创建数据源
return new HikariDataSource(hikariConfig);

36
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/security/config/SecurityConfiguration.java

@ -1,27 +1,61 @@
package cn.iocoder.yudao.module.infra.framework.security.config;
import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer;
import cn.iocoder.yudao.framework.security.core.annotations.AuthCheck;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
/**
* Infra 模块的 Security 配置
*/
@Configuration("infraSecurityConfiguration")
@Slf4j
public class SecurityConfiguration {
@Value("${spring.boot.admin.context-path:''}")
private String adminSeverContextPath;
@Resource
private ApplicationContext applicationContext;
@Bean("infraAuthorizeRequestsCustomizer")
public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() {
return new AuthorizeRequestsCustomizer() {
@Override
public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {
// 查找全部宝象购的链接
Map<RequestMappingInfo, HandlerMethod> handlerMethods = applicationContext.getBean(RequestMappingHandlerMapping.class).getHandlerMethods();
Set<String> anonymousUrls = new HashSet<>();
for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethods.entrySet()) {
HandlerMethod handlerMethod = infoEntry.getValue();
// 宝象购app包下 并且没有登录标识 放行
if (handlerMethod.getBeanType().getPackage().getName().startsWith("co.yixiang.app")
&& !handlerMethod.hasMethodAnnotation(AuthCheck.class)){
PatternsRequestCondition requestCondition = infoEntry.getKey().getPatternsCondition();
Optional.ofNullable(requestCondition).orElseThrow(RuntimeException::new);
anonymousUrls.addAll(requestCondition.getPatterns());
}
}
// anonymousUrls.forEach(s -> log.info("宝象购可以匿名访问的url:{}", s));
registry.antMatchers(anonymousUrls.toArray(new String[0])).anonymous();
// Swagger 接口文档
registry.antMatchers("/swagger-ui.html").anonymous()
.antMatchers("/swagger-resources/**").anonymous()
@ -32,6 +66,8 @@ public class SecurityConfiguration {
.antMatchers("/actuator/**").anonymous();
// Druid 监控
registry.antMatchers("/druid/**").anonymous();
// 首页
registry.antMatchers("/").anonymous();
// Spring Boot Admin Server 的安全配置
registry.antMatchers(adminSeverContextPath).anonymous()
.antMatchers(adminSeverContextPath + "/**").anonymous();

6
yudao-module-infra/yudao-module-infra-impl/src/main/resources/mapper/test/TestDemoMapper.xml

@ -9,8 +9,8 @@
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
-->
<select id="selectList2" resultType="TestDemoDO">
SELECT * FROM infra_test_demo
</select>
<!-- <select id="selectList2" resultType="TestDemoDO">-->
<!-- SELECT * FROM infra_test_demo-->
<!-- </select>-->
</mapper>

2
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java

@ -14,7 +14,7 @@ import lombok.NoArgsConstructor;
@Builder
public class AppAuthLoginRespVO {
@ApiModelProperty(value = "token", required = true, example = "yudaoyuanma")
@ApiModelProperty(value = "token", required = true, example = "zsw")
private String token;
}

17
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/weixin/TestConfigure.java

@ -0,0 +1,17 @@
package cn.iocoder.yudao.module.member.controller.app.weixin;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class TestConfigure {
@Bean
public WxMpService wxMpService(){
WxMpService wxMpService = new WxMpServiceImpl();
return wxMpService;
}
}

10
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java

@ -68,7 +68,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
@Resource
private PasswordEncoder passwordEncoder;
@Resource
private MemberUserMapper userMapper;
private MemberUserMapper memberUserMapper;
@Override
public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException {
@ -286,7 +286,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
MemberUserDO userDO = checkOldPassword(userId, reqVO.getOldPassword());
// 更新用户密码
userMapper.updateById(MemberUserDO.builder().id(userDO.getId())
memberUserMapper.updateById(MemberUserDO.builder().id(userDO.getId())
.password(passwordEncoder.encode(reqVO.getPassword())).build());
}
@ -300,7 +300,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
getClientIP()));
// 更新密码
userMapper.updateById(MemberUserDO.builder().id(userDO.getId())
memberUserMapper.updateById(MemberUserDO.builder().id(userDO.getId())
.password(passwordEncoder.encode(reqVO.getPassword())).build());
}
@ -319,7 +319,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
*/
@VisibleForTesting
public MemberUserDO checkOldPassword(Long id, String oldPassword) {
MemberUserDO user = userMapper.selectById(id);
MemberUserDO user = memberUserMapper.selectById(id);
if (user == null) {
throw exception(USER_NOT_EXISTS);
}
@ -331,7 +331,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
}
public MemberUserDO checkUserIfExists(String mobile) {
MemberUserDO user = userMapper.selectByMobile(mobile);
MemberUserDO user = memberUserMapper.selectByMobile(mobile);
if (user == null) {
throw exception(USER_NOT_EXISTS);
}

274
yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImplTest.java

@ -1,137 +1,137 @@
package cn.iocoder.yudao.module.member.service.user;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.member.controller.app.user.vo.AppUserUpdateMobileReqVO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper;
import cn.iocoder.yudao.module.member.service.auth.MemberAuthServiceImpl;
import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.util.function.Consumer;
import static cn.hutool.core.util.RandomUtil.*;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.when;
// TODO @芋艿:单测的 review,等逻辑都达成一致后
/**
* {@link MemberUserServiceImpl} 的单元测试类
*
* @author 宋天
*/
@Import({MemberUserServiceImpl.class, YudaoRedisAutoConfiguration.class})
public class MemberUserServiceImplTest extends BaseDbAndRedisUnitTest {
@Resource
private MemberUserServiceImpl memberUserService;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Resource
private MemberUserMapper userMapper;
@MockBean
private MemberAuthServiceImpl authService;
@MockBean
private PasswordEncoder passwordEncoder;
@MockBean
private SmsCodeApi smsCodeApi;
@MockBean
private FileApi fileApi;
@Test
public void testUpdateNickName_success(){
// mock 数据
MemberUserDO userDO = randomUserDO();
userMapper.insert(userDO);
// 随机昵称
String newNickName = randomString();
// 调用接口修改昵称
memberUserService.updateUserNickname(userDO.getId(),newNickName);
// 查询新修改后的昵称
String nickname = memberUserService.getUser(userDO.getId()).getNickname();
// 断言
assertEquals(newNickName,nickname);
}
@Test
public void testUpdateAvatar_success() throws Exception {
// mock 数据
MemberUserDO dbUser = randomUserDO();
userMapper.insert(dbUser);
// 准备参数
Long userId = dbUser.getId();
byte[] avatarFileBytes = randomBytes(10);
ByteArrayInputStream avatarFile = new ByteArrayInputStream(avatarFileBytes);
// mock 方法
String avatar = randomString();
when(fileApi.createFile(eq(avatarFileBytes))).thenReturn(avatar);
// 调用
String str = memberUserService.updateUserAvatar(userId, avatarFile);
// 断言
assertEquals(avatar, str);
}
@Test
public void updateMobile_success(){
// mock数据
String oldMobile = randomNumbers(11);
MemberUserDO userDO = randomUserDO();
userDO.setMobile(oldMobile);
userMapper.insert(userDO);
// TODO 芋艿:需要修复该单元测试,重构多模块带来的
// 旧手机和旧验证码
// SmsCodeDO codeDO = new SmsCodeDO();
String oldCode = RandomUtil.randomString(4);
// codeDO.setMobile(userDO.getMobile());
// codeDO.setCode(oldCode);
// codeDO.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene());
// codeDO.setUsed(Boolean.FALSE);
// when(smsCodeService.checkCodeIsExpired(codeDO.getMobile(),codeDO.getCode(),codeDO.getScene())).thenReturn(codeDO);
// 更新手机号
String newMobile = randomNumbers(11);
String newCode = randomNumbers(4);
AppUserUpdateMobileReqVO reqVO = new AppUserUpdateMobileReqVO();
reqVO.setMobile(newMobile);
reqVO.setCode(newCode);
reqVO.setOldMobile(oldMobile);
reqVO.setOldCode(oldCode);
memberUserService.updateUserMobile(userDO.getId(),reqVO);
assertEquals(memberUserService.getUser(userDO.getId()).getMobile(),newMobile);
}
// ========== 随机对象 ==========
@SafeVarargs
private static MemberUserDO randomUserDO(Consumer<MemberUserDO>... consumers) {
Consumer<MemberUserDO> consumer = (o) -> {
o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
};
return randomPojo(MemberUserDO.class, ArrayUtils.append(consumer, consumers));
}
}
//package cn.iocoder.yudao.module.member.service.user;
//
//import cn.hutool.core.util.RandomUtil;
//import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
//import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
//import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
//import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest;
//import cn.iocoder.yudao.module.infra.api.file.FileApi;
//import cn.iocoder.yudao.module.member.controller.app.user.vo.AppUserUpdateMobileReqVO;
//import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
//import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper;
//import cn.iocoder.yudao.module.member.service.auth.MemberAuthServiceImpl;
//import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
//import org.junit.jupiter.api.Test;
//import org.springframework.boot.test.mock.mockito.MockBean;
//import org.springframework.context.annotation.Import;
//import org.springframework.data.redis.core.StringRedisTemplate;
//import org.springframework.security.crypto.password.PasswordEncoder;
//
//import javax.annotation.Resource;
//import java.io.ByteArrayInputStream;
//import java.util.function.Consumer;
//
//import static cn.hutool.core.util.RandomUtil.*;
//import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
//import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
//import static org.junit.jupiter.api.Assertions.assertEquals;
//import static org.mockito.Mockito.eq;
//import static org.mockito.Mockito.when;
//
//// TODO @芋艿:单测的 review,等逻辑都达成一致后
///**
// * {@link MemberUserServiceImpl} 的单元测试类
// *
// * @author 宋天
// */
//@Import({MemberUserServiceImpl.class, YudaoRedisAutoConfiguration.class})
//public class MemberUserServiceImplTest extends BaseDbAndRedisUnitTest {
//
// @Resource
// private MemberUserServiceImpl memberUserService;
//
// @Resource
// private StringRedisTemplate stringRedisTemplate;
//
// @Resource
// private MemberUserMapper userMapper;
//
// @MockBean
// private MemberAuthServiceImpl authService;
//
// @MockBean
// private PasswordEncoder passwordEncoder;
//
// @MockBean
// private SmsCodeApi smsCodeApi;
// @MockBean
// private FileApi fileApi;
//
// @Test
// public void testUpdateNickName_success(){
// // mock 数据
// MemberUserDO userDO = randomUserDO();
// userMapper.insert(userDO);
//
// // 随机昵称
// String newNickName = randomString();
//
// // 调用接口修改昵称
// memberUserService.updateUserNickname(userDO.getId(),newNickName);
// // 查询新修改后的昵称
// String nickname = memberUserService.getUser(userDO.getId()).getNickname();
// // 断言
// assertEquals(newNickName,nickname);
// }
//
// @Test
// public void testUpdateAvatar_success() throws Exception {
// // mock 数据
// MemberUserDO dbUser = randomUserDO();
// userMapper.insert(dbUser);
//
// // 准备参数
// Long userId = dbUser.getId();
// byte[] avatarFileBytes = randomBytes(10);
// ByteArrayInputStream avatarFile = new ByteArrayInputStream(avatarFileBytes);
// // mock 方法
// String avatar = randomString();
// when(fileApi.createFile(eq(avatarFileBytes))).thenReturn(avatar);
// // 调用
// String str = memberUserService.updateUserAvatar(userId, avatarFile);
// // 断言
// assertEquals(avatar, str);
// }
//
// @Test
// public void updateMobile_success(){
// // mock数据
// String oldMobile = randomNumbers(11);
// MemberUserDO userDO = randomUserDO();
// userDO.setMobile(oldMobile);
// userMapper.insert(userDO);
//
// // TODO 芋艿:需要修复该单元测试,重构多模块带来的
// // 旧手机和旧验证码
//// SmsCodeDO codeDO = new SmsCodeDO();
// String oldCode = RandomUtil.randomString(4);
//// codeDO.setMobile(userDO.getMobile());
//// codeDO.setCode(oldCode);
//// codeDO.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene());
//// codeDO.setUsed(Boolean.FALSE);
//// when(smsCodeService.checkCodeIsExpired(codeDO.getMobile(),codeDO.getCode(),codeDO.getScene())).thenReturn(codeDO);
//
// // 更新手机号
// String newMobile = randomNumbers(11);
// String newCode = randomNumbers(4);
// AppUserUpdateMobileReqVO reqVO = new AppUserUpdateMobileReqVO();
// reqVO.setMobile(newMobile);
// reqVO.setCode(newCode);
// reqVO.setOldMobile(oldMobile);
// reqVO.setOldCode(oldCode);
// memberUserService.updateUserMobile(userDO.getId(),reqVO);
//
// assertEquals(memberUserService.getUser(userDO.getId()).getMobile(),newMobile);
// }
//
// // ========== 随机对象 ==========
//
// @SafeVarargs
// private static MemberUserDO randomUserDO(Consumer<MemberUserDO>... consumers) {
// Consumer<MemberUserDO> consumer = (o) -> {
// o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
// };
// return randomPojo(MemberUserDO.class, ArrayUtils.append(consumer, consumers));
// }
//
//}

2
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java

@ -123,4 +123,6 @@ public interface ErrorCodeConstants {
ErrorCode SENSITIVE_WORD_NOT_EXISTS = new ErrorCode(1002019000, "系统敏感词在所有标签中都不存在");
ErrorCode SENSITIVE_WORD_EXISTS = new ErrorCode(1002019001, "系统敏感词已在标签中存在");
ErrorCode CP_USER_NOT_EXISTS = new ErrorCode(1002021001,"微信企业成员不存在");
}

15
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/wxcp/WxCpMsgTypeEnum.java

@ -0,0 +1,15 @@
package cn.iocoder.yudao.module.system.enums.wxcp;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum WxCpMsgTypeEnum {
project,
task;
}

5
yudao-module-system/yudao-module-system-impl/pom.xml

@ -97,6 +97,11 @@
<artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-weixin</artifactId>
</dependency>
</dependencies>
</project>

100
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/CpUserController.java

@ -0,0 +1,100 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.module.system.controller.admin.CpUser.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
import cn.iocoder.yudao.module.system.convert.CpUser.CpUserConvert;
import cn.iocoder.yudao.module.system.service.CpUser.CpUserService;
@Api(tags = "管理后台 - 企业微信成员")
@RestController
@RequestMapping("/system/cp-user")
@Validated
public class CpUserController {
@Resource
private CpUserService cpUserService;
@PostMapping("/create")
@ApiOperation("创建企业微信成员")
@PreAuthorize("@ss.hasPermission('system:cp-user:create')")
public CommonResult<Long> createCpUser(@Valid @RequestBody CpUserCreateReqVO createReqVO) {
return success(cpUserService.createCpUser(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新企业微信成员")
@PreAuthorize("@ss.hasPermission('system:cp-user:update')")
public CommonResult<Boolean> updateCpUser(@Valid @RequestBody CpUserUpdateReqVO updateReqVO) {
cpUserService.updateCpUser(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@ApiOperation("删除企业微信成员")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('system:cp-user:delete')")
public CommonResult<Boolean> deleteCpUser(@RequestParam("id") Long id) {
cpUserService.deleteCpUser(id);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得企业微信成员")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('system:cp-user:query')")
public CommonResult<CpUserRespVO> getCpUser(@RequestParam("id") Long id) {
CpUserDO cpUser = cpUserService.getCpUser(id);
return success(CpUserConvert.INSTANCE.convert(cpUser));
}
@GetMapping("/list")
@ApiOperation("获得企业微信成员列表")
@ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
@PreAuthorize("@ss.hasPermission('system:cp-user:query')")
public CommonResult<List<CpUserRespVO>> getCpUserList(@RequestParam("ids") Collection<Long> ids) {
List<CpUserDO> list = cpUserService.getCpUserList(ids);
return success(CpUserConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@ApiOperation("获得企业微信成员分页")
@PreAuthorize("@ss.hasPermission('system:cp-user:query')")
public CommonResult<PageResult<CpUserRespVO>> getCpUserPage(@Valid CpUserPageReqVO pageVO) {
PageResult<CpUserDO> pageResult = cpUserService.getCpUserPage(pageVO);
return success(CpUserConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/export-excel")
@ApiOperation("导出企业微信成员 Excel")
@PreAuthorize("@ss.hasPermission('system:cp-user:export')")
@OperateLog(type = EXPORT)
public void exportCpUserExcel(@Valid CpUserExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<CpUserDO> list = cpUserService.getCpUserList(exportReqVO);
// 导出 Excel
List<CpUserExcelVO> datas = CpUserConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "企业微信成员.xls", "数据", CpUserExcelVO.class, datas);
}
}

44
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/dto/CpMessageDto.java

@ -0,0 +1,44 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser.dto;
import cn.iocoder.yudao.module.system.enums.wxcp.WxCpMsgTypeEnum;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
@Data
@ApiModel("企业微信发送推送消息")
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CpMessageDto {
private WxCpMsgTypeEnum typeEnum;
private Long id;
// 标题
private String title;
// 子标题
private String description;
private Map<String,String> contentItems;
// 是否放大第一对item
private Boolean emphasisFirstItem;
/**
* 用于微信消息推送的 - 模板ID 不一定适用于企业微信
*/
private String templateId;
/**
* 接收人userid
*/
private List<String> reciveIds;
}

49
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/vo/CpUserBaseVO.java

@ -0,0 +1,49 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
/**
* 企业微信成员 Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Data
public class CpUserBaseVO {
@ApiModelProperty(value = "用户昵称", required = true)
@NotNull(message = "用户昵称不能为空")
private String userid;
@ApiModelProperty(value = "头像", required = true)
@NotNull(message = "头像不能为空")
private String avatar;
@ApiModelProperty(value = "状态", required = true)
@NotNull(message = "状态不能为空")
private Integer status;
@ApiModelProperty(value = "手机号", required = true)
@NotNull(message = "手机号不能为空")
private String mobile;
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "部门")
private Object department;
@ApiModelProperty(value = "职位")
private String position;
@ApiModelProperty(value = "邮件")
private String email;
@ApiModelProperty(value = "企业邮件")
private String bizMail;
@ApiModelProperty(value = "工时")
private Integer workHour;
}

14
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/vo/CpUserCreateReqVO.java

@ -0,0 +1,14 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 企业微信成员创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CpUserCreateReqVO extends CpUserBaseVO {
}

53
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/vo/CpUserExcelVO.java

@ -0,0 +1,53 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import com.alibaba.excel.annotation.ExcelProperty;
/**
* 企业微信成员 Excel VO
*
* @author 系统管理员
*/
@Data
public class CpUserExcelVO {
@ExcelProperty("编号")
private Long id;
@ExcelProperty("用户昵称")
private String userid;
@ExcelProperty("头像")
private String avatar;
@ExcelProperty("状态")
private Integer status;
@ExcelProperty("手机号")
private String mobile;
@ExcelProperty("创建时间")
private Date createTime;
@ExcelProperty("姓名")
private String name;
@ExcelProperty("部门")
private Object department;
@ExcelProperty("职位")
private String position;
@ExcelProperty("邮件")
private String email;
@ExcelProperty("企业邮件")
private String bizMail;
@ApiModelProperty(value = "工时")
private Integer workHour;
}

52
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/vo/CpUserExportReqVO.java

@ -0,0 +1,52 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "管理后台 - 企业微信成员 Excel 导出 Request VO", description = "参数和 CpUserPageReqVO 是一致的")
@Data
public class CpUserExportReqVO {
@ApiModelProperty(value = "用户昵称")
private String userid;
@ApiModelProperty(value = "头像")
private String avatar;
@ApiModelProperty(value = "状态")
private Integer status;
@ApiModelProperty(value = "手机号")
private String mobile;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "部门")
private Object department;
@ApiModelProperty(value = "职位")
private String position;
@ApiModelProperty(value = "邮件")
private String email;
@ApiModelProperty(value = "企业邮件")
private String bizMail;
@ApiModelProperty(value = "工时")
private Integer workHour;
}

54
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/vo/CpUserPageReqVO.java

@ -0,0 +1,54 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("管理后台 - 企业微信成员分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CpUserPageReqVO extends PageParam {
@ApiModelProperty(value = "用户昵称")
private String userid;
@ApiModelProperty(value = "头像")
private String avatar;
@ApiModelProperty(value = "状态")
private Integer status;
@ApiModelProperty(value = "手机号")
private String mobile;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始创建时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束创建时间")
private Date endCreateTime;
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "部门")
private Object department;
@ApiModelProperty(value = "职位")
private String position;
@ApiModelProperty(value = "邮件")
private String email;
@ApiModelProperty(value = "企业邮件")
private String bizMail;
@ApiModelProperty(value = "工时")
private Integer workHour;
}

19
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/vo/CpUserRespVO.java

@ -0,0 +1,19 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
@ApiModel("管理后台 - 企业微信成员 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CpUserRespVO extends CpUserBaseVO {
@ApiModelProperty(value = "编号", required = true)
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

18
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/CpUser/vo/CpUserUpdateReqVO.java

@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.system.controller.admin.CpUser.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
@ApiModel("管理后台 - 企业微信成员更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class CpUserUpdateReqVO extends CpUserBaseVO {
@ApiModelProperty(value = "编号", required = true)
@NotNull(message = "编号不能为空")
private Long id;
}

102
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java

@ -1,17 +1,32 @@
package cn.iocoder.yudao.module.system.controller.admin.auth;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.module.system.controller.admin.auth.param.WxCpLoginDto;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserCreateReqVO;
import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
import cn.iocoder.yudao.module.system.convert.user.UserConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum;
import cn.iocoder.yudao.module.system.service.CpUser.CpUserService;
import cn.iocoder.yudao.module.system.service.auth.AdminAuthService;
import cn.iocoder.yudao.module.system.service.auth.AdminAuthServiceImpl;
import cn.iocoder.yudao.module.system.service.auth.UserSessionService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.permission.RoleService;
import cn.iocoder.yudao.module.system.service.social.SocialUserService;
@ -21,6 +36,12 @@ import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpMaJsCode2SessionResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -46,11 +67,29 @@ public class AuthController {
@Resource
private AdminUserService userService;
@Resource
private AdminUserMapper adminUserMapper;
@Resource
private RoleService roleService;
@Resource
private PermissionService permissionService;
@Resource
private SocialUserService socialUserService;
@Resource
private CpUserService cpUserService;
@Resource
private WxCpService wxCpService;
@Resource
private UserSessionService userSessionService;
@Resource
private AdminAuthServiceImpl adminAuthService;
@Resource
private UserRoleMapper userRoleMapper;
@Resource
private PasswordEncoder passwordEncoder;
@Resource
private WxMaService wxMaService;
@PostMapping("/login")
@ApiOperation("使用账号密码登录")
@ -61,6 +100,69 @@ public class AuthController {
return success(AuthLoginRespVO.builder().token(token).build());
}
@PostMapping("/loginByCp")
@ApiOperation("微信小程序登录")
public CommonResult<AuthLoginRespVO> loginByMxApp(@RequestBody @Valid WxCpLoginDto dto) throws WxErrorException {
CpUserDO cpuser;
// 企业微信登录
if ("wxcp".equals(dto.getCode())){
cpuser = cpUserService.getByUserId("test");
}else{
if (dto.getPlatform().equalsIgnoreCase("WX")){
//普通微信
WxMaJscode2SessionResult result = wxMaService.jsCode2SessionInfo(dto.getCode());
log.info("微信登录信息,{}", result);
cpuser = cpUserService.getByUserId(result.getUnionid());
if (ObjectUtil.isEmpty(cpuser)){
cpuser = cpUserService.getByUserId("test");
}
}else{
//企业微信
WxCpMaJsCode2SessionResult session = wxCpService.jsCode2Session(dto.getCode());
log.info("企业微信登录信息:{}", session);
cpuser = cpUserService.getByUserId(session.getUserId());
}
}
if (ObjectUtil.isEmpty(cpuser)){
return CommonResult.error(ErrorCodeConstants.USER_NOT_EXISTS.getCode(),"未发现绑定的企业用户,暂时无法登录,请联系管理员");
}
AdminUserDO user = userService.getUserByUsername(cpuser.getUserId());
if (ObjectUtil.isEmpty(user)){
//第一次登录 注册一个系统用户
user = AdminUserDO.builder()
.username(cpuser.getUserId())
.nickname(cpuser.getName())
.cpUserId(cpuser.getUserId())
.password((passwordEncoder.encode("123456")))
.cpUserId(cpuser.getUserId())
.build();
user.setTenantId(1L);
adminUserMapper.insert(user);
//设置默认角色 农场人员
UserRoleDO userRole = new UserRoleDO();
userRole.setUserId(user.getId());
userRole.setRoleId(112L);
userRole.setTenantId(1L);
userRoleMapper.insert(userRole);
}else {
user.setCpUserId(cpuser.getUserId());
userService.updateUser(UserConvert.INSTANCE.convertFromEntity(user));
}
LoginUser login = AuthConvert.INSTANCE.convert(user);
//权限
login.setRoleIds(adminAuthService.getUserRoleIds(login.getId()));
String token = userSessionService.createUserSession(login, getClientIP(), getUserAgent());
log.info("{}:TOKEN:::{}",user.getUsername(),token);
AuthLoginRespVO vo = AuthLoginRespVO.builder().token(token).user(cpuser).build();
return CommonResult.success(vo);
}
@GetMapping("/get-permission-info")
@ApiOperation("获取登录用户的权限信息")
public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo() {

15
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/param/WxCpLoginDto.java

@ -0,0 +1,15 @@
package cn.iocoder.yudao.module.system.controller.admin.auth.param;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
@Data
public class WxCpLoginDto {
@NotEmpty(message = "CODE不能为空")
private String code;
private String platform;
}

4
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthLoginReqVO.java

@ -18,7 +18,7 @@ import javax.validation.constraints.Pattern;
@Builder
public class AuthLoginReqVO {
@ApiModelProperty(value = "账号", required = true, example = "yudaoyuanma")
@ApiModelProperty(value = "账号", required = true, example = "zsw")
@NotEmpty(message = "登录账号不能为空")
@Length(min = 4, max = 16, message = "账号长度为 4-16 位")
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
@ -37,6 +37,8 @@ public class AuthLoginReqVO {
@NotEmpty(message = "唯一标识不能为空", groups = CodeEnableGroup.class)
private String uuid;
private String platform;
/**
* 开启验证码的 Group
*/

5
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthLoginRespVO.java

@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
@ -14,7 +16,8 @@ import lombok.NoArgsConstructor;
@Builder
public class AuthLoginRespVO {
@ApiModelProperty(value = "token", required = true, example = "yudaoyuanma")
@ApiModelProperty(value = "token", required = true, example = "zsw")
private String token;
private CpUserDO user;
}

3
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthMenuRespVO.java

@ -34,6 +34,9 @@ public class AuthMenuRespVO {
@ApiModelProperty(value = "菜单图标", example = "/menu/list", notes = "仅菜单类型为菜单或者目录时,才需要传")
private String icon;
@ApiModelProperty(value = "是否隐藏")
private Boolean hidden;
/**
* 子路由
*/

2
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/auth/AuthSocialLogin2ReqVO.java

@ -34,7 +34,7 @@ public class AuthSocialLogin2ReqVO {
@NotEmpty(message = "state 不能为空")
private String state;
@ApiModelProperty(value = "账号", required = true, example = "yudaoyuanma")
@ApiModelProperty(value = "账号", required = true, example = "zsw")
@NotEmpty(message = "登录账号不能为空")
@Length(min = 4, max = 16, message = "账号长度为 4-16 位")
@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")

2
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuBaseVO.java

@ -50,4 +50,6 @@ public class MenuBaseVO {
@NotNull(message = "状态不能为空")
private Integer status;
private Boolean hidden;
}

3
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserBaseVO.java

@ -51,4 +51,7 @@ public class UserBaseVO {
@ApiModelProperty(value = "用户头像", example = "https://www.iocoder.cn/xxx.png")
private String avatar;
@ApiModelProperty("企业微信userid")
private String cpUserId;
}

2
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java

@ -28,4 +28,6 @@ public class UserRespVO extends UserBaseVO {
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式")
private Date createTime;
@ApiModelProperty("企业微信userid")
private String cpUserId;
}

37
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/CpUser/CpUserConvert.java

@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.system.convert.CpUser;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import me.chanjar.weixin.cp.bean.WxCpUser;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import cn.iocoder.yudao.module.system.controller.admin.CpUser.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
/**
* 企业微信成员 Convert
*
* @author 系统管理员
*/
@Mapper
public interface CpUserConvert {
CpUserConvert INSTANCE = Mappers.getMapper(CpUserConvert.class);
CpUserDO convert(CpUserCreateReqVO bean);
CpUserDO convert(CpUserUpdateReqVO bean);
CpUserRespVO convert(CpUserDO bean);
List<CpUserRespVO> convertList(List<CpUserDO> list);
PageResult<CpUserRespVO> convertPage(PageResult<CpUserDO> page);
List<CpUserExcelVO> convertList02(List<CpUserDO> list);
List<CpUserDO> convertListFromWxApi(List<WxCpUser> list);
}

13
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java

@ -10,12 +10,15 @@ import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.enums.permission.MenuIdEnum;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.function.Function;
@Mapper
public interface AuthConvert {
@ -31,10 +34,18 @@ public interface AuthConvert {
}
default AuthPermissionInfoRespVO convert(AdminUserDO user, List<RoleDO> roleList, List<MenuDO> menuList) {
Set<String> permissions = CollectionUtils.convertSet(menuList, MenuDO::getPermission);
// 兼容了一个菜单多个权限。包含逗号分为多块写入
menuList.forEach(menuDO -> {
if (menuDO.getPermission().contains(",")){
permissions.remove(menuDO.getPermission());
permissions.addAll( Sets.newHashSet(Arrays.asList(menuDO.getPermission().split(","))));
}
});
return AuthPermissionInfoRespVO.builder()
.user(AuthPermissionInfoRespVO.UserVO.builder().id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).build())
.roles(CollectionUtils.convertSet(roleList, RoleDO::getCode))
.permissions(CollectionUtils.convertSet(menuList, MenuDO::getPermission))
.permissions(permissions)
.build();
}

2
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/user/UserConvert.java

@ -23,6 +23,8 @@ public interface UserConvert {
UserPageItemRespVO convert(AdminUserDO bean);
UserUpdateReqVO convertFromEntity(AdminUserDO bean);
UserPageItemRespVO.Dept convert(DeptDO bean);
AdminUserDO convert(UserCreateReqVO bean);

67
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/CpUser/CpUserDO.java

@ -0,0 +1,67 @@
package cn.iocoder.yudao.module.system.dal.dataobject.CpUser;
import lombok.*;
import java.util.*;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 企业微信成员 DO
*
* @author 系统管理员
*/
@TableName("wxcp_users")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CpUserDO extends BaseDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 用户昵称
*/
@TableField(value = "user_id")
private String userId;
/**
* 头像
*/
private String avatar;
/**
* 状态
*/
private Integer status;
/**
* 手机号
*/
private String mobile;
/**
* 姓名
*/
private String name;
/**
* 部门
*/
private Object department;
/**
* 职位
*/
private String position;
/**
* 邮件
*/
private String email;
/**
* 企业邮件
*/
private String bizMail;
private Integer workHour;
}

2
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/MenuDO.java

@ -73,4 +73,6 @@ public class MenuDO extends BaseDO {
*/
private Integer status;
private Boolean hidden;
}

4
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/UserRoleDO.java

@ -1,8 +1,10 @@
package cn.iocoder.yudao.module.system.dal.dataobject.permission;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -14,7 +16,7 @@ import lombok.EqualsAndHashCode;
@TableName("system_user_role")
@Data
@EqualsAndHashCode(callSuper = true)
public class UserRoleDO extends BaseDO {
public class UserRoleDO extends TenantBaseDO {
/**
* 自增主键

5
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/AdminUserDO.java

@ -91,4 +91,9 @@ public class AdminUserDO extends TenantBaseDO {
*/
private Date loginDate;
/**
* 企业微信用户ID
*/
private String cpUserId;
}

50
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/CpUser/CpUserMapper.java

@ -0,0 +1,50 @@
package cn.iocoder.yudao.module.system.dal.mysql.CpUser;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.system.controller.admin.CpUser.vo.*;
/**
* 企业微信成员 Mapper
*
* @author 系统管理员
*/
@Mapper
public interface CpUserMapper extends BaseMapperX<CpUserDO> {
default PageResult<CpUserDO> selectPage(CpUserPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<CpUserDO>()
.eqIfPresent(CpUserDO::getUserId, reqVO.getUserid())
.eqIfPresent(CpUserDO::getAvatar, reqVO.getAvatar())
.eqIfPresent(CpUserDO::getStatus, reqVO.getStatus())
.eqIfPresent(CpUserDO::getMobile, reqVO.getMobile())
.betweenIfPresent(CpUserDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.likeIfPresent(CpUserDO::getName, reqVO.getName())
.eqIfPresent(CpUserDO::getDepartment, reqVO.getDepartment())
.eqIfPresent(CpUserDO::getPosition, reqVO.getPosition())
.eqIfPresent(CpUserDO::getEmail, reqVO.getEmail())
.eqIfPresent(CpUserDO::getBizMail, reqVO.getBizMail())
.orderByDesc(CpUserDO::getId));
}
default List<CpUserDO> selectList(CpUserExportReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<CpUserDO>()
.eqIfPresent(CpUserDO::getUserId, reqVO.getUserid())
.eqIfPresent(CpUserDO::getAvatar, reqVO.getAvatar())
.eqIfPresent(CpUserDO::getStatus, reqVO.getStatus())
.eqIfPresent(CpUserDO::getMobile, reqVO.getMobile())
.betweenIfPresent(CpUserDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
.likeIfPresent(CpUserDO::getName, reqVO.getName())
.eqIfPresent(CpUserDO::getDepartment, reqVO.getDepartment())
.eqIfPresent(CpUserDO::getPosition, reqVO.getPosition())
.eqIfPresent(CpUserDO::getEmail, reqVO.getEmail())
.eqIfPresent(CpUserDO::getBizMail, reqVO.getBizMail())
.orderByDesc(CpUserDO::getId));
}
}

15
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictMapper.java

@ -0,0 +1,15 @@
package cn.iocoder.yudao.module.system.dal.mysql.dict;
import cn.iocoder.yudao.module.system.dict.DictModel;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface DictMapper extends BaseMapper<DictModel> {
List<DictModel> queryTableDictByKeysAndFilterSql(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("filterSql") String filterSql, @Param("codeValues") List<String> codeValues);
}

43
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dict/Dict.java

@ -0,0 +1,43 @@
package cn.iocoder.yudao.module.system.dict;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 字典注解
* @author: dangzhenghui
* @date: 2019年03月17日-下午9:37:16
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Dict {
/**
* 方法描述: 数据code
* dangzhenghui
* 2019年03月17日-下午9:37:16
*
* @return 返回类型 String
*/
String dicCode();
/**
* 方法描述: 数据Text
* dangzhenghui
* 2019年03月17日-下午9:37:16
*
* @return 返回类型 String
*/
String dicText() default "";
/**
* 方法描述: 数据字典表
* dangzhenghui
* 2019年03月17日-下午9:37:16
*
* @return 返回类型 String
*/
String dictTable() default "";
}

327
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dict/DictAspect.java

@ -0,0 +1,327 @@
package cn.iocoder.yudao.module.system.dict;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.service.dict.DictDataService;
import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* @Description: 字典aop类
* @Author: dangzhenghui
* @Date: 2019-3-17 21:50
* @Version: 1.0
*/
@Aspect
@Component
@Slf4j
public class DictAspect {
@Autowired
private DictDataService dictDataService;
@Autowired
public RedisTemplate redisTemplate;
public static final String DICT_TEXT_SUFFIX = "_dictText";
/**
* 定义切点Pointcut
*/
@Pointcut("execution(public * cn.iocoder.yudao.module.*.controller..*.*Controller.*(..))")
public void excudeService() {
}
@Around("excudeService()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
long time1=System.currentTimeMillis();
Object result = pjp.proceed();
long time2=System.currentTimeMillis();
log.debug("获取JSON数据 耗时:"+(time2-time1)+"ms");
long start=System.currentTimeMillis();
this.parseDictText(result);
long end=System.currentTimeMillis();
log.debug("注入字典到JSON数据 耗时"+(end-start)+"ms");
return result;
}
/**
* 本方法针对返回对象为Result 的IPage的分页列表数据进行动态字典注入
* 字典注入实现 通过对实体类添加注解@dict 来标识需要的字典内容,字典分为单字典code即可 table字典 code table text配合使用与原来jeecg的用法相同
* 示例为SysUser 字段为sex 添加了注解@Dict(dicCode = "sex") 会在字典服务立马查出来对应的text 然后在请求list的时候将这个字典text已字段名称加_dictText形式返回到前端
* 例输入当前返回值的就会多出一个sex_dictText字段
* {
* sex:1,
* sex_dictText:"男"
* }
* 前端直接取值sext_dictText在table里面无需再进行前端的字典转换了
* customRender:function (text) {
* if(text==1){
* return "男";
* }else if(text==2){
* return "女";
* }else{
* return text;
* }
* }
* 目前vue是这么进行字典渲染到table上的多了就很麻烦了 这个直接在服务端渲染完成前端可以直接用
* @param result
*/
private void parseDictText(Object result) {
if (result instanceof CommonResult) {
if (((CommonResult) result).getData() instanceof PageResult) {
List<JSONObject> items = new ArrayList<>();
//step.1 筛选出加了 Dict 注解的字段列表
List<Field> dictFieldList = new ArrayList<>();
// 字典数据列表, key = 字典code,value=数据列表
Map<String, List<String>> dataListMap = new HashMap<>(5);
for (Object record : ((PageResult) ((CommonResult) result).getData()).getList()) {
ObjectMapper mapper = new ObjectMapper();
// 1String json="{}";
String json = JSONUtil.toJsonStr(record);
// try {
// //解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
// json = mapper.writeValueAsString(record);
// } catch (JsonProcessingException e) {
// log.error("json解析失败"+e.getMessage(),e);
// }
//update-begin--Author:scott -- Date:20211223 ----for:【issues/3303】restcontroller返回json数据后key顺序错乱 -----
JSONObject item = JSONObject.parseObject(json, Feature.OrderedField);
//update-end--Author:scott -- Date:20211223 ----for:【issues/3303】restcontroller返回json数据后key顺序错乱 -----
//update-begin--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------
//for (Field field : record.getClass().getDeclaredFields()) {
// 遍历所有字段,把字典Code取出来,放到 map 里
for (Field field : getAllFields(record)) {
String value = item.getString(field.getName());
if (ObjectUtil.isEmpty(value)) {
continue;
}
//update-end--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------
if (field.getAnnotation(Dict.class) != null) {
if (!dictFieldList.contains(field)) {
dictFieldList.add(field);
}
String code = field.getAnnotation(Dict.class).dicCode();
String text = field.getAnnotation(Dict.class).dicText();
String table = field.getAnnotation(Dict.class).dictTable();
List<String> dataList;
String dictCode = code;
if (!StringUtils.isEmpty(table)) {
dictCode = String.format("%s,%s,%s", table, text, code);
}
dataList = dataListMap.computeIfAbsent(dictCode, k -> new ArrayList<>());
this.listAddAllDeduplicate(dataList, Arrays.asList(value.split(",")));
}
//date类型默认转换string格式化日期
// if (CommonConstant.JAVA_UTIL_DATE.equals(field.getType().getName())&&field.getAnnotation(JsonFormat.class)==null&&item.get(field.getName())!=null){
// SimpleDateFormat aDate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
// }
}
items.add(item);
}
//step.2 调用翻译方法,一次性翻译
Map<String, List<DictModel>> translText = this.translateAllDict(dataListMap);
//step.3 将翻译结果填充到返回结果里
for (JSONObject record : items) {
for (Field field : dictFieldList) {
String code = field.getAnnotation(Dict.class).dicCode();
String text = field.getAnnotation(Dict.class).dicText();
String table = field.getAnnotation(Dict.class).dictTable();
String fieldDictCode = code;
if (!StringUtils.isEmpty(table)) {
fieldDictCode = String.format("%s,%s,%s", table, text, code);
}
String value = record.getString(field.getName());
if (ObjectUtil.isNotEmpty(value)) {
List<DictModel> dictModels = translText.get(fieldDictCode);
if(dictModels==null || dictModels.size()==0){
continue;
}
String textValue = this.translDictText(dictModels, value);
log.debug(" 字典Val : " + textValue);
log.debug(" __翻译字典字段__ " + field.getName() + DICT_TEXT_SUFFIX + ": " + textValue);
// TODO-sun 测试输出,待删
log.debug(" ---- dictCode: " + fieldDictCode);
log.debug(" ---- value: " + value);
log.debug(" ----- text: " + textValue);
log.debug(" ---- dictModels: " + JSON.toJSONString(dictModels));
record.put(field.getName() + DICT_TEXT_SUFFIX, textValue);
}
}
}
((PageResult)((CommonResult) result).getData()).setList(items);
}
}
}
/**
* list 去重添加
*/
private void listAddAllDeduplicate(List<String> dataList, List<String> addList) {
// 筛选出dataList中没有的数据
List<String> filterList = addList.stream().filter(i -> !dataList.contains(i)).collect(Collectors.toList());
dataList.addAll(filterList);
}
/**
* 一次性把所有的字典都翻译了
* 1. 所有的普通数据字典的所有数据只执行一次SQL
* 2. 表字典相同的所有数据只执行一次SQL
* @param dataListMap
* @return
*/
private Map<String, List<DictModel>> translateAllDict(Map<String, List<String>> dataListMap) {
// 翻译后的字典文本,key=dictCode
Map<String, List<DictModel>> translText = new HashMap<>(5);
// 需要翻译的数据(有些可以从redis缓存中获取,就不走数据库查询)
List<String> needTranslData = new ArrayList<>();
//step.1 先通过redis中获取缓存字典数据
for (String dictCode : dataListMap.keySet()) {
List<String> dataList = dataListMap.get(dictCode);
if (dataList.size() == 0) {
continue;
}
// 表字典需要翻译的数据
List<String> needTranslDataTable = new ArrayList<>();
for (String s : dataList) {
String data = s.trim();
if (data.length() == 0) {
continue; //跳过循环
}
if (dictCode.contains(",")) {
String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, data);
if (redisTemplate.hasKey(keyString)) {
try {
String text = redisTemplate.opsForValue().get(keyString).toString();
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
list.add(new DictModel(data, text));
} catch (Exception e) {
log.warn(e.getMessage());
}
} else if (!needTranslDataTable.contains(data)) {
// 去重添加
needTranslDataTable.add(data);
}
} else {
String keyString = String.format("sys:cache:dict::%s:%s", dictCode, data);
if (redisTemplate.hasKey(keyString)) {
try {
String text = redisTemplate.opsForValue().get(keyString).toString();
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
list.add(new DictModel(data, text));
} catch (Exception e) {
log.warn(e.getMessage());
}
} else if (!needTranslData.contains(data)) {
// 去重添加
needTranslData.add(data);
}
}
}
//step.2 调用数据库翻译表字典
if (needTranslDataTable.size() > 0) {
String[] arr = dictCode.split(",");
String table = arr[0], text = arr[1], code = arr[2];
String values = String.join(",", needTranslDataTable);
log.info("translateDictFromTableByKeys.dictCode:" + dictCode);
log.info("translateDictFromTableByKeys.values:" + values);
List<DictModel> texts = dictDataService.queryTableDictTextByKeys(table,text,code,needTranslDataTable);
log.info("translateDictFromTableByKeys.result:" + texts);
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
list.addAll(texts);
// 做 redis 缓存
for (DictModel dict : texts) {
String redisKey = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, dict.getValue());
try {
// update-begin-author:taoyan date:20211012 for: 字典表翻译注解缓存未更新 issues/3061
// 保留5分钟
redisTemplate.opsForValue().set(redisKey, dict.getText(), 300, TimeUnit.SECONDS);
// update-end-author:taoyan date:20211012 for: 字典表翻译注解缓存未更新 issues/3061
} catch (Exception e) {
log.warn(e.getMessage(), e);
}
}
}
}
//step.3 调用数据库进行翻译普通字典
return translText;
}
/**
* 字典值替换文本
*
* @param dictModels
* @param values
* @return
*/
private String translDictText(List<DictModel> dictModels, String values) {
List<String> result = new ArrayList<>();
// 允许多个逗号分隔,允许传数组对象
String[] splitVal = values.split(",");
for (String val : splitVal) {
String dictText = val;
for (DictModel dict : dictModels) {
if (val.equals(dict.getValue())) {
dictText = dict.getText();
break;
}
}
result.add(dictText);
}
return String.join(",", result);
}
public static Field[] getAllFields(Object object) {
Class<?> clazz = object.getClass();
List<Field> fieldList = new ArrayList<>();
while (clazz != null) {
fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
clazz = clazz.getSuperclass();
}
Field[] fields = new Field[fieldList.size()];
fieldList.toArray(fields);
return fields;
}
}

52
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dict/DictModel.java

@ -0,0 +1,52 @@
package cn.iocoder.yudao.module.system.dict;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @Description: 字典类
* @author: jeecg-boot
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@JsonIgnoreProperties(ignoreUnknown = true)
public class DictModel implements Serializable{
private static final long serialVersionUID = 1L;
public DictModel() {
}
public DictModel(String value, String text) {
this.value = value;
this.text = text;
}
/**
* 字典value
*/
private String value;
/**
* 字典文本
*/
private String text;
/**
* 特殊用途 JgEditableTable
* @return
*/
public String getTitle() {
return this.text;
}
/**
* 特殊用途 vue3 Select组件
*/
public String getLabel() {
return this.text;
}
}

4
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java

@ -26,6 +26,10 @@ public class SecurityConfiguration {
registry.antMatchers(buildAdminApi("/system/tenant/get-id-by-name")).anonymous();
// 短信回调 API
registry.antMatchers(buildAdminApi("/system/sms/callback/**")).anonymous();
// 企业微信登录
registry.antMatchers(buildAdminApi("/system/loginByCp")).anonymous();
// 第三方登录
registry.antMatchers(buildAdminApi("/system/social-auth-redirect")).anonymous();
}
};

25
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/job/cpuser/CpWeixinUserSyncJob.java

@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.system.job.cpuser;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.module.system.service.CpUser.CpUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
@Slf4j
public class CpWeixinUserSyncJob implements JobHandler {
@Resource
private CpUserService cpUserService;
@Override
public String execute(String param) throws Exception {
TenantContextHolder.setTenantId(1L);
cpUserService.cpUserSync();
return "企业微信同步完成...";
}
}

79
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/CpUser/CpUserService.java

@ -0,0 +1,79 @@
package cn.iocoder.yudao.module.system.service.CpUser;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.system.controller.admin.CpUser.dto.CpMessageDto;
import cn.iocoder.yudao.module.system.controller.admin.CpUser.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import com.baomidou.mybatisplus.extension.service.IService;
import me.chanjar.weixin.common.error.WxErrorException;
/**
* 企业微信成员 Service 接口
*
* @author 系统管理员
*/
public interface CpUserService extends IService<CpUserDO> {
/**
* 创建企业微信成员
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createCpUser(@Valid CpUserCreateReqVO createReqVO);
/**
* 更新企业微信成员
*
* @param updateReqVO 更新信息
*/
void updateCpUser(@Valid CpUserUpdateReqVO updateReqVO);
/**
* 删除企业微信成员
*
* @param id 编号
*/
void deleteCpUser(Long id);
/**
* 获得企业微信成员
*
* @param id 编号
* @return 企业微信成员
*/
CpUserDO getCpUser(Long id);
CpUserDO getByUserId(String userId);
/**
* 获得企业微信成员列表
*
* @param ids 编号
* @return 企业微信成员列表
*/
List<CpUserDO> getCpUserList(Collection<Long> ids);
/**
* 获得企业微信成员分页
*
* @param pageReqVO 分页查询
* @return 企业微信成员分页
*/
PageResult<CpUserDO> getCpUserPage(CpUserPageReqVO pageReqVO);
/**
* 获得企业微信成员列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 企业微信成员列表
*/
List<CpUserDO> getCpUserList(CpUserExportReqVO exportReqVO);
void cpUserSync() throws WxErrorException;
void sendMessage(CpMessageDto cpMessage) throws WxErrorException;
}

164
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/CpUser/CpUserServiceImpl.java

@ -0,0 +1,164 @@
package cn.iocoder.yudao.module.system.service.CpUser;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.system.controller.admin.CpUser.dto.CpMessageDto;
import cn.iocoder.yudao.module.system.enums.wxcp.WxCpMsgTypeEnum;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpDepart;
import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.cp.bean.message.WxCpMessage;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import java.util.*;
import java.util.stream.Collectors;
import cn.iocoder.yudao.module.system.controller.admin.CpUser.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.convert.CpUser.CpUserConvert;
import cn.iocoder.yudao.module.system.dal.mysql.CpUser.CpUserMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
/**
* 企业微信成员 Service 实现类
*
* @author 系统管理员
*/
@Service
@Validated
@Slf4j
public class CpUserServiceImpl extends ServiceImpl<CpUserMapper,CpUserDO> implements CpUserService {
@Resource
private CpUserMapper cpUserMapper;
@Autowired
private WxCpService wxCpService;
@Override
public Long createCpUser(CpUserCreateReqVO createReqVO) {
// 插入
CpUserDO cpUser = CpUserConvert.INSTANCE.convert(createReqVO);
cpUserMapper.insert(cpUser);
// 返回
return cpUser.getId();
}
@Override
public void updateCpUser(CpUserUpdateReqVO updateReqVO) {
// 校验存在
this.validateCpUserExists(updateReqVO.getId());
// 更新
CpUserDO updateObj = CpUserConvert.INSTANCE.convert(updateReqVO);
cpUserMapper.updateById(updateObj);
}
@Override
public void deleteCpUser(Long id) {
// 校验存在
this.validateCpUserExists(id);
// 删除
cpUserMapper.deleteById(id);
}
private void validateCpUserExists(Long id) {
if (cpUserMapper.selectById(id) == null) {
throw exception(CP_USER_NOT_EXISTS);
}
}
@Override
public CpUserDO getCpUser(Long id) {
return cpUserMapper.selectById(id);
}
@Override
public CpUserDO getByUserId(String userId) {
return this.getOne(Wrappers.<CpUserDO>lambdaQuery().eq(CpUserDO::getUserId,userId),false);
}
@Override
public List<CpUserDO> getCpUserList(Collection<Long> ids) {
return cpUserMapper.selectBatchIds(ids);
}
@Override
public PageResult<CpUserDO> getCpUserPage(CpUserPageReqVO pageReqVO) {
return cpUserMapper.selectPage(pageReqVO);
}
@Override
public List<CpUserDO> getCpUserList(CpUserExportReqVO exportReqVO) {
return cpUserMapper.selectList(exportReqVO);
}
public void cpUserSync() throws WxErrorException {
WxCpConfigStorage config = wxCpService.getWxCpConfigStorage();
List<WxCpDepart> departList = wxCpService.getDepartmentService().list(null);
//根据部门id获取部门成员信息
//6 旭清回鄉生態農業發展公司
//35 回鄉信息技术公司
List<WxCpUser> userList = wxCpService.getUserService().listByDepartment(6L, true, 0);
userList.addAll(wxCpService.getUserService().listByDepartment(35L, true, 0));
List<CpUserDO> rs = CpUserConvert.INSTANCE.convertListFromWxApi(userList);
List<CpUserDO> nowUsers = this.cpUserMapper.selectList();
// 已经存在的员工
List<String> nowUsersIds = nowUsers.stream().map(CpUserDO::getUserId).collect(Collectors.toList());
rs.removeIf(cpUserDO -> nowUsersIds.contains(cpUserDO.getUserId()));
this.saveBatch(rs);
// 已经离职的员工 设置删除
List<String> leaveUserIds = userList.stream().filter(wxCpUser -> wxCpUser.getStatus() == 0)
.map(WxCpUser::getUserId).collect(Collectors.toList());
if (ObjectUtil.isNotEmpty(leaveUserIds)) {
List<CpUserDO> leaveUsers = this.list(Wrappers.<CpUserDO>lambdaQuery()
.in(CpUserDO::getUserId, leaveUserIds));
leaveUsers.forEach(cpUserDO -> cpUserDO.setDeleted(true));
this.updateBatchById(leaveUsers);
}
}
@Override
public void sendMessage(CpMessageDto cpMessage) throws WxErrorException {
WxCpMessage message = new WxCpMessage();
String agentId = wxCpService.getWxCpConfigStorage().getAgentId().toString();
String page = String.format("/pages/task/%sDetail/index?id=%d",
cpMessage.getTypeEnum().equals(WxCpMsgTypeEnum.project) ? "project" : "task",
cpMessage.getId());
message.setMsgType("miniprogram_notice");
message.setAppId(agentId);
message.setPage(page);
message.setTitle(cpMessage.getTitle());
message.setDescription(cpMessage.getDescription());
message.setContentItems(cpMessage.getContentItems());
message.setToUser(String.join("|", cpMessage.getReciveIds()));
wxCpService.getMessageService().send(message);
}
}

11
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java

@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*;
import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
import javax.validation.Valid;
import java.util.Set;
/**
* 管理后台的认证 Service 接口
@ -24,6 +25,16 @@ public interface AdminAuthService extends SecurityAuthFrameworkService {
*/
String login(@Valid AuthLoginReqVO reqVO, String userIp, String userAgent);
/**
* 获得 User 拥有的角色编号数组
*
* @param userId 用户编号
* @return 角色编号数组
*/
Set<Long> getUserRoleIds(Long userId);
/**
* 社交登录使用 code 授权码
*

19
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.system.service.auth;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
@ -13,9 +14,11 @@ import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthSocialBi
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthSocialLogin2ReqVO;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthSocialLoginReqVO;
import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
import cn.iocoder.yudao.module.system.service.CpUser.CpUserService;
import cn.iocoder.yudao.module.system.service.common.CaptchaService;
import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
@ -25,6 +28,7 @@ import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
@ -71,6 +75,11 @@ public class AdminAuthServiceImpl implements AdminAuthService {
@Resource
private SocialUserService socialUserService;
@Resource
private RedisTemplate redisTemplate;
@Resource
private CpUserService cpUserService;
@Resource
private Validator validator;
@ -106,13 +115,19 @@ public class AdminAuthServiceImpl implements AdminAuthService {
// 使用账号密码,进行登录
LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
CpUserDO wxUser = cpUserService.getByUserId(loginUser.getUsername());
if (ObjectUtil.isNotEmpty(wxUser)){
//将cpUserId存入 key为 系统用户id value为 cpUserId
redisTemplate.opsForValue().set("CpUserId::" + loginUser.getId(), wxUser.getId().toString());
}
// 缓存登陆用户到 Redis 中,返回 sessionId 编号
return createUserSessionAfterLoginSuccess(loginUser, LoginLogTypeEnum.LOGIN_USERNAME, userIp, userAgent);
}
private void verifyCaptcha(AuthLoginReqVO reqVO) {
// 如果验证码关闭,则不进行校验
if (!captchaService.isCaptchaEnable()) {
if (!captchaService.isCaptchaEnable() || "wxcp".equals(reqVO.getPlatform())) {
return;
}
// 校验验证码
@ -187,7 +202,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
* @param userId 用户编号
* @return 角色编号数组
*/
private Set<Long> getUserRoleIds(Long userId) {
public Set<Long> getUserRoleIds(Long userId) {
return permissionService.getUserRoleIds(userId, singleton(CommonStatusEnum.ENABLE.getStatus()));
}

3
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java

@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataCrea
import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataExportReqVO;
import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataUpdateReqVO;
import cn.iocoder.yudao.module.system.dict.DictModel;
import java.util.Collection;
import java.util.List;
@ -94,4 +95,6 @@ public interface DictDataService extends DictDataFrameworkService {
*/
void validDictDatas(String dictType, Collection<String> values);
List<DictModel> queryTableDictTextByKeys(String table, String text, String code, List<String> keys);
}

23
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java

@ -13,20 +13,20 @@ import cn.iocoder.yudao.module.system.convert.dict.DictDataConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO;
import cn.iocoder.yudao.module.system.dal.mysql.dict.DictDataMapper;
import cn.iocoder.yudao.module.system.dal.mysql.dict.DictMapper;
import cn.iocoder.yudao.module.system.dict.DictModel;
import cn.iocoder.yudao.module.system.mq.producer.dict.DictDataProducer;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableTable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
@ -40,6 +40,8 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
@Slf4j
public class DictDataServiceImpl implements DictDataService {
@Autowired
private DictMapper dictMapper;
/**
* 排序 dictType > sort
*/
@ -277,4 +279,17 @@ public class DictDataServiceImpl implements DictDataService {
});
}
@Override
public List<DictModel> queryTableDictTextByKeys(String table, String text, String code, List<String> keys) {
//update-begin-author:taoyan date:20220113 for: @dict注解支持 dicttable 设置where条件
String filterSql = null;
if(table.toLowerCase().indexOf("where")>0){
String[] arr = table.split(" (?i)where ");
table = arr[0];
filterSql = arr[1];
}
return dictMapper.queryTableDictByKeysAndFilterSql(table, text, code, filterSql, keys);
//update-end-author:taoyan date:20220113 for: @dict注解支持 dicttable 设置where条件
}
}

10
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java

@ -95,7 +95,15 @@ public class MenuServiceImpl implements MenuService {
ImmutableMultimap.Builder<String, MenuDO> permMenuCacheBuilder = ImmutableMultimap.builder();
menuList.forEach(menuDO -> {
menuCacheBuilder.put(menuDO.getId(), menuDO);
permMenuCacheBuilder.put(menuDO.getPermission(), menuDO);
// 兼容了一个菜单多个权限。包含逗号分为多块写入
if (menuDO.getPermission().contains(",")){
Arrays.asList(menuDO.getPermission().split(",")).forEach(s -> {
permMenuCacheBuilder.put(s, menuDO);
});
}else {
permMenuCacheBuilder.put(menuDO.getPermission(), menuDO);
}
});
menuCache = menuCacheBuilder.build();
permissionMenuCache = permMenuCacheBuilder.build();

13
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java

@ -27,6 +27,7 @@ import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -101,6 +102,10 @@ public class PermissionServiceImpl implements PermissionService {
@Lazy // 注入自己,所以延迟加载
private PermissionService self;
@Resource
private RedisTemplate redisTemplate;
/**
* 初始化 {@link #roleMenuCache} {@link #menuRoleCache} 缓存
*/
@ -317,6 +322,10 @@ public class PermissionServiceImpl implements PermissionService {
if (ArrayUtil.isEmpty(permissions)) {
return true;
}
//如果带角色字段 也过
if (hasAnyRoles(permissions)){
return true;
}
// 获得当前登录的角色。如果为空,说明没有权限
Set<Long> roleIds = SecurityFrameworkUtils.getLoginUserRoleIds();
@ -429,4 +438,8 @@ public class PermissionServiceImpl implements PermissionService {
UserRoleDO::getUserId);
}
public Long getCpUserIdBySystemUserId(Long userId){
return Long.valueOf(redisTemplate.opsForValue().get("CpUserId::" + userId).toString());
}
}

6
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java

@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfi
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import javax.validation.Valid;
@ -200,4 +201,9 @@ public interface AdminUserService {
*/
List<AdminUserDO> getUsersByStatus(Integer status);
/**
* 根据系统用户id获取cpUser用户
**/
List<CpUserDO> getCpUserByAdminUser(List<Long> adminUserIdList);
}

83
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.service.user;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
@ -12,13 +13,16 @@ import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfi
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*;
import cn.iocoder.yudao.module.system.convert.user.UserConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.CpUser.CpUserDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.CpUser.CpUserMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dept.PostService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
@ -29,6 +33,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
@ -42,11 +47,11 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
@Slf4j
public class AdminUserServiceImpl implements AdminUserService {
@Value("${sys.user.init-password:yudaoyuanma}")
@Value("${sys.user.init-password:zsw}")
private String userInitPassword;
@Resource
private AdminUserMapper userMapper;
private AdminUserMapper adminUserMapper;
@Resource
private DeptService deptService;
@ -61,13 +66,15 @@ public class AdminUserServiceImpl implements AdminUserService {
@Resource
private FileApi fileApi;
@Resource
private CpUserMapper cpUserMapper;
@Override
public Long createUser(UserCreateReqVO reqVO) {
// 校验账户配合
tenantService.handleTenantInfo(tenant -> {
long count = userMapper.selectCount();
long count = adminUserMapper.selectCount();
if (count >= tenant.getAccountCount()) {
throw exception(USER_COUNT_MAX, tenant.getAccountCount());
}
@ -79,7 +86,7 @@ public class AdminUserServiceImpl implements AdminUserService {
AdminUserDO user = UserConvert.INSTANCE.convert(reqVO);
user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
user.setPassword(passwordEncoder.encode(reqVO.getPassword())); // 加密密码
userMapper.insert(user);
adminUserMapper.insert(user);
return user.getId();
}
@ -90,12 +97,12 @@ public class AdminUserServiceImpl implements AdminUserService {
reqVO.getDeptId(), reqVO.getPostIds());
// 更新用户
AdminUserDO updateObj = UserConvert.INSTANCE.convert(reqVO);
userMapper.updateById(updateObj);
adminUserMapper.updateById(updateObj);
}
@Override
public void updateUserLogin(Long id, String loginIp) {
userMapper.updateById(new AdminUserDO().setId(id).setLoginIp(loginIp).setLoginDate(new Date()));
adminUserMapper.updateById(new AdminUserDO().setId(id).setLoginIp(loginIp).setLoginDate(new Date()));
}
@Override
@ -105,7 +112,7 @@ public class AdminUserServiceImpl implements AdminUserService {
this.checkEmailUnique(id, reqVO.getEmail());
this.checkMobileUnique(id, reqVO.getMobile());
// 执行更新
userMapper.updateById(UserConvert.INSTANCE.convert(reqVO).setId(id));
adminUserMapper.updateById(UserConvert.INSTANCE.convert(reqVO).setId(id));
}
@Override
@ -115,7 +122,7 @@ public class AdminUserServiceImpl implements AdminUserService {
// 执行更新
AdminUserDO updateObj = new AdminUserDO().setId(id);
updateObj.setPassword(passwordEncoder.encode(reqVO.getNewPassword())); // 加密密码
userMapper.updateById(updateObj);
adminUserMapper.updateById(updateObj);
}
@Override
@ -127,7 +134,7 @@ public class AdminUserServiceImpl implements AdminUserService {
AdminUserDO sysUserDO = new AdminUserDO();
sysUserDO.setId(id);
sysUserDO.setAvatar(avatar);
userMapper.updateById(sysUserDO);
adminUserMapper.updateById(sysUserDO);
return avatar;
}
@ -139,7 +146,7 @@ public class AdminUserServiceImpl implements AdminUserService {
AdminUserDO updateObj = new AdminUserDO();
updateObj.setId(id);
updateObj.setPassword(passwordEncoder.encode(password)); // 加密密码
userMapper.updateById(updateObj);
adminUserMapper.updateById(updateObj);
}
@Override
@ -150,7 +157,7 @@ public class AdminUserServiceImpl implements AdminUserService {
AdminUserDO updateObj = new AdminUserDO();
updateObj.setId(id);
updateObj.setStatus(status);
userMapper.updateById(updateObj);
adminUserMapper.updateById(updateObj);
}
@Override
@ -158,24 +165,24 @@ public class AdminUserServiceImpl implements AdminUserService {
// 校验用户存在
this.checkUserExists(id);
// 删除用户
userMapper.deleteById(id);
adminUserMapper.deleteById(id);
// 删除用户关联数据
permissionService.processUserDeleted(id);
}
@Override
public AdminUserDO getUserByUsername(String username) {
return userMapper.selectByUsername(username);
return adminUserMapper.selectByUsername(username);
}
@Override
public PageResult<AdminUserDO> getUserPage(UserPageReqVO reqVO) {
return userMapper.selectPage(reqVO, this.getDeptCondition(reqVO.getDeptId()));
return adminUserMapper.selectPage(reqVO, this.getDeptCondition(reqVO.getDeptId()));
}
@Override
public AdminUserDO getUser(Long id) {
return userMapper.selectById(id);
return adminUserMapper.selectById(id);
}
@Override
@ -183,7 +190,7 @@ public class AdminUserServiceImpl implements AdminUserService {
if (CollUtil.isEmpty(deptIds)) {
return Collections.emptyList();
}
return userMapper.selectListByDeptIds(deptIds);
return adminUserMapper.selectListByDeptIds(deptIds);
}
@Override
@ -193,7 +200,7 @@ public class AdminUserServiceImpl implements AdminUserService {
}
// 过滤不符合条件的
// TODO 芋艿:暂时只能内存过滤。解决方案:1、新建一个关联表;2、基于 where + 函数;3、json 字段,适合 mysql 8+ 版本
List<AdminUserDO> users = userMapper.selectList();
List<AdminUserDO> users = adminUserMapper.selectList();
users.removeIf(user -> !CollUtil.containsAny(user.getPostIds(), postIds));
return users;
}
@ -203,7 +210,7 @@ public class AdminUserServiceImpl implements AdminUserService {
if (CollUtil.isEmpty(ids)) {
return Collections.emptyList();
}
return userMapper.selectBatchIds(ids);
return adminUserMapper.selectBatchIds(ids);
}
@Override
@ -212,7 +219,7 @@ public class AdminUserServiceImpl implements AdminUserService {
return;
}
// 获得岗位信息
List<AdminUserDO> users = userMapper.selectBatchIds(ids);
List<AdminUserDO> users = adminUserMapper.selectBatchIds(ids);
Map<Long, AdminUserDO> userMap = CollectionUtils.convertMap(users, AdminUserDO::getId);
// 校验
ids.forEach(id -> {
@ -228,17 +235,17 @@ public class AdminUserServiceImpl implements AdminUserService {
@Override
public List<AdminUserDO> getUsers(UserExportReqVO reqVO) {
return userMapper.selectList(reqVO, this.getDeptCondition(reqVO.getDeptId()));
return adminUserMapper.selectList(reqVO, this.getDeptCondition(reqVO.getDeptId()));
}
@Override
public List<AdminUserDO> getUsersByNickname(String nickname) {
return userMapper.selectListByNickname(nickname);
return adminUserMapper.selectListByNickname(nickname);
}
@Override
public List<AdminUserDO> getUsersByUsername(String username) {
return userMapper.selectListByUsername(username);
return adminUserMapper.selectListByUsername(username);
}
/**
@ -278,7 +285,7 @@ public class AdminUserServiceImpl implements AdminUserService {
if (id == null) {
return;
}
AdminUserDO user = userMapper.selectById(id);
AdminUserDO user = adminUserMapper.selectById(id);
if (user == null) {
throw exception(USER_NOT_EXISTS);
}
@ -289,7 +296,7 @@ public class AdminUserServiceImpl implements AdminUserService {
if (StrUtil.isBlank(username)) {
return;
}
AdminUserDO user = userMapper.selectByUsername(username);
AdminUserDO user = adminUserMapper.selectByUsername(username);
if (user == null) {
return;
}
@ -307,7 +314,7 @@ public class AdminUserServiceImpl implements AdminUserService {
if (StrUtil.isBlank(email)) {
return;
}
AdminUserDO user = userMapper.selectByEmail(email);
AdminUserDO user = adminUserMapper.selectByEmail(email);
if (user == null) {
return;
}
@ -325,7 +332,7 @@ public class AdminUserServiceImpl implements AdminUserService {
if (StrUtil.isBlank(mobile)) {
return;
}
AdminUserDO user = userMapper.selectByMobile(mobile);
AdminUserDO user = adminUserMapper.selectByMobile(mobile);
if (user == null) {
return;
}
@ -346,7 +353,7 @@ public class AdminUserServiceImpl implements AdminUserService {
*/
@VisibleForTesting
public void checkOldPassword(Long id, String oldPassword) {
AdminUserDO user = userMapper.selectById(id);
AdminUserDO user = adminUserMapper.selectById(id);
if (user == null) {
throw exception(USER_NOT_EXISTS);
}
@ -373,9 +380,9 @@ public class AdminUserServiceImpl implements AdminUserService {
return;
}
// 判断如果不存在,在进行插入
AdminUserDO existUser = userMapper.selectByUsername(importUser.getUsername());
AdminUserDO existUser = adminUserMapper.selectByUsername(importUser.getUsername());
if (existUser == null) {
userMapper.insert(UserConvert.INSTANCE.convert(importUser)
adminUserMapper.insert(UserConvert.INSTANCE.convert(importUser)
.setPassword(passwordEncoder.encode(userInitPassword))); // 设置默认密码
respVO.getCreateUsernames().add(importUser.getUsername());
return;
@ -387,7 +394,7 @@ public class AdminUserServiceImpl implements AdminUserService {
}
AdminUserDO updateUser = UserConvert.INSTANCE.convert(importUser);
updateUser.setId(existUser.getId());
userMapper.updateById(updateUser);
adminUserMapper.updateById(updateUser);
respVO.getUpdateUsernames().add(importUser.getUsername());
});
return respVO;
@ -395,7 +402,21 @@ public class AdminUserServiceImpl implements AdminUserService {
@Override
public List<AdminUserDO> getUsersByStatus(Integer status) {
return userMapper.selectListByStatus(status);
return adminUserMapper.selectListByStatus(status);
}
public List<CpUserDO> getCpUserByAdminUser(List<Long> adminUserIdList){
List<AdminUserDO> adminUserList = adminUserMapper.selectList(Wrappers.<AdminUserDO>lambdaQuery().in(AdminUserDO::getId, adminUserIdList));
if (ObjectUtil.isEmpty(adminUserList)){
return new ArrayList<>();
}
List<String> usernameList = adminUserList.stream().map(AdminUserDO::getUsername).collect(Collectors.toList());
List<CpUserDO> cpUserList = cpUserMapper.selectList(Wrappers.<CpUserDO>lambdaQuery().in(CpUserDO::getUserId, usernameList));
if (ObjectUtil.isEmpty(cpUserList)){
return new ArrayList<>();
}
return cpUserList;
}
}

12
yudao-module-system/yudao-module-system-impl/src/main/java/resources/mapper/CpUser/CpUserMapper.xml

@ -0,0 +1,12 @@
<?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="cn.iocoder.yudao.module.system.dal.mysql.CpUser.CpUserMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>

17
yudao-module-system/yudao-module-system-impl/src/main/java/resources/mapper/dict/DictMapper.xml

@ -0,0 +1,17 @@
<?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="cn.iocoder.yudao.module.system.dal.mysql.dict.DictMapper">
<!-- 查询字典表的数据 支持设置过滤条件、设置存储值作为in查询条件 -->
<select id="queryTableDictByKeysAndFilterSql" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
select ${text} as "text", ${code} as "value" from ${table} where ${code} IN (
<foreach item="key" collection="codeValues" separator=",">
#{key}
</foreach>
)
<if test="filterSql != null and filterSql != ''">
and ${filterSql}
</if>
</select>
</mapper>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save